package main import "core:fmt" Parser :: struct { lexer: ^Lexer, tok, next: Token, can_be_function: bool, } parser_create :: proc(lexer: ^Lexer) -> (ret: Parser) { ret = { lexer = lexer, can_be_function = true, } parser_next(&ret) parser_next(&ret) return } @(private = "file") parser_next :: proc(parser: ^Parser) { parser.tok = parser.next parser.next = lexer_next(parser.lexer) } @(private = "file") accept :: proc(parser: ^Parser, tok: TokenKind) -> bool { if parser.tok.kind == tok { parser_next(parser) return true } return false } @(private = "file") expect :: proc(parser: ^Parser, tok: TokenKind) { if !accept(parser, tok) { append(&g_message_list, message_create(.Error, fmt.aprintf("Expected {}, got {} at {}", tok, parser.tok.kind, "TODO"), parser.tok.range)) } } parser_parse :: proc(parser: ^Parser) -> (ret: ^Node) { ret = parser_parse_block(parser, .EOF) return } @(private = "file") parser_parse_block :: proc(parser: ^Parser, end: TokenKind) -> (ret: ^Node) { range := parser.tok.range statements : [dynamic]^Node for parser.tok.kind != end && parser.tok.kind != .EOF { append(&statements, parser_parse_statement(parser)) } expect(parser, end) return node_create_block(range, statements) } @(private = "file") parser_parse_statement :: proc(parser: ^Parser) -> ^Node { ret := parser_parse_expression(parser) expect(parser, .Semicolon) return ret } @(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 } @(private = "file") parser_parse_binary_expression :: proc(parser: ^Parser, kinds: []TokenKind, next: proc(parser: ^Parser) -> ^Node) -> ^Node { lhs := next(parser) for kind in kinds { for accept(parser, kind) { rhs := next(parser) lhs = node_create_binary(kind, lhs.range, lhs, rhs) lhs^.range.end = rhs.range.end } } return lhs } @(private = "file") parser_parse_assignment :: proc(parser: ^Parser) -> ^Node { return parser_parse_binary_expression(parser, {.Assign}, parser_parse_addition) } @(private = "file") parser_parse_addition :: proc(parser: ^Parser) -> ^Node { return parser_parse_binary_expression(parser, {.Add, .Subtract}, parser_parse_multiplication) } @(private = "file") parser_parse_multiplication :: proc(parser: ^Parser) -> ^Node { return parser_parse_binary_expression(parser, {.Multiply, .Divide, .Modulo}, parser_parse_exponent) } @(private = "file") parser_parse_exponent :: proc(parser: ^Parser) -> ^Node { return parser_parse_binary_expression(parser, {.Exponent}, parser_parse_prefix_2) } @(private = "file") parser_parse_bitwise :: proc(parser: ^Parser) -> ^Node { return parser_parse_binary_expression(parser, {.BitwiseAnd, .BitwiseOr, .BitwiseXOR, .BitwiseLeftShift, .BitwiseRightShift}, parser_parse_prefix_2) } @(private = "file") parser_parse_prefix_2 :: proc(parser: ^Parser) -> ^Node { range := parser.tok.range if accept(parser, .Not) { rhs := parser_parse_suffix(parser) range.end = rhs.range.end return node_create_unary(.Not, range, rhs) } else if accept(parser, .BitwiseNot) { rhs := parser_parse_suffix(parser) range.end = rhs.range.end return node_create_unary(.BitwiseNot, range, rhs) } else if accept(parser, .Increment) { rhs := parser_parse_suffix(parser) range.end = rhs.range.end return node_create_unary(.Increment, range, rhs) } else if accept(parser, .Decrement) { rhs := parser_parse_suffix(parser) range.end = rhs.range.end return node_create_unary(.Decrement, range, rhs) } else if accept(parser, .BitwiseXOR) { rhs := parser_parse_suffix(parser) range.end = rhs.range.end return node_create_unary(.BitwiseXOR, range, rhs) } return parser_parse_suffix(parser) } @(private = "file") parser_parse_suffix :: proc(parser: ^Parser) -> ^Node { range := parser.tok.range lhs := parser_parse_prefix(parser) range_op := parser.tok.range range.end = range_op.end if accept(parser, .OpenBracket) { rhs := parser_parse_expression(parser) range.end = rhs.range.end expect(parser, .CloseBracket) return node_create_index_access(range, lhs, rhs) } else if accept(parser, .Increment) { return node_create_unary(.Increment, range, lhs) } else if accept(parser, .Decrement) { return node_create_unary(.Decrement, range, lhs) } return lhs } @(private = "file") parser_parse_prefix :: proc(parser: ^Parser) -> ^Node { range := parser.tok.range if accept(parser, .Add) { return node_create_unary(.Add, range, parser_parse_prefix(parser)) } else if accept(parser, .Subtract) { return node_create_unary(.Subtract, range, parser_parse_prefix(parser)) } return parser_parse_factor(parser) } @(private = "file") parser_parse_factor :: proc(parser: ^Parser) -> (ret: ^Node) { ret = nil if parser.tok.kind == .Integer { ret = node_create_value(.Integer, parser.tok.range, parser.tok.value) parser_next(parser) } else if parser.tok.kind == .Float { ret = node_create_value(.Float, parser.tok.range, parser.tok.value) parser_next(parser) } else if parser.tok.kind == .Character { ret = node_create_value(.Character, parser.tok.range, parser.tok.value) parser_next(parser) } else if parser.tok.kind == .String { ret = node_create_value(.String, parser.tok.range, parser.tok.value) parser_next(parser) } else if parser.tok.kind == .Identifier { ret = node_create_value(.Identifier, parser.tok.range, parser.tok.value) parser_next(parser) prev := parser.can_be_function parser.can_be_function = false if accept(parser, .Dot) { ret = node_create_field_access({ ret.range.start, parser.tok.range.start }, ret, parser_parse_factor(parser)) } parser.can_be_function = prev if parser.can_be_function && parser.tok.kind != .CloseParen && parser.tok.kind != .Semicolon && parser.tok.kind != .Arrow && parser.tok.kind != .EOF { 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 { append(&args, parser_parse_expression(parser)) } ret = node_create_function_call(ret.range, ret, args) parser.can_be_function = prev } } else if accept(parser, .OpenParen) { prev := parser.can_be_function parser.can_be_function = true ret = parser_parse_expression(parser) parser.can_be_function = prev expect(parser, .CloseParen) } else { append(&g_message_list, message_create(.Error, fmt.aprintf("Unexpected factor token {} at {}", parser.tok.kind, "TODO"), parser.tok.range)) } return }