78 lines
1.6 KiB
V
78 lines
1.6 KiB
V
// Copyright (c) 2019 Alexander Medvednikov. All rights reserved.
|
|
// Use of this source code is governed by an MIT license
|
|
// that can be found in the LICENSE file.
|
|
module parser
|
|
|
|
import (
|
|
compiler2.scanner
|
|
compiler2.ast
|
|
compiler2.token
|
|
)
|
|
|
|
struct Parser {
|
|
scanner &scanner.Scanner
|
|
mut:
|
|
tok token.Token
|
|
lit string
|
|
}
|
|
|
|
pub fn parse_expr(text string) ast.Expr {
|
|
mut s := scanner.new_scanner(text)
|
|
res := s.scan()
|
|
mut p := Parser{
|
|
scanner: s
|
|
tok: res.tok
|
|
lit: res.lit
|
|
}
|
|
// return p.expr()
|
|
return p.expr(token.lowest_prec)
|
|
}
|
|
|
|
fn (p mut Parser) next() {
|
|
res := p.scanner.scan()
|
|
p.tok = res.tok
|
|
//println(p.tok.str())
|
|
p.lit = res.lit
|
|
}
|
|
|
|
// Implementation of Pratt Precedence
|
|
pub fn (p mut Parser) expr(rbp int) ast.Expr {
|
|
// null denotation (prefix)
|
|
tok := p.tok
|
|
lit := p.lit
|
|
p.next()
|
|
mut left := ast.Expr{}
|
|
match tok {
|
|
.lpar {
|
|
left = p.expr(0)
|
|
if p.tok != .rpar {
|
|
panic("Parse Error: expected )")
|
|
}
|
|
p.next()
|
|
}
|
|
else {
|
|
// TODO: fix bug. note odd conditon instead of else if (same below)
|
|
if tok.is_scalar() {
|
|
left = ast.ScalarExpr{val: lit, typ: tok}
|
|
}
|
|
if !tok.is_scalar() && tok.is_unary() {
|
|
left = ast.UnaryExpr{left: p.expr(token.highest_prec), op: tok}
|
|
}
|
|
}
|
|
}
|
|
|
|
// left binding power
|
|
for rbp < p.tok.precedence() {
|
|
tok2 := p.tok
|
|
p.next()
|
|
// left denotation (infix)
|
|
if tok2.is_right_assoc() {
|
|
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence() - 1)}
|
|
}
|
|
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
|
left = ast.BinaryExpr{left: left, op: tok2, right: p.expr(tok2.precedence())}
|
|
}
|
|
}
|
|
return left
|
|
}
|