UnaryExpr and fix type check for BynaryExpr

This commit is contained in:
uan
2026-02-04 19:11:08 +01:00
parent fc79c23b77
commit 541d3c7c7f
3 changed files with 44 additions and 48 deletions

View File

@@ -70,10 +70,15 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
// ------------------------------------------- Expressions
type Expr = VoidExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr
type Expr = VoidExpr | UnaryExpr | BinaryExpr | IntegerLiteral | RealLiteral | BoolLiteral | Variable | TypeExpr | Function | TypeCast | ParenExpr
struct VoidExpr {}
struct UnaryExpr {
ident string
op string
}
struct BinaryExpr {
left Expr
op string
@@ -201,8 +206,8 @@ fn (mut p Parser) parse_primary() Expr {
.integer {IntegerLiteral{token.text.int()}}
.real {RealLiteral{token.text.f32()}}
.boolean {BoolLiteral{token.text == 'true'}}
.identifier {Variable{token.text}}
.kw_fn {Function{token.text}}
.identifier {p.parse_ident(token.text)}
.type {p.parse_type(token.text)}
.lparen {p.parse_paren()}
else {parse_error("Unexpected Token")}
@@ -213,13 +218,21 @@ fn (mut p Parser) parse_expr() Expr {
mut left := p.parse_primary()
match p.peek().type {
.plus, .minus, .star, .slash, .equals, .eq_eq, .not_eq, .less_eq, .greater_eq {
.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}
}
}
fn (mut p Parser) parse_ident(ident string) Expr {
return match p.peek().type {
.increment, .decrement {UnaryExpr {ident: ident, op: p.next().text}}
else {Variable{ident}}
}
}
fn (mut p Parser) parse_binary(left Expr, op string) BinaryExpr {
p.next()
right := p.parse_expr()
@@ -227,6 +240,7 @@ fn (mut p Parser) parse_binary(left Expr, op string) BinaryExpr {
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)}")
}
p.check_binary_expr_types(binary_expr)
return binary_expr
}
@@ -252,6 +266,14 @@ fn (mut p Parser) parse_paren() ParenExpr {
return ParenExpr{expr: expr}
}
fn (mut p Parser) check_binary_expr_types(expr BinaryExpr) {
left_t := p.get_expr_type(expr.left)
right_t := p.get_expr_type(expr.right)
if left_t != right_t {
parse_error ('Type mismatch in expression: ${left_t} and ${right_t}')
}
}
fn (mut p Parser) get_expr_type(expr Expr) string {
return match expr {
ParenExpr {p.get_expr_type(expr.expr)}
@@ -260,11 +282,8 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
BoolLiteral {'bool'}
VoidExpr {'void'}
BinaryExpr {
p.check_binary_expr_types(expr)
left_t := p.get_expr_type(expr.left)
right_t := p.get_expr_type(expr.right)
if left_t != right_t {
parse_error ('Type mismatch in expression: ${left_t} and ${right_t}')
}
if expr.op in ['<=', '==', '>=', '!='] {
'bool'
} else {
@@ -288,8 +307,7 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
fn (mut p Parser) is_op_valid_for_type(type string, op string) bool {
global := ['=', '==', '!=']
mut legal_ops := match type {
'int' {['+', '-', '*', '/', '<', '>', '<=', '>=',]}
'real' {['+', '-', '*', '/', '<', '>', '<=', '>=']}
'int', 'real' {['+', '-', '*', '/', '<', '>', '<=', '>=', '++', '--', '+=', '-=', '*=', '/=']}
'bool' {['=']}
else {[]}
}