basic One2C code gen
This commit is contained in:
76
parser.v
76
parser.v
@@ -2,6 +2,28 @@ module main
|
||||
|
||||
import term
|
||||
|
||||
// ------------------------------------------- Precedence
|
||||
|
||||
enum Precedence {
|
||||
lowest
|
||||
assignment // = , +=, -=
|
||||
comparison // ==, !=, <, >
|
||||
sum // +, -
|
||||
product // *, /
|
||||
prefix // -x, !x
|
||||
call // function()
|
||||
}
|
||||
|
||||
fn (p Parser) get_precedence(tok_type TokenType) Precedence {
|
||||
return match tok_type {
|
||||
.equals, .plus_eq, .minus_eq, .star_eq, .slash_eq { .assignment }
|
||||
.eq_eq, .not_eq, .less_eq, .greater_eq { .comparison }
|
||||
.plus, .minus { .sum }
|
||||
.star, .slash { .product }
|
||||
else { .lowest }
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------- Symbol Table
|
||||
|
||||
type SymbolInfo = VarSymbolInfo | FuncSymbolInfo
|
||||
@@ -70,7 +92,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
|
||||
|
||||
// ------------------------------------------- Expressions
|
||||
|
||||
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr
|
||||
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr
|
||||
|
||||
struct VoidExpr {}
|
||||
|
||||
@@ -118,6 +140,11 @@ struct ParenExpr {
|
||||
expr Expr
|
||||
}
|
||||
|
||||
struct PrintExpr {
|
||||
expr Expr
|
||||
type string
|
||||
}
|
||||
|
||||
// ------------------------------------------- Statements
|
||||
|
||||
type Stmt = VarDecl | ExprStmt | ReturnStmt | Block | FuncDecl
|
||||
@@ -139,7 +166,7 @@ struct ExprStmt {
|
||||
}
|
||||
|
||||
struct ReturnStmt {
|
||||
value Expr
|
||||
expr Expr
|
||||
}
|
||||
|
||||
struct Block {
|
||||
@@ -210,20 +237,20 @@ fn (mut p Parser) parse_primary() Expr {
|
||||
.identifier {p.parse_ident(token.text)}
|
||||
.type {p.parse_type(token.text)}
|
||||
.lparen {p.parse_paren()}
|
||||
.kw_print {p.parse_print()}
|
||||
else {parse_error("Unexpected Token")}
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_expr() Expr {
|
||||
mut left := p.parse_primary()
|
||||
fn (mut p Parser) parse_expr(prec Precedence) Expr {
|
||||
mut expr := p.parse_primary()
|
||||
|
||||
match p.peek().type {
|
||||
.plus, .minus, .star, .slash, .equals, .eq_eq, .not_eq, .less_eq, .greater_eq,
|
||||
.plus_eq, .minus_eq, .star_eq, .slash_eq {
|
||||
return p.parse_binary(left, p.peek().text)
|
||||
}
|
||||
else {return left}
|
||||
for int(prec) < int(p.get_precedence(p.peek().type)) {
|
||||
op_tok := p.next()
|
||||
expr = p.parse_binary(expr, op_tok.text, p.get_precedence(op_tok.type))
|
||||
}
|
||||
|
||||
return expr
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_ident(ident string) Expr {
|
||||
@@ -233,10 +260,19 @@ fn (mut p Parser) parse_ident(ident string) Expr {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_binary(left Expr, op string) BinaryExpr {
|
||||
p.next()
|
||||
right := p.parse_expr()
|
||||
fn (mut p Parser) parse_print() PrintExpr {
|
||||
p.expect(.lparen)
|
||||
expr := p.parse_expr(.lowest)
|
||||
p.expect(.rparen)
|
||||
return PrintExpr{expr: expr, type: p.get_expr_type(expr)}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_binary(left Expr, op string, prec Precedence) BinaryExpr {
|
||||
//p.next()
|
||||
right := p.parse_expr(prec)
|
||||
binary_expr := BinaryExpr{left, op, right}
|
||||
|
||||
|
||||
if !p.is_op_valid_for_type(p.get_expr_type(left), op) {
|
||||
parse_error("Illegal operation ${op} for type ${p.get_expr_type(left)}")
|
||||
}
|
||||
@@ -248,7 +284,7 @@ fn (mut p Parser) parse_type(type string) Expr {
|
||||
|
||||
if p.peek().type == .lparen {
|
||||
p.next()
|
||||
expr := p.parse_expr()
|
||||
expr := p.parse_expr(.lowest)
|
||||
p.expect(.rparen)
|
||||
|
||||
return TypeCast {
|
||||
@@ -261,7 +297,7 @@ fn (mut p Parser) parse_type(type string) Expr {
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_paren() ParenExpr {
|
||||
expr := p.parse_expr()
|
||||
expr := p.parse_expr(.lowest)
|
||||
p.expect(.rparen)
|
||||
return ParenExpr{expr: expr}
|
||||
}
|
||||
@@ -356,7 +392,7 @@ fn (mut p Parser) parse_var_decl() VarDecl {
|
||||
}
|
||||
|
||||
p.expect(.equals)
|
||||
val := p.parse_expr()
|
||||
val := p.parse_expr(.lowest)
|
||||
|
||||
if type_tok.text == 'void' {
|
||||
parse_error("Cannot declare a variable of type void")
|
||||
@@ -402,9 +438,9 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
|
||||
return_stmts := p.get_return_stmts_recursive(block)
|
||||
|
||||
for return_stmt in return_stmts {
|
||||
if p.get_expr_type(return_stmt.value) != type_tok.text {
|
||||
if p.get_expr_type(return_stmt.expr) != type_tok.text {
|
||||
parse_error("Mismatch between declared return type (${type_tok.text}) \
|
||||
and actual return type (${p.get_expr_type(return_stmt.value)})")
|
||||
and actual return type (${p.get_expr_type(return_stmt.expr)})")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -437,12 +473,12 @@ fn (mut p Parser) parse_return_stmt() ReturnStmt {
|
||||
p.expect(.semicolon)
|
||||
}
|
||||
return ReturnStmt {
|
||||
value: expr
|
||||
expr: expr
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_expr_stmt() ExprStmt {
|
||||
expr := p.parse_expr()
|
||||
expr := p.parse_expr(.lowest)
|
||||
p.expect(.semicolon)
|
||||
|
||||
return ExprStmt {
|
||||
|
||||
Reference in New Issue
Block a user