UnaryExpr and fix type check for BynaryExpr
This commit is contained in:
52
lexer.v
52
lexer.v
@@ -26,6 +26,12 @@ enum TokenType as u8 {
|
||||
greater_eq
|
||||
less_eq
|
||||
not_eq
|
||||
plus_eq
|
||||
minus_eq
|
||||
star_eq
|
||||
slash_eq
|
||||
increment
|
||||
decrement
|
||||
lparen
|
||||
rparen
|
||||
lsqparen
|
||||
@@ -46,43 +52,7 @@ struct Token {
|
||||
}
|
||||
|
||||
fn str_from_toktype(type TokenType) string {
|
||||
return match type {
|
||||
.integer {'integer'}
|
||||
.real {'real'}
|
||||
.boolean {'boolean'}
|
||||
.kw_let {'let'}
|
||||
.type {'type'}
|
||||
.kw_if {'if'}
|
||||
.kw_else {'else'}
|
||||
.kw_for {'for'}
|
||||
.kw_break {'break'}
|
||||
.kw_fn {'fn'}
|
||||
.kw_return {'return'}
|
||||
.identifier {'identifier'}
|
||||
.eof {'EOF'}
|
||||
.unknown {'unknown'}
|
||||
.plus {'plus'}
|
||||
.minus {'minus'}
|
||||
.star {'star'}
|
||||
.slash {'slash'}
|
||||
.equals {'equals'}
|
||||
.less {'less'}
|
||||
.greater {'greater'}
|
||||
.lparen {'lparen'}
|
||||
.rparen {'rparen'}
|
||||
.lsqparen {'lsqparen'}
|
||||
.rsqparen {'rsqparen'}
|
||||
.lbracket {'lbracket'}
|
||||
.rbracket {'rbracket'}
|
||||
.dot {'dot'}
|
||||
.comma {'comma'}
|
||||
.semicolon {'semicolon'}
|
||||
.colon {'colon'}
|
||||
.eq_eq {'eq eq'}
|
||||
.greater_eq {'greater eq'}
|
||||
.less_eq {'less eq'}
|
||||
.not_eq {'not eq'}
|
||||
}
|
||||
return type.str()
|
||||
}
|
||||
|
||||
fn toktype_from_delimiter(delimiter string) TokenType {
|
||||
@@ -108,6 +78,12 @@ fn toktype_from_delimiter(delimiter string) TokenType {
|
||||
'>=' {.greater_eq}
|
||||
'<=' {.less_eq}
|
||||
'!=' {.not_eq}
|
||||
'+=' {.plus_eq}
|
||||
'-=' {.minus_eq}
|
||||
'*=' {.star_eq}
|
||||
'/=' {.slash_eq}
|
||||
'++' {.increment}
|
||||
'--' {.decrement}
|
||||
else {.unknown}
|
||||
}
|
||||
}
|
||||
@@ -175,7 +151,7 @@ fn lex(input string) ?[]Token {
|
||||
mut tok_str := input[right].ascii_str()
|
||||
if right + 1 < input.len {
|
||||
combined := input.substr(right, right + 2)
|
||||
if combined in ['==', '>=', '<=', '!='] {
|
||||
if combined in ['==', '>=', '<=', '!=', '+=', '-=', '*=', '/=', '++', '--'] {
|
||||
tok_str = combined
|
||||
right++
|
||||
}
|
||||
|
||||
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