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
|
greater_eq
|
||||||
less_eq
|
less_eq
|
||||||
not_eq
|
not_eq
|
||||||
|
plus_eq
|
||||||
|
minus_eq
|
||||||
|
star_eq
|
||||||
|
slash_eq
|
||||||
|
increment
|
||||||
|
decrement
|
||||||
lparen
|
lparen
|
||||||
rparen
|
rparen
|
||||||
lsqparen
|
lsqparen
|
||||||
@@ -46,43 +52,7 @@ struct Token {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn str_from_toktype(type TokenType) string {
|
fn str_from_toktype(type TokenType) string {
|
||||||
return match type {
|
return type.str()
|
||||||
.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'}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn toktype_from_delimiter(delimiter string) TokenType {
|
fn toktype_from_delimiter(delimiter string) TokenType {
|
||||||
@@ -108,6 +78,12 @@ fn toktype_from_delimiter(delimiter string) TokenType {
|
|||||||
'>=' {.greater_eq}
|
'>=' {.greater_eq}
|
||||||
'<=' {.less_eq}
|
'<=' {.less_eq}
|
||||||
'!=' {.not_eq}
|
'!=' {.not_eq}
|
||||||
|
'+=' {.plus_eq}
|
||||||
|
'-=' {.minus_eq}
|
||||||
|
'*=' {.star_eq}
|
||||||
|
'/=' {.slash_eq}
|
||||||
|
'++' {.increment}
|
||||||
|
'--' {.decrement}
|
||||||
else {.unknown}
|
else {.unknown}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -175,7 +151,7 @@ fn lex(input string) ?[]Token {
|
|||||||
mut tok_str := input[right].ascii_str()
|
mut tok_str := input[right].ascii_str()
|
||||||
if right + 1 < input.len {
|
if right + 1 < input.len {
|
||||||
combined := input.substr(right, right + 2)
|
combined := input.substr(right, right + 2)
|
||||||
if combined in ['==', '>=', '<=', '!='] {
|
if combined in ['==', '>=', '<=', '!=', '+=', '-=', '*=', '/=', '++', '--'] {
|
||||||
tok_str = combined
|
tok_str = combined
|
||||||
right++
|
right++
|
||||||
}
|
}
|
||||||
|
|||||||
36
parser.v
36
parser.v
@@ -70,10 +70,15 @@ fn (mut s SymbolTable) is_in_global_scope() bool {
|
|||||||
|
|
||||||
// ------------------------------------------- Expressions
|
// ------------------------------------------- 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 VoidExpr {}
|
||||||
|
|
||||||
|
struct UnaryExpr {
|
||||||
|
ident string
|
||||||
|
op string
|
||||||
|
}
|
||||||
|
|
||||||
struct BinaryExpr {
|
struct BinaryExpr {
|
||||||
left Expr
|
left Expr
|
||||||
op string
|
op string
|
||||||
@@ -201,8 +206,8 @@ fn (mut p Parser) parse_primary() Expr {
|
|||||||
.integer {IntegerLiteral{token.text.int()}}
|
.integer {IntegerLiteral{token.text.int()}}
|
||||||
.real {RealLiteral{token.text.f32()}}
|
.real {RealLiteral{token.text.f32()}}
|
||||||
.boolean {BoolLiteral{token.text == 'true'}}
|
.boolean {BoolLiteral{token.text == 'true'}}
|
||||||
.identifier {Variable{token.text}}
|
|
||||||
.kw_fn {Function{token.text}}
|
.kw_fn {Function{token.text}}
|
||||||
|
.identifier {p.parse_ident(token.text)}
|
||||||
.type {p.parse_type(token.text)}
|
.type {p.parse_type(token.text)}
|
||||||
.lparen {p.parse_paren()}
|
.lparen {p.parse_paren()}
|
||||||
else {parse_error("Unexpected Token")}
|
else {parse_error("Unexpected Token")}
|
||||||
@@ -213,13 +218,21 @@ fn (mut p Parser) parse_expr() Expr {
|
|||||||
mut left := p.parse_primary()
|
mut left := p.parse_primary()
|
||||||
|
|
||||||
match p.peek().type {
|
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)
|
return p.parse_binary(left, p.peek().text)
|
||||||
}
|
}
|
||||||
else {return left}
|
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 {
|
fn (mut p Parser) parse_binary(left Expr, op string) BinaryExpr {
|
||||||
p.next()
|
p.next()
|
||||||
right := p.parse_expr()
|
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) {
|
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)}")
|
parse_error("Illegal operation ${op} for type ${p.get_expr_type(left)}")
|
||||||
}
|
}
|
||||||
|
p.check_binary_expr_types(binary_expr)
|
||||||
return binary_expr
|
return binary_expr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,6 +266,14 @@ fn (mut p Parser) parse_paren() ParenExpr {
|
|||||||
return ParenExpr{expr: expr}
|
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 {
|
fn (mut p Parser) get_expr_type(expr Expr) string {
|
||||||
return match expr {
|
return match expr {
|
||||||
ParenExpr {p.get_expr_type(expr.expr)}
|
ParenExpr {p.get_expr_type(expr.expr)}
|
||||||
@@ -260,11 +282,8 @@ fn (mut p Parser) get_expr_type(expr Expr) string {
|
|||||||
BoolLiteral {'bool'}
|
BoolLiteral {'bool'}
|
||||||
VoidExpr {'void'}
|
VoidExpr {'void'}
|
||||||
BinaryExpr {
|
BinaryExpr {
|
||||||
|
p.check_binary_expr_types(expr)
|
||||||
left_t := p.get_expr_type(expr.left)
|
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 ['<=', '==', '>=', '!='] {
|
if expr.op in ['<=', '==', '>=', '!='] {
|
||||||
'bool'
|
'bool'
|
||||||
} else {
|
} 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 {
|
fn (mut p Parser) is_op_valid_for_type(type string, op string) bool {
|
||||||
global := ['=', '==', '!=']
|
global := ['=', '==', '!=']
|
||||||
mut legal_ops := match type {
|
mut legal_ops := match type {
|
||||||
'int' {['+', '-', '*', '/', '<', '>', '<=', '>=',]}
|
'int', 'real' {['+', '-', '*', '/', '<', '>', '<=', '>=', '++', '--', '+=', '-=', '*=', '/=']}
|
||||||
'real' {['+', '-', '*', '/', '<', '>', '<=', '>=']}
|
|
||||||
'bool' {['=']}
|
'bool' {['=']}
|
||||||
else {[]}
|
else {[]}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user