Fix parser and implement if-elif-else
This commit is contained in:
parent
f51a8817aa
commit
f5a72da29d
@ -131,7 +131,13 @@ lexer_next :: proc(lexer: ^Lexer) -> (ret: Token) {
|
||||
case '/': ret = token_create(.Divide, crange)
|
||||
case '%': ret = token_create(.Modulo, crange)
|
||||
case '`': ret = token_create(.Exponent, crange)
|
||||
case '=': ret = token_create(.Assign, crange)
|
||||
case '=':
|
||||
ret = token_create(.Assign, crange)
|
||||
if lexer.next == '=' {
|
||||
lexer_advance(lexer)
|
||||
crange.end = lexer.position
|
||||
ret = token_create(.Equals, crange)
|
||||
}
|
||||
case '!':
|
||||
ret = token_create(.Not, crange)
|
||||
if lexer.next == '=' {
|
||||
|
73
parser.odin
73
parser.odin
@ -98,26 +98,7 @@ parser_parse_if_statement :: proc(parser: ^Parser) -> ^Node {
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_expression :: proc(parser: ^Parser) -> ^Node {
|
||||
return parser_parse_arrow(parser)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_arrow :: proc(parser: ^Parser) -> ^Node {
|
||||
// Basically, a -> b is the same as function_call(b, {a})
|
||||
lhs := parser_parse_assignment(parser)
|
||||
for accept(parser, .Arrow) {
|
||||
rhs := parser_parse_assignment(parser)
|
||||
if rhs.kind != .FunctionCall && rhs.kind != .Identifier && rhs.kind != .FieldAccess && rhs.kind != .IndexAccess {
|
||||
append(&g_message_list, message_create(.Error, fmt.aprintf("Expected function call, got {} at {}", rhs.kind, "TODO"), rhs.range))
|
||||
return lhs
|
||||
}
|
||||
if rhs.kind != .FunctionCall {
|
||||
rhs = node_create_function_call(rhs.range, rhs, nil)
|
||||
}
|
||||
inject_at(&rhs.children, 1, lhs)
|
||||
lhs = rhs
|
||||
}
|
||||
return lhs
|
||||
return parser_parse_assignment(parser)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
@ -135,7 +116,42 @@ parser_parse_binary_expression :: proc(parser: ^Parser, kinds: []TokenKind, next
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_assignment :: proc(parser: ^Parser) -> ^Node {
|
||||
return parser_parse_binary_expression(parser, {.Assign}, parser_parse_addition)
|
||||
return parser_parse_binary_expression(parser, {.Assign}, parser_parse_arrow)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_arrow :: proc(parser: ^Parser) -> ^Node {
|
||||
// Basically, a -> b is the same as function_call(b, {a})
|
||||
lhs := parser_parse_equality(parser)
|
||||
for accept(parser, .Arrow) {
|
||||
rhs := parser_parse_assignment(parser)
|
||||
if rhs.kind != .FunctionCall &&
|
||||
rhs.kind != .Identifier &&
|
||||
rhs.kind != .FieldAccess &&
|
||||
rhs.kind != .IndexAccess {
|
||||
append(&g_message_list, message_create(
|
||||
.Error,
|
||||
fmt.aprintf("Expected function call, got {} at {}", rhs.kind, "TODO"),
|
||||
rhs.range))
|
||||
return lhs
|
||||
}
|
||||
if rhs.kind != .FunctionCall {
|
||||
rhs = node_create_function_call(rhs.range, rhs, nil)
|
||||
}
|
||||
inject_at(&rhs.children, 1, lhs)
|
||||
lhs = rhs
|
||||
}
|
||||
return lhs
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_equality :: proc(parser: ^Parser) -> ^Node {
|
||||
return parser_parse_binary_expression(parser, {.Equals, .NotEquals}, parser_parse_comparison)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_comparison :: proc(parser: ^Parser) -> ^Node {
|
||||
return parser_parse_binary_expression(parser, {.LessThan, .LessThanOrEqual, .GreaterThan, .GreaterThanOrEqual}, parser_parse_addition)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
@ -215,6 +231,19 @@ parser_parse_prefix :: proc(parser: ^Parser) -> ^Node {
|
||||
return parser_parse_factor(parser)
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_is_factor_token_or_prefix :: proc(tt: TokenKind) -> bool {
|
||||
#partial switch tt {
|
||||
case .Identifier, .Integer, .Float, .String, .Character, .OpenParen:
|
||||
return true
|
||||
case .Not, .Subtract, .BitwiseNot, .Increment, .Decrement:
|
||||
// Assuming these can be used as prefixes in unary operations
|
||||
return true
|
||||
case:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
@(private = "file")
|
||||
parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
|
||||
ret = nil
|
||||
@ -243,7 +272,7 @@ parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
|
||||
prev := parser.can_be_function
|
||||
parser.can_be_function = false
|
||||
args : [dynamic]^Node
|
||||
for parser.tok.kind != .CloseParen && parser.tok.kind != .Semicolon && parser.tok.kind != .Arrow && parser.tok.kind != .EOF {
|
||||
for parser.tok.kind != .CloseParen && parser.tok.kind != .Semicolon && parser.tok.kind != .Arrow && parser.tok.kind != .EOF && parser_is_factor_token_or_prefix(parser.tok.kind) {
|
||||
append(&args, parser_parse_expression(parser))
|
||||
}
|
||||
ret = node_create_function_call(ret.range, ret, args)
|
||||
|
Loading…
x
Reference in New Issue
Block a user