Add parser for use statment

This commit is contained in:
Slendi 2024-02-08 18:30:10 +02:00
parent f5a72da29d
commit 8c8a395193
3 changed files with 74 additions and 6 deletions

View File

@ -1,6 +1,7 @@
package main package main
import "core:fmt" import "core:fmt"
import "core:c/libc"
NodeKind :: enum { NodeKind :: enum {
Integer, Integer,
@ -21,6 +22,8 @@ NodeKind :: enum {
Enum, Enum,
Union, Union,
Use,
If, 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..<len(path) {
if path[i] == '.' {
break
}
if path[i] == '/' {
clear(&new_alias)
continue
}
if libc.isalnum(i32(path[i])) == 0 {
append(&new_alias, '_')
} else {
append(&new_alias, path[i])
}
}
if len(new_alias) == 0 {
panic("Invalid alias for use statement")
}
append(&ret.children, node_create_value(.Identifier, range, new_alias))
}
return
}
node_create_if :: proc(range: TextRange, condition, then, else_: ^Node) -> (ret: ^Node) { node_create_if :: proc(range: TextRange, condition, then, else_: ^Node) -> (ret: ^Node) {
ret = new(Node) ret = new(Node)
ret^ = { ret^ = {

View File

@ -35,10 +35,12 @@ accept :: proc(parser: ^Parser, tok: TokenKind) -> bool {
} }
@(private = "file") @(private = "file")
expect :: proc(parser: ^Parser, tok: TokenKind) { expect :: proc(parser: ^Parser, tok: TokenKind) -> bool {
if !accept(parser, tok) { if !accept(parser, tok) {
append(&g_message_list, message_create(.Error, fmt.aprintf("Expected {}, got {} at {}", tok, parser.tok.kind, "TODO"), parser.tok.range)) 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) { parser_parse :: proc(parser: ^Parser) -> (ret: ^Node) {
@ -62,13 +64,15 @@ parser_parse_block :: proc(parser: ^Parser, end: TokenKind) -> (ret: ^Node) {
@(private = "file") @(private = "file")
parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) { parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
range_beg := parser.tok.range
if accept(parser, .Semicolon) { if accept(parser, .Semicolon) {
ret = nil ret = nil
} else if parser.tok.kind == .If { } else if parser.tok.kind == .If {
range_beg := parser.tok.range
expect(parser, .If) expect(parser, .If)
ret = parser_parse_if_statement(parser) ret = parser_parse_if_statement(parser)
ret.range.start = range_beg.start ret.range.start = range_beg.start
} else if parser.tok.kind == .Use {
ret = parser_parse_use_statement(parser)
} else { } else {
ret = parser_parse_expression(parser) ret = parser_parse_expression(parser)
expect(parser, .Semicolon) expect(parser, .Semicolon)
@ -76,12 +80,26 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
return 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") @(private = "file")
parser_parse_if_statement :: proc(parser: ^Parser) -> ^Node { parser_parse_if_statement :: proc(parser: ^Parser) -> ^Node {
range := parser.tok.range range := parser.tok.range
expect(parser, .OpenParen)
condition := parser_parse_expression(parser) condition := parser_parse_expression(parser)
expect(parser, .CloseParen)
expect(parser, .OpenBrace) expect(parser, .OpenBrace)
body := parser_parse_block(parser, .CloseBrace) body := parser_parse_block(parser, .CloseBrace)
if accept(parser, .Elif) { if accept(parser, .Elif) {

View File

@ -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.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) {
if a == 1 {
lol lol
} elif (b == 2) { } elif b == 2 {
kek kek
} else { } else {
aaaaaaa aaaaaaa