From 8c8a39519325e7b2e967243228dd96a3f544c18f Mon Sep 17 00:00:00 2001 From: Slendi Date: Thu, 8 Feb 2024 18:30:10 +0200 Subject: [PATCH] Add parser for use statment --- ast.odin | 46 ++++++++++++++++++++++++++++++++++++++++++++++ parser.odin | 26 ++++++++++++++++++++++---- test.cat | 8 ++++++-- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/ast.odin b/ast.odin index 698303f..6c7c70e 100644 --- a/ast.odin +++ b/ast.odin @@ -1,6 +1,7 @@ package main import "core:fmt" +import "core:c/libc" NodeKind :: enum { Integer, @@ -21,6 +22,8 @@ NodeKind :: enum { Enum, Union, + Use, + If, } @@ -136,6 +139,49 @@ node_print :: proc(node: ^Node, indent := 0) { } } +node_create_use :: proc(range: TextRange, path, alias: [dynamic]u8) -> (ret: ^Node) { + path_ := path + // Check if the path ends with ".cat", if not, append it. + len_path := len(path_) + if len(path_) < 4 || path_[len_path - 4] != '.' || path_[len_path - 3] != 'c' || path_[len_path - 2] != 'a' || path_[len_path - 1] != 't' { + append(&path_, '.') + append(&path_, 'c') + append(&path_, 'a') + append(&path_, 't') + } + ret = new(Node) + ret^ = { + kind = .Use, + range = range, + value = path_, + } + if len(alias) != 0 { + append(&ret.children, node_create_value(.Identifier, range, alias)) + } else { + // Get the filename, and trucate the extension, then replace any special characters with _ + new_alias := [dynamic]u8{} + for i in 0.. (ret: ^Node) { ret = new(Node) ret^ = { diff --git a/parser.odin b/parser.odin index 425d366..d6ea77e 100644 --- a/parser.odin +++ b/parser.odin @@ -35,10 +35,12 @@ accept :: proc(parser: ^Parser, tok: TokenKind) -> bool { } @(private = "file") -expect :: proc(parser: ^Parser, tok: TokenKind) { +expect :: proc(parser: ^Parser, tok: TokenKind) -> bool { if !accept(parser, tok) { append(&g_message_list, message_create(.Error, fmt.aprintf("Expected {}, got {} at {}", tok, parser.tok.kind, "TODO"), parser.tok.range)) + return false } + return true } parser_parse :: proc(parser: ^Parser) -> (ret: ^Node) { @@ -62,13 +64,15 @@ parser_parse_block :: proc(parser: ^Parser, end: TokenKind) -> (ret: ^Node) { @(private = "file") parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) { + range_beg := parser.tok.range 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 if parser.tok.kind == .Use { + ret = parser_parse_use_statement(parser) } else { ret = parser_parse_expression(parser) expect(parser, .Semicolon) @@ -76,12 +80,26 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) { return } +@(private = "file") +parser_parse_use_statement :: proc(parser: ^Parser) -> ^Node { + range := parser.tok.range + expect(parser, .Use) + alias : [dynamic]u8 + if parser.tok.kind == .Identifier { + alias = parser.tok.value.([dynamic]u8) + parser_next(parser) + } + tok := parser.tok + if !expect(parser, .String) { + return nil + } + return node_create_use(range, tok.value.([dynamic]u8), alias) +} + @(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) { diff --git a/test.cat b/test.cat index 1980272..437cb14 100644 --- a/test.cat +++ b/test.cat @@ -1,8 +1,12 @@ +use "fmt.cat" +use lib "directory/long_library_name" + fmt.printf "%d + %d = %d File length: %d" a b a + b (io.file_size "file.txt") fmt.println "Hello world!" -if (a == 1) { + +if a == 1 { lol -} elif (b == 2) { +} elif b == 2 { kek } else { aaaaaaa