Add parser for use statment
This commit is contained in:
parent
f5a72da29d
commit
8c8a395193
46
ast.odin
46
ast.odin
@ -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^ = {
|
||||||
|
26
parser.odin
26
parser.odin
@ -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) {
|
||||||
|
8
test.cat
8
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.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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user