2019-12-22 04:34:37 +03:00
|
|
|
// 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
|
2019-12-26 13:27:35 +03:00
|
|
|
compiler2.table
|
2019-12-22 04:34:37 +03:00
|
|
|
)
|
|
|
|
|
|
|
|
struct Parser {
|
|
|
|
scanner &scanner.Scanner
|
|
|
|
mut:
|
2019-12-24 20:54:43 +03:00
|
|
|
tok token.Token
|
|
|
|
lit string
|
2019-12-26 13:27:35 +03:00
|
|
|
//vars []string
|
|
|
|
table &table.Table
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
|
|
|
|
2019-12-26 13:27:35 +03:00
|
|
|
pub fn parse_expr(text string, table &table.Table) ast.Expr {
|
2019-12-22 04:34:37 +03:00
|
|
|
mut s := scanner.new_scanner(text)
|
|
|
|
res := s.scan()
|
|
|
|
mut p := Parser{
|
|
|
|
scanner: s
|
|
|
|
tok: res.tok
|
|
|
|
lit: res.lit
|
2019-12-26 13:27:35 +03:00
|
|
|
table: table
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
expr,_ := p.expr(token.lowest_prec)
|
|
|
|
return expr
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
|
|
|
|
2019-12-26 13:27:35 +03:00
|
|
|
pub fn parse_file(text string, table &table.Table) ast.Program {
|
|
|
|
s := scanner.new_scanner(text)
|
|
|
|
mut exprs := []ast.Expr
|
|
|
|
mut p := Parser{
|
|
|
|
scanner: s
|
|
|
|
//tok: res.tok
|
|
|
|
//lit: res.lit
|
|
|
|
table: table
|
|
|
|
}
|
|
|
|
p.next()
|
|
|
|
for {
|
|
|
|
//res := s.scan()
|
|
|
|
if p.tok == .eof {
|
|
|
|
break
|
|
|
|
}
|
|
|
|
println('expr at ' + p.tok.str())
|
|
|
|
expr,_ := p.expr(token.lowest_prec)
|
|
|
|
exprs << expr
|
|
|
|
p.next()
|
|
|
|
}
|
|
|
|
println('nr exprs = $exprs.len')
|
|
|
|
println(exprs[0])
|
|
|
|
return ast.Program{exprs}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
2019-12-24 20:54:43 +03:00
|
|
|
pub fn parse_stmt(text string) ast.Stmt {
|
|
|
|
mut s := scanner.new_scanner(text)
|
|
|
|
res := s.scan()
|
|
|
|
mut p := Parser{
|
|
|
|
scanner: s
|
|
|
|
tok: res.tok
|
|
|
|
lit: res.lit
|
|
|
|
}
|
|
|
|
return p.stmt()
|
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
*/
|
|
|
|
|
2019-12-24 20:54:43 +03:00
|
|
|
|
2019-12-22 04:34:37 +03:00
|
|
|
fn (p mut Parser) next() {
|
|
|
|
res := p.scanner.scan()
|
|
|
|
p.tok = res.tok
|
2019-12-24 20:54:43 +03:00
|
|
|
// println(p.tok.str())
|
2019-12-22 04:34:37 +03:00
|
|
|
p.lit = res.lit
|
|
|
|
}
|
|
|
|
|
2019-12-25 15:39:58 +03:00
|
|
|
// Implementation of Pratt Precedence
|
2019-12-26 13:27:35 +03:00
|
|
|
pub fn (p mut Parser) expr(rbp int) (ast.Expr,ast.Type) {
|
2019-12-25 15:39:58 +03:00
|
|
|
// null denotation (prefix)
|
|
|
|
tok := p.tok
|
|
|
|
lit := p.lit
|
2019-12-26 13:27:35 +03:00
|
|
|
|
|
|
|
if p.tok == .name {
|
|
|
|
name := p.lit
|
|
|
|
p.next()
|
|
|
|
if p.tok == .decl_assign {
|
|
|
|
p.next()
|
|
|
|
mut node := ast.Expr{}
|
|
|
|
expr,t :=p.expr(token.lowest_prec)
|
|
|
|
if name in p.table.names {
|
|
|
|
verror('redefinition of `$name`')
|
|
|
|
}
|
|
|
|
p.table.names << name
|
|
|
|
println(p.table.names)
|
|
|
|
println('added $name')
|
|
|
|
// TODO can't return VarDecl{}
|
|
|
|
node = ast.VarDecl{
|
|
|
|
name: name
|
|
|
|
expr: expr//p.expr(token.lowest_prec)
|
|
|
|
typ: t
|
|
|
|
}//, ast.void_type
|
|
|
|
return node, ast.void_type
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
p.next()
|
|
|
|
}
|
2019-12-26 12:02:38 +03:00
|
|
|
mut node := ast.Expr{}
|
2019-12-26 13:27:35 +03:00
|
|
|
mut typ := ast.void_type
|
2019-12-25 15:39:58 +03:00
|
|
|
match tok {
|
|
|
|
.lpar {
|
2019-12-26 13:27:35 +03:00
|
|
|
node,typ = p.expr(0)
|
2019-12-25 15:39:58 +03:00
|
|
|
if p.tok != .rpar {
|
2019-12-24 20:54:43 +03:00
|
|
|
panic('Parse Error: expected )')
|
2019-12-25 15:39:58 +03:00
|
|
|
}
|
|
|
|
p.next()
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
2019-12-25 15:39:58 +03:00
|
|
|
else {
|
|
|
|
// TODO: fix bug. note odd conditon instead of else if (same below)
|
|
|
|
if tok.is_scalar() {
|
2019-12-26 13:21:41 +03:00
|
|
|
if tok == .str {
|
2019-12-26 13:27:35 +03:00
|
|
|
node = ast.StringLiteral{
|
2019-12-26 13:21:41 +03:00
|
|
|
val: lit
|
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
typ = ast.string_type
|
|
|
|
}
|
|
|
|
if tok == .number {
|
|
|
|
node = ast.IntegerLiteral{
|
2019-12-26 13:21:41 +03:00
|
|
|
val: lit.int()
|
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
typ = ast.int_type
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
// else {
|
|
|
|
// verror('bad scalar token')
|
|
|
|
// }
|
2019-12-25 15:39:58 +03:00
|
|
|
}
|
|
|
|
if !tok.is_scalar() && tok.is_unary() {
|
2019-12-26 13:27:35 +03:00
|
|
|
expr,_ := p.expr(token.highest_prec)
|
2019-12-24 20:54:43 +03:00
|
|
|
node = ast.UnaryExpr{
|
2019-12-26 13:27:35 +03:00
|
|
|
// left: p.expr(token.highest_prec)
|
|
|
|
left: expr
|
2019-12-24 20:54:43 +03:00
|
|
|
op: tok
|
|
|
|
}
|
2019-12-25 15:39:58 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
}
|
|
|
|
}
|
2019-12-25 15:39:58 +03:00
|
|
|
// left binding power
|
|
|
|
for rbp < p.tok.precedence() {
|
|
|
|
tok2 := p.tok
|
2019-12-22 04:34:37 +03:00
|
|
|
p.next()
|
2019-12-26 13:27:35 +03:00
|
|
|
//mut t1 := ast.Type{}
|
|
|
|
mut t2 := ast.Type{}
|
|
|
|
//mut q := false
|
2019-12-25 15:39:58 +03:00
|
|
|
// left denotation (infix)
|
|
|
|
if tok2.is_right_assoc() {
|
2019-12-26 13:27:35 +03:00
|
|
|
//q = true
|
|
|
|
mut expr := ast.Expr{}
|
|
|
|
expr,t2 = p.expr(tok2.precedence() - 1)
|
2019-12-24 20:54:43 +03:00
|
|
|
node = ast.BinaryExpr{
|
|
|
|
left: node
|
2019-12-26 13:27:35 +03:00
|
|
|
//left_type: t1
|
2019-12-24 20:54:43 +03:00
|
|
|
op: tok2
|
2019-12-26 13:27:35 +03:00
|
|
|
// right: p.expr(tok2.precedence() - 1)
|
|
|
|
|
|
|
|
right: expr
|
|
|
|
|
|
|
|
}
|
|
|
|
if typ.name != t2.name {
|
|
|
|
println('bad types $typ.name $t2.name')
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
2019-12-25 15:39:58 +03:00
|
|
|
}
|
|
|
|
if !tok2.is_right_assoc() && tok2.is_left_assoc() {
|
2019-12-26 13:27:35 +03:00
|
|
|
mut expr := ast.Expr{}
|
|
|
|
expr,t2 = p.expr(tok2.precedence())
|
2019-12-24 20:54:43 +03:00
|
|
|
node = ast.BinaryExpr{
|
|
|
|
left: node
|
|
|
|
op: tok2
|
2019-12-26 13:27:35 +03:00
|
|
|
right: expr
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
2019-12-25 15:39:58 +03:00
|
|
|
}
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
return node,typ
|
2019-12-24 20:54:43 +03:00
|
|
|
}
|
|
|
|
|
2019-12-26 13:27:35 +03:00
|
|
|
/*
|
2019-12-24 20:54:43 +03:00
|
|
|
fn (p mut Parser) stmt() ast.Stmt {
|
|
|
|
if p.tok == .name {
|
|
|
|
name := p.lit
|
|
|
|
p.next()
|
|
|
|
if p.tok == .decl_assign {
|
|
|
|
p.next()
|
|
|
|
return ast.VarDecl{
|
|
|
|
name: name
|
|
|
|
expr: p.expr(token.lowest_prec)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
|
|
match node {
|
|
|
|
Ident {
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
|
2019-12-26 12:02:38 +03:00
|
|
|
return ast.VarDecl{}
|
2019-12-22 04:34:37 +03:00
|
|
|
}
|
2019-12-26 13:27:35 +03:00
|
|
|
*/
|
|
|
|
|
2019-12-26 13:21:41 +03:00
|
|
|
|
|
|
|
fn verror(s string) {
|
|
|
|
println(s)
|
|
|
|
exit(1)
|
|
|
|
}
|