way better prints yay
This commit is contained in:
59
parser.v
59
parser.v
@@ -12,6 +12,7 @@ enum Precedence {
|
||||
product // *, /
|
||||
prefix // -x, !x
|
||||
call // function()
|
||||
access // .
|
||||
}
|
||||
|
||||
fn (p Parser) get_precedence(tok_type TokenType) Precedence {
|
||||
@@ -20,6 +21,7 @@ fn (p Parser) get_precedence(tok_type TokenType) Precedence {
|
||||
.eq_eq, .not_eq, .less_eq, .greater_eq { .comparison }
|
||||
.plus, .minus { .sum }
|
||||
.star, .slash { .product }
|
||||
.dot { .access }
|
||||
else { .lowest }
|
||||
}
|
||||
}
|
||||
@@ -39,6 +41,7 @@ struct FuncSymbolInfo {
|
||||
|
||||
struct ClassSymbolInfo {
|
||||
name string
|
||||
members_info map[string]VarSymbolInfo
|
||||
}
|
||||
|
||||
struct SymbolTable {
|
||||
@@ -90,8 +93,12 @@ fn (mut s SymbolTable) lookup_func(name string) ?FuncSymbolInfo {
|
||||
return none
|
||||
}
|
||||
|
||||
fn (mut s SymbolTable) define_class(name string) {
|
||||
s.structs[name] = ClassSymbolInfo{name: name}
|
||||
fn (mut s SymbolTable) define_class(name string, members []ClassMember) {
|
||||
mut members_info := map[string]VarSymbolInfo{}
|
||||
for member in members {
|
||||
members_info[member.name] = VarSymbolInfo{member.type}
|
||||
}
|
||||
s.structs[name] = ClassSymbolInfo{name: name, members_info: members_info}
|
||||
}
|
||||
|
||||
fn (mut s SymbolTable) lookup_class(name string) ?ClassSymbolInfo {
|
||||
@@ -108,7 +115,7 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
|
||||
|
||||
// ------------------------------------------- Expressions
|
||||
|
||||
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation
|
||||
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr | PrintExpr | FnCall | ClassMember | ClassInstantiation | MemberAccess
|
||||
|
||||
struct VoidExpr {}
|
||||
|
||||
@@ -148,6 +155,11 @@ struct ClassMember {
|
||||
type string
|
||||
}
|
||||
|
||||
struct MemberAccess {
|
||||
from Expr
|
||||
member string
|
||||
}
|
||||
|
||||
struct ClassInstantiation {
|
||||
name string
|
||||
member_values []Expr
|
||||
@@ -295,9 +307,16 @@ fn (mut p Parser) parse_primary() Expr {
|
||||
fn (mut p Parser) parse_expr(prec Precedence) Expr {
|
||||
mut expr := p.parse_primary()
|
||||
|
||||
|
||||
|
||||
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))
|
||||
|
||||
if op_tok.type == .dot {
|
||||
expr = p.parse_member_access(expr)
|
||||
} else {
|
||||
expr = p.parse_binary(expr, op_tok.text, p.get_precedence(op_tok.type))
|
||||
}
|
||||
}
|
||||
|
||||
return expr
|
||||
@@ -307,7 +326,7 @@ fn (mut p Parser) parse_ident(ident string) Expr {
|
||||
if p.symbols.lookup_class(ident) != none {
|
||||
return match p.peek().type {
|
||||
.lbracket {p.parse_class_inst(ident)}
|
||||
else {p.parse_type('struct ${ident}')}
|
||||
else {p.parse_type('${ident}')}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -322,6 +341,12 @@ fn (mut p Parser) parse_ident(ident string) Expr {
|
||||
}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_member_access(from Expr) MemberAccess {
|
||||
member_tok := p.next()
|
||||
if member_tok.type != .identifier {parse_error("Expected identifier after member access")}
|
||||
return MemberAccess {from: from, member: member_tok.text}
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_class_member(name string) ClassMember {
|
||||
p.expect(.identifier)
|
||||
|
||||
@@ -330,7 +355,7 @@ fn (mut p Parser) parse_class_member(name string) ClassMember {
|
||||
.type {type_tok.text}
|
||||
.identifier {
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
'struct ${type_tok.text}'
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected type after class member ${name} in declaration, got ${p.peek().type}")}
|
||||
}
|
||||
@@ -448,7 +473,6 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
|
||||
}
|
||||
}
|
||||
Variable {
|
||||
p.dump_stmt()
|
||||
info := p.symbols.lookup_var(expr.name) or {
|
||||
parse_error("Undefined variable ${expr.name}")
|
||||
}
|
||||
@@ -459,6 +483,15 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
|
||||
fninfo := p.symbols.lookup_func(expr.name) or {parse_error("Tried to call undefined function ${expr.name}")}
|
||||
fninfo.type
|
||||
}
|
||||
MemberAccess {
|
||||
mut type_from := p.get_expr_type(expr.from)
|
||||
classinfo := p.symbols.lookup_class(type_from)or{parse_error("Non-existant class ${type_from}")}
|
||||
if expr.member in classinfo.members_info {
|
||||
classinfo.members_info[expr.member].type
|
||||
} else {
|
||||
parse_error("Undefined class member ${expr.member}")
|
||||
}
|
||||
}
|
||||
ClassInstantiation {expr.name}
|
||||
else {"Tried getting type of unexpected Expr"}
|
||||
}
|
||||
@@ -515,7 +548,7 @@ fn (mut p Parser) parse_var_decl(is_const bool) VarDecl {
|
||||
.type {type_tok.text}
|
||||
.identifier {
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
'struct ${type_tok.text}'
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected variable type after name when declaring ${name_tok.text}")}
|
||||
}
|
||||
@@ -569,7 +602,7 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
|
||||
.type {type_tok.text}
|
||||
.identifier {
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
'struct ${type_tok.text}'
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected argument type after name when declaring ${p_name}")}
|
||||
}
|
||||
@@ -594,7 +627,7 @@ fn (mut p Parser) parse_func_decl() FuncDecl {
|
||||
.type {type_tok.text}
|
||||
.identifier {
|
||||
p.expect_ident_is_class(type_tok.text)
|
||||
'struct ${type_tok.text}'
|
||||
type_tok.text
|
||||
}
|
||||
else{parse_error("Expected function return type after name when declaring ${name_tok.text}")}
|
||||
}
|
||||
@@ -632,7 +665,7 @@ fn (mut p Parser) parse_class() ClassDecl {
|
||||
members << p.parse_class_member(p.peek().text)
|
||||
}
|
||||
p.expect(.rbracket)
|
||||
p.symbols.define_class(name)
|
||||
p.symbols.define_class(name, members)
|
||||
return ClassDecl{name: name, members: members}
|
||||
}
|
||||
|
||||
@@ -697,7 +730,7 @@ fn (mut p Parser) parse_block(no_scope bool) Block {
|
||||
|
||||
}
|
||||
|
||||
fn (mut p Parser) parse_program() []Stmt {
|
||||
fn (mut p Parser) parse_program() ([]Stmt, SymbolTable) {
|
||||
p.symbols.variable_scopes << map[string]VarSymbolInfo{}
|
||||
for p.peek().type != .eof {
|
||||
p.statements << p.parse_statement()
|
||||
@@ -706,7 +739,7 @@ fn (mut p Parser) parse_program() []Stmt {
|
||||
$if debug {
|
||||
dump(p.symbols.functions)
|
||||
}
|
||||
return p.statements
|
||||
return p.statements, p.symbols
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user