Add declaration parsing
This commit is contained in:
parent
8c8a395193
commit
90a495ba1b
20
ast.odin
20
ast.odin
@ -25,6 +25,7 @@ NodeKind :: enum {
|
|||||||
Use,
|
Use,
|
||||||
|
|
||||||
If,
|
If,
|
||||||
|
VariableDeclaration,
|
||||||
}
|
}
|
||||||
|
|
||||||
Node :: struct {
|
Node :: struct {
|
||||||
@ -116,6 +117,7 @@ node_print :: proc(node: ^Node, indent := 0) {
|
|||||||
}
|
}
|
||||||
if node == nil {
|
if node == nil {
|
||||||
fmt.println("nil")
|
fmt.println("nil")
|
||||||
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
fmt.printf("{}: {} ", node.kind, "TODO")
|
fmt.printf("{}: {} ", node.kind, "TODO")
|
||||||
@ -195,3 +197,21 @@ node_create_if :: proc(range: TextRange, condition, then, else_: ^Node) -> (ret:
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
node_create_variable :: proc(range: TextRange, name, type_, value: ^Node, is_const: bool) -> (ret: ^Node) {
|
||||||
|
fmt.printf("Creating variable declaration for {} with value {}\n", name.value.([dynamic]u8), value)
|
||||||
|
ret = new(Node)
|
||||||
|
ret^ = {
|
||||||
|
kind = .VariableDeclaration,
|
||||||
|
range = range,
|
||||||
|
children = { name, type_, value },
|
||||||
|
value = is_const,
|
||||||
|
}
|
||||||
|
|
||||||
|
//if value != nil {
|
||||||
|
// fmt.printf("Appending value to variable declaration\n")
|
||||||
|
// append(&ret.children, value)
|
||||||
|
//}
|
||||||
|
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -181,6 +181,7 @@ lexer_next :: proc(lexer: ^Lexer) -> (ret: Token) {
|
|||||||
case '?': ret = token_create(.Question, crange)
|
case '?': ret = token_create(.Question, crange)
|
||||||
case ':': ret = token_create(.Colon, crange)
|
case ':': ret = token_create(.Colon, crange)
|
||||||
case '.': ret = token_create(.Dot, crange)
|
case '.': ret = token_create(.Dot, crange)
|
||||||
|
case ',': ret = token_create(.Comma, crange)
|
||||||
case ';': ret = token_create(.Semicolon, crange)
|
case ';': ret = token_create(.Semicolon, crange)
|
||||||
|
|
||||||
case '"': ret = lexer_read_string(lexer, .String, '\"')
|
case '"': ret = lexer_read_string(lexer, .String, '\"')
|
||||||
@ -276,6 +277,7 @@ lexer_read_identifier :: proc(lexer: ^Lexer) -> Token {
|
|||||||
else if compare_dyn_arr_string(&str, "ret") { return token_create(.Ret, crange) }
|
else if compare_dyn_arr_string(&str, "ret") { return token_create(.Ret, crange) }
|
||||||
else if compare_dyn_arr_string(&str, "static") { return token_create(.Static, crange) }
|
else if compare_dyn_arr_string(&str, "static") { return token_create(.Static, crange) }
|
||||||
else if compare_dyn_arr_string(&str, "defer") { return token_create(.Defer, crange) }
|
else if compare_dyn_arr_string(&str, "defer") { return token_create(.Defer, crange) }
|
||||||
|
else if compare_dyn_arr_string(&str, "let") { return token_create(.Let, crange) }
|
||||||
else if compare_dyn_arr_string(&str, "and") { return token_create(.And, crange) }
|
else if compare_dyn_arr_string(&str, "and") { return token_create(.And, crange) }
|
||||||
else if compare_dyn_arr_string(&str, "or") { return token_create(.Or, crange) }
|
else if compare_dyn_arr_string(&str, "or") { return token_create(.Or, crange) }
|
||||||
|
|
||||||
|
90
parser.odin
90
parser.odin
@ -53,9 +53,17 @@ parser_parse_block :: proc(parser: ^Parser, end: TokenKind) -> (ret: ^Node) {
|
|||||||
range := parser.tok.range
|
range := parser.tok.range
|
||||||
statements : [dynamic]^Node
|
statements : [dynamic]^Node
|
||||||
for parser.tok.kind != end && parser.tok.kind != .EOF {
|
for parser.tok.kind != end && parser.tok.kind != .EOF {
|
||||||
stmt := parser_parse_statement(parser)
|
if accept(parser, .Let) {
|
||||||
if stmt != nil {
|
ret := parser_parse_definitions(parser)
|
||||||
append(&statements, stmt)
|
expect(parser, .Semicolon)
|
||||||
|
for stmt in ret {
|
||||||
|
append(&statements, stmt)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stmt := parser_parse_statement(parser)
|
||||||
|
if stmt != nil {
|
||||||
|
append(&statements, stmt)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
expect(parser, end)
|
expect(parser, end)
|
||||||
@ -80,6 +88,76 @@ parser_parse_statement :: proc(parser: ^Parser) -> (ret: ^Node) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
parser_parse_type :: proc(parser: ^Parser) -> (ret: ^Node) {
|
||||||
|
// FIXME: Add more types
|
||||||
|
range := parser.tok.range
|
||||||
|
if parser.tok.kind == .Identifier {
|
||||||
|
ret = node_create_value(.Identifier, range, parser.tok.value.([dynamic]u8))
|
||||||
|
parser_next(parser)
|
||||||
|
} else {
|
||||||
|
append(&g_message_list, message_create(
|
||||||
|
.Error,
|
||||||
|
fmt.aprintf("Expected type, got {} at {}", parser.tok.kind, "TODO"),
|
||||||
|
parser.tok.range))
|
||||||
|
ret = nil
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
@(private = "file")
|
||||||
|
parser_parse_definitions :: proc(parser: ^Parser, end := TokenKind.Semicolon) -> [dynamic]^Node {
|
||||||
|
range := parser.tok.range
|
||||||
|
vars : [dynamic]^Node
|
||||||
|
type : ^Node = nil
|
||||||
|
are_constants := false
|
||||||
|
uninitialized := false
|
||||||
|
for parser.tok.kind != end && parser.tok.kind != .EOF {
|
||||||
|
names := [dynamic][dynamic]u8{}
|
||||||
|
for parser.tok.kind == .Identifier {
|
||||||
|
tok := parser.tok
|
||||||
|
if !expect(parser, .Identifier) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
append(&names, tok.value.([dynamic]u8))
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(parser, .Colon)
|
||||||
|
|
||||||
|
if parser.tok.kind != .Colon && parser.tok.kind != .Assign {
|
||||||
|
type = parser_parse_type(parser)
|
||||||
|
}
|
||||||
|
|
||||||
|
if accept(parser, .Assign) {
|
||||||
|
are_constants = false
|
||||||
|
} else if accept(parser, .Colon) {
|
||||||
|
are_constants = true
|
||||||
|
} else {
|
||||||
|
uninitialized = true
|
||||||
|
}
|
||||||
|
|
||||||
|
for i in 0..<len(names) {
|
||||||
|
value : ^Node = nil
|
||||||
|
if uninitialized == false {
|
||||||
|
value = parser_parse_expression(parser)
|
||||||
|
}
|
||||||
|
fmt.printf("value: {}\n", value)
|
||||||
|
name_node := node_create_value(.Identifier, range, names[i])
|
||||||
|
append(&vars, node_create_variable(range, name_node, type, value, are_constants))
|
||||||
|
}
|
||||||
|
|
||||||
|
if !accept(parser, .Comma) {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
type = nil
|
||||||
|
are_constants = false
|
||||||
|
uninitialized = false
|
||||||
|
}
|
||||||
|
return vars
|
||||||
|
}
|
||||||
|
|
||||||
@(private = "file")
|
@(private = "file")
|
||||||
parser_parse_use_statement :: proc(parser: ^Parser) -> ^Node {
|
parser_parse_use_statement :: proc(parser: ^Parser) -> ^Node {
|
||||||
range := parser.tok.range
|
range := parser.tok.range
|
||||||
@ -144,9 +222,9 @@ parser_parse_arrow :: proc(parser: ^Parser) -> ^Node {
|
|||||||
for accept(parser, .Arrow) {
|
for accept(parser, .Arrow) {
|
||||||
rhs := parser_parse_assignment(parser)
|
rhs := parser_parse_assignment(parser)
|
||||||
if rhs.kind != .FunctionCall &&
|
if rhs.kind != .FunctionCall &&
|
||||||
rhs.kind != .Identifier &&
|
rhs.kind != .Identifier &&
|
||||||
rhs.kind != .FieldAccess &&
|
rhs.kind != .FieldAccess &&
|
||||||
rhs.kind != .IndexAccess {
|
rhs.kind != .IndexAccess {
|
||||||
append(&g_message_list, message_create(
|
append(&g_message_list, message_create(
|
||||||
.Error,
|
.Error,
|
||||||
fmt.aprintf("Expected function call, got {} at {}", rhs.kind, "TODO"),
|
fmt.aprintf("Expected function call, got {} at {}", rhs.kind, "TODO"),
|
||||||
|
5
test.cat
5
test.cat
@ -4,6 +4,11 @@ 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!"
|
||||||
|
|
||||||
|
let a := 123
|
||||||
|
let uninitialized : u32
|
||||||
|
let multiple variables here : u32 = 1 2 3
|
||||||
|
let string : str, number : i32
|
||||||
|
|
||||||
if a == 1 {
|
if a == 1 {
|
||||||
lol
|
lol
|
||||||
} elif b == 2 {
|
} elif b == 2 {
|
||||||
|
@ -19,7 +19,6 @@ TokenKind :: enum {
|
|||||||
Type,
|
Type,
|
||||||
Use,
|
Use,
|
||||||
Pub,
|
Pub,
|
||||||
Let,
|
|
||||||
Mut,
|
Mut,
|
||||||
As,
|
As,
|
||||||
In,
|
In,
|
||||||
@ -34,6 +33,7 @@ TokenKind :: enum {
|
|||||||
Ret,
|
Ret,
|
||||||
Static,
|
Static,
|
||||||
Defer,
|
Defer,
|
||||||
|
Let,
|
||||||
|
|
||||||
// Logical Operators Keywords
|
// Logical Operators Keywords
|
||||||
And,
|
And,
|
||||||
@ -80,6 +80,7 @@ TokenKind :: enum {
|
|||||||
Colon,
|
Colon,
|
||||||
Arrow,
|
Arrow,
|
||||||
Dot,
|
Dot,
|
||||||
|
Comma,
|
||||||
|
|
||||||
// Other
|
// Other
|
||||||
Semicolon,
|
Semicolon,
|
||||||
@ -96,6 +97,7 @@ TextRange :: struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TokenValue :: union {
|
TokenValue :: union {
|
||||||
|
bool,
|
||||||
u64,
|
u64,
|
||||||
f64,
|
f64,
|
||||||
[dynamic]u8,
|
[dynamic]u8,
|
||||||
@ -140,3 +142,5 @@ token_create_f64 :: proc(kind: TokenKind, value: f64, range: TextRange) -> Token
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user