v/vlib/compiler2/parser/parser.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
}