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(.Divide, crange)
|
||||||
case '%': ret = token_create(.Modulo, crange)
|
case '%': ret = token_create(.Modulo, crange)
|
||||||
case '`': ret = token_create(.Exponent, 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 '!':
|
case '!':
|
||||||
ret = token_create(.Not, crange)
|
ret = token_create(.Not, crange)
|
||||||
if lexer.next == '=' {
|
if lexer.next == '=' {
|
||||||
|
73
parser.odin
73
parser.odin
@ -98,26 +98,7 @@ parser_parse_if_statement :: proc(parser: ^Parser) -> ^Node {
|
|||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
parser_parse_expression :: proc(parser: ^Parser) -> ^Node {
|
parser_parse_expression :: proc(parser: ^Parser) -> ^Node {
|
||||||
return parser_parse_arrow(parser)
|
return parser_parse_assignment(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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
@ -135,7 +116,42 @@ parser_parse_binary_expression :: proc(parser: ^Parser, kinds: []TokenKind, next
|
|||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
parser_parse_assignment :: proc(parser: ^Parser) -> ^Node {
|
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")
|
@(private = "file")
|
||||||
@ -215,6 +231,19 @@ parser_parse_prefix :: proc(parser: ^Parser) -> ^Node {
|
|||||||
return parser_parse_factor(parser)
|
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")
|
@(private = "file")
|
||||||
parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
|
parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
|
||||||
ret = nil
|
ret = nil
|
||||||
@ -243,7 +272,7 @@ parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) {
|
|||||||
prev := parser.can_be_function
|
prev := parser.can_be_function
|
||||||
parser.can_be_function = false
|
parser.can_be_function = false
|
||||||
args : [dynamic]^Node
|
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))
|
append(&args, parser_parse_expression(parser))
|
||||||
}
|
}
|
||||||
ret = node_create_function_call(ret.range, ret, args)
|
ret = node_create_function_call(ret.range, ret, args)
|
||||||
|
7
test.cat
7
test.cat
@ -1,2 +1,9 @@
|
|||||||
fmt.printf "%d + %d = %d File length: %d" a b a + b (io.file_size "file.txt")
|
fmt.printf "%d + %d = %d File length: %d" a b a + b (io.file_size "file.txt")
|
||||||
fmt.println "Hello world!"
|
fmt.println "Hello world!"
|
||||||
|
if (a == 1) {
|
||||||
|
lol
|
||||||
|
} elif (b == 2) {
|
||||||
|
kek
|
||||||
|
} else {
|
||||||
|
aaaaaaa
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user