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
|
||||
|
||||
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..<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) {
|
||||
ret = new(Node)
|
||||
ret^ = {
|
||||
|
26
parser.odin
26
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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user