UnaryExpr and fix type check for BynaryExpr
This commit is contained in:
36
parser.v
36
parser.v
@@ -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 {[]}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user