From f51a8817aaae6bced7c12b1c6b14de74cc775595 Mon Sep 17 00:00:00 2001 From: Slendi Date: Thu, 8 Feb 2024 15:41:01 +0200 Subject: [PATCH] Create parser for if statements --- ast.odin | 15 +++++++++++++++ lexer.odin | 1 + parser.odin | 42 +++++++++++++++++++++++++++++++++++++----- 3 files changed, 53 insertions(+), 5 deletions(-) diff --git a/ast.odin b/ast.odin index 774b2ad..698303f 100644 --- a/ast.odin +++ b/ast.odin @@ -20,6 +20,8 @@ NodeKind :: enum { Struct, Enum, Union, + + If, } Node :: struct { @@ -134,3 +136,16 @@ node_print :: proc(node: ^Node, indent := 0) { } } +node_create_if :: proc(range: TextRange, condition, then, else_: ^Node) -> (ret: ^Node) { + ret = new(Node) + ret^ = { + kind = .If, + range = range, + children = { condition, then }, + } + if else_ != nil { + append(&ret.children, else_) + } + return +} + diff --git a/lexer.odin b/lexer.odin index 33658a8..ff8d1bf 100644 --- a/lexer.odin +++ b/lexer.odin @@ -259,6 +259,7 @@ lexer_read_identifier :: proc(lexer: ^Lexer) -> Token { else if compare_dyn_arr_string(&str, "mut") { return token_create(.Mut, crange) } else if compare_dyn_arr_string(&str, "as") { return token_create(.As, crange) } else if compare_dyn_arr_string(&str, "in") { return token_create(.In, crange) } + else if compare_dyn_arr_string(&str, "if") { return token_create(.If, crange) } else if compare_dyn_arr_string(&str, "else") { return token_create(.Else, crange) } else if compare_dyn_arr_string(&str, "elif") { return token_create(.Elif, crange) } else if compare_dyn_arr_string(&str, "for") { return token_create(.For, crange) } diff --git a/parser.odin b/parser.odin index b3309ec..68a5085 100644 --- a/parser.odin +++ b/parser.odin @@ -51,17 +51,49 @@ 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)) + stmt := parser_parse_statement(parser) + if stmt != nil { + append(&statements, stmt) + } } 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 +parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) { + if accept(parser, .Semicolon) { + ret = nil + } else if parser.tok.kind == .If { + range_beg := parser.tok.range + expect(parser, .If) + ret = parser_parse_if_statement(parser) + ret.range.start = range_beg.start + } else { + ret = parser_parse_expression(parser) + expect(parser, .Semicolon) + } + return +} + +@(private = "file") +parser_parse_if_statement :: proc(parser: ^Parser) -> ^Node { + range := parser.tok.range + expect(parser, .OpenParen) + condition := parser_parse_expression(parser) + expect(parser, .CloseParen) + expect(parser, .OpenBrace) + body := parser_parse_block(parser, .CloseBrace) + if accept(parser, .Elif) { + falsebody := parser_parse_if_statement(parser) + return node_create_if(range, condition, body, falsebody) + } + if accept(parser, .Else) { + expect(parser, .OpenBrace) + falsebody := parser_parse_block(parser, .CloseBrace) + return node_create_if(range, condition, body, falsebody) + } + return node_create_if(range, condition, body, nil) } @(private = "file")