Fix parser and implement if-elif-else

This commit is contained in:
Slendi 2024-02-08 17:09:58 +02:00
parent f51a8817aa
commit f5a72da29d
3 changed files with 65 additions and 23 deletions

View File

@ -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 == '=' {

View File

@ -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)

View File

@ -1,2 +1,9 @@
fmt.printf "%d + %d = %d File length: %d" a b a + b (io.file_size "file.txt")
fmt.println "Hello world!"
if (a == 1) {
lol
} elif (b == 2) {
kek
} else {
aaaaaaa
}