1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

compiler2: start implementing pratt style parser

This commit is contained in:
joe-conigliaro
2019-12-25 23:39:58 +11:00
committed by Alexander Medvednikov
parent ca284482cb
commit de1be1dc66
4 changed files with 180 additions and 74 deletions

View File

@ -24,7 +24,8 @@ pub fn parse_expr(text string) ast.Expr {
tok: res.tok
lit: res.lit
}
return p.expr()
// return p.expr()
return p.expr(token.lowest_prec)
}
fn (p mut Parser) next() {
@ -34,48 +35,43 @@ fn (p mut Parser) next() {
p.lit = res.lit
}
fn (p mut Parser) expr() ast.Expr {
//println('\n\nexpr()')
mut node := p.term()
for p.tok == .plus || p.tok == .minus {
op := p.tok
p.next()
node = ast.BinaryExpr {
left: node
op: op
right: p.term()
// 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}
}
}
}
return node
}
fn (p mut Parser) term() ast.Expr {
mut node := p.factor()
for p.tok == .mul || p.tok == .div || p.tok == .mod {
op := p.tok
// left binding power
for rbp < p.tok.precedence() {
tok2 := p.tok
p.next()
node = ast.BinaryExpr {
left: node
op: op
right: p.factor()
// 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 node
//return ast.BinaryExpr{}
//return ast.Expr.Binary(ast.BinaryExpr{})
return left
}
fn (p mut Parser) factor() ast.Expr {
if p.tok == .number {
val := p.lit.int()
p.next()
return ast.IntegerExpr { val: val }
} else {
println('bad factor token')
println(p.tok)
exit(1)
}
}

View File

@ -5,19 +5,37 @@ import compiler2.ast
fn test_parser() {
//expr := ast.IntegerExpr {val:10}
//expr := ast.BinaryExpr{}
// print using walk
expr := parse_expr('3 + 7')
walk(expr)
println('')
println('\n')
text_expr := [
'4 + 4',
'1 + 2 * 5',
'(2 * 3) / 2',
'3 + (7 * 6)',
'2 ^ 8 * (7 * 6)',
'(2) + (17*2-30) * (5)+2 - (8/2)*4'
]
for s in text_expr {
// print using str method
x := parse_expr(s)
println('source: $s')
println('parsed: $x')
println('===================')
}
}
fn walk(node ast.Expr) {
//println('walk()')
match node {
ast.IntegerExpr {
print(it.val)
}
ast.BinaryExpr {
print(' (')
walk(it.left)
// print('$it.op.str()')
match it.op {
.plus {
print(' + ')
@ -29,7 +47,16 @@ fn walk(node ast.Expr) {
}
walk(it.right)
print(') ')
}
else {}
ast.ScalarExpr {
walk(it.left)
print(' $it.val ')
}
ast.UnaryExpr {
walk(it.left)
print(' $it.op ')
}
else { }
}
}
}