1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
|
internal b32 is_ast_node_nil(AstNode *node)
{
return (node == NULL || node == &nil_ast_node);
}
// used to fill in the AstNode(new_node)
// TokenNode *current_node signifies the current node in the iteration when cycling
// that got produced by the lexer over the tokenstream
internal void handle_binary_expression(TokenNode *current_node, AstNode *new_node, Ast *ast)
{
new_node->type = AstNodeType::Binary;
AstNode *temp_current_node = ast->current;
ast->current->first = temp_current_node;
// TODO: i think we should categorize these better in the future
if (current_node->next->token->type == TokenType::IdentToken ||
current_node->next->token->type == TokenType::Number ||
current_node->next->token->type == TokenType::String) {
TokenNode *next_token = current_node->next;
current_node->last = next_token;
// restructure the tree by moving the next node to sit closer?
// todo: this needs testing
current_node->next = current_node->next->next;
}
}
internal void handle_ternary_expression()
{
/// TODO: do we have any ternary expressions in the language?
}
internal void adopt_ast_node(Ast *ast, AstNode *node)
{
node->parent = ast->current;
ast->current->next = node;
}
// TODO: do we want a reference or copy fo the token we are working on?
internal Ast *parse_tokenized_tree_fmt(MemArena *arena, TokenTree *token_tree)
{
// TODO: replace with something containing a breakpoint, Assert or something like that
// currently it still throws that asm junk
// im going to ignore it for now and just put if checks. do a scan of the code later and fix it
// up
if (!token_tree || !arena)
return NULL;
Ast *ast = PushStruct(arena, Ast);
MemStack *stack;
stack = ArenaToStack(arena, MiB(10));
for (TokenNode *current_node = token_tree->current; !is_token_node_nil(current_node); current_node = current_node->next) {
AstNode *new_node = StackPushStruct(stack, AstNode);
// TODO: cleanup after scan
if (!new_node) {
// NOTE: this doesn't need to be part of the compiler output because it should never fail
Log("Failed to push new node on to the stack");
return NULL;
}
FillAstNodeFieldWIthNilNode(new_node, first);
FillAstNodeFieldWIthNilNode(new_node, last);
FillAstNodeFieldWIthNilNode(new_node, parent);
FillAstNodeFieldWIthNilNode(new_node, next);
switch (current_node->token->type) {
case TokenType::IdentToken: {
if (is_ast_node_nil(ast->current)) {
ast->current = new_node;
ast->current->type = AstNodeType::IdentExpr;
}
} break;
case TokenType::Value: {
if (is_ast_node_nil(ast->current->first) &&
ast->current->type == AstNodeType::Literal) {
new_node->type = AstNodeType::Assignment;
ast->current = new_node;
}
} break;
// TODO: or do we mark this as an expression and evaluate it later?
// this can be taken as a value or parameter
case TokenType::String: {
if (ast->current->type == AstNodeType::Function ||
ast->current->type == AstNodeType::IdentExpr) {
// TODO: handle this as an expression
}
} break;
case TokenType::Number: {
if (ast->current->type == AstNodeType::Function ||
ast->current->type == AstNodeType::IdentExpr) {
}
} break;
case TokenType::Double_Equal: {
handle_binary_expression(current_node, new_node, ast);
} break;
case TokenType::Greater_Equal: {
} break;
case TokenType::Lesser_Equal: {
} break;
case TokenType::Param: {
} break;
case TokenType::Right_Shift: {
} break;
case TokenType::Left_Shift: {
} break;
case TokenType::Asterisk: {
} break;
// ignore comments for now
case TokenType::Cpp_Style_Comment_Start: {
} break;
case TokenType::C_Style_Comment_Start: {
} break;
case TokenType::C_Style_Comment_End: {
} break;
default: {
// 1. TokenType::Undedfined
// 2. null
} break;
}
}
return NULL;
}
|