summaryrefslogtreecommitdiff
path: root/source/fajr_parser
diff options
context:
space:
mode:
Diffstat (limited to 'source/fajr_parser')
-rw-r--r--source/fajr_parser/fajr_parser.c364
-rw-r--r--source/fajr_parser/fajr_parser.h60
2 files changed, 424 insertions, 0 deletions
diff --git a/source/fajr_parser/fajr_parser.c b/source/fajr_parser/fajr_parser.c
new file mode 100644
index 0000000..cfd1fb2
--- /dev/null
+++ b/source/fajr_parser/fajr_parser.c
@@ -0,0 +1,364 @@
1internal syntax_node *
2PeekToOffset(syntax_node *Node, i32 PeekOffset, b32 findChild)
3{
4 if(PeekOffset < 0)
5 {
6 for(i32 PeekCount = 0; PeekCount < PeekOffset; PeekCount++)
7 {
8 if(!Node || !Node->Next) return &nil_syntax_node;
9 Node = Node->Next;
10 }
11 }
12 else if(PeekOffset > 0)
13 {
14 for(i32 PeekCount = 0; PeekCount < PeekOffset; PeekCount++)
15 {
16 if(!Node || !Node->First) return &nil_syntax_node;
17 Node = Node->First;
18 }
19 }
20 else if(PeekOffset == 0)
21 {
22 return Node;
23 }
24
25 return &nil_syntax_node;
26}
27
28internal void
29NodePushChild(concrete_syntax_tree *Tree, syntax_node *Node)
30{
31 Node->Parent = Tree->Current;
32
33 if(Tree->Current->First == &nil_syntax_node)
34 {
35 Tree->Current->First = Node;
36 Tree->Current->Last = Node;
37 }
38 else
39 {
40 Tree->Current->Last->Next = Node;
41 Tree->Current->Last = Node;
42 }
43}
44
45internal void
46NodePushNext(concrete_syntax_tree *Tree, syntax_node *Node)
47{
48 Node->Parent = Tree->Current;
49
50 if(Tree->Current->Next == &nil_syntax_node) Tree->Current->Next = Node;
51 else Tree->Current->Last->Next = Node;
52}
53
54internal inline b32
55IsNilSyntaxNode(syntax_node *Node)
56{
57 return Node == &nil_syntax_node || Node == NULL;
58}
59
60internal void
61DisownNode(concrete_syntax_tree *Tree, syntax_node *Node)
62{
63 Node->First = &nil_syntax_node;
64 Node->Last = &nil_syntax_node;
65 Node->Parent = &nil_syntax_node;
66 Node->Next = &nil_syntax_node;
67 Node->Token = &nil_token;
68 Node->Type = SyntaxNodeUnwanted;
69}
70
71internal void
72CopyNode(syntax_node *Dest, syntax_node *Src)
73{
74 Src->First = Dest->First;
75 Src->Parent = Dest->Parent;
76 Src->Last = Dest->Last;
77 Src->Next = Dest->Next;
78 Src->Token = Dest->Token;
79 Src->Type = Dest->Type;
80}
81
82/* Insert the node at any given spot thus hopefully allowwing for code changes without breaking */
83internal void
84AdoptNode(concrete_syntax_tree *Tree, syntax_node *Node, syntax_node *ParentNode, b32 asChild)
85{
86 //
87 if (!IsNilSyntaxNode(ParentNode)) return;
88
89 //
90 if (asChild)
91 {
92 ParentNode->Last->Next = Node;
93 Node->Next = ParentNode->Last;
94 }
95 else
96 {
97 // copy node
98 ParentNode->Next = Node;
99 CopyNode(Node, ParentNode->Next);
100 }
101
102
103 NodePushNext(Tree, Node);
104
105 return;
106}
107
108
109internal inline void
110Ground(token *Token)
111{
112 Token->Flags = (token_flags)(Token->Flags | FlagDirty);
113}
114
115internal concrete_syntax_tree *
116Parse(mem_arena *Arena, token_list *List, concrete_syntax_tree *Tree)
117{
118 for(token_node *TokenNode = List->Root;
119 TokenNode != &nil_token_node && TokenNode != NULL;
120 TokenNode = TokenNode->Next)
121 {
122 token *Token = TokenNode->Token;
123 syntax_node *SyntaxNode;
124
125 {
126 SyntaxNode = PushStruct(Arena, syntax_node);
127 SyntaxNode->Token = Token;
128 SyntaxNode->First = &nil_syntax_node;
129 SyntaxNode->Last = &nil_syntax_node;
130 SyntaxNode->Next = &nil_syntax_node;
131 SyntaxNode->Parent = &nil_syntax_node;
132 }
133
134
135 if(IsNilSyntaxNode(Tree->Root))
136 {
137 Tree->Root = SyntaxNode;
138 Tree->Current = SyntaxNode;
139 }
140
141 switch((token_type)Token->Type)
142 {
143 case TokenIdentifier:
144 {
145 if(!IsNilTokenNode(TokenNode) && TokenNode->Next->Token->Type == (token_type)'=')
146 {
147 token_node *ValueNode = TokenNode->Next->Next;
148
149 if(ValueNode->Token->Type != TokenIdentifierAssignmentValue &&
150 ValueNode->Token->Type != TokenValue)
151 {
152 ValueNode->Token->Type = TokenIdentifierAssignmentValue;
153 }
154 }
155
156 if(Tree->Current != SyntaxNode)
157 {
158 NodePushChild(Tree, SyntaxNode);
159 }
160 }
161 break;
162
163 case TokenIdentifierAssignmentValue:
164 {
165 NodePushChild(Tree, SyntaxNode);
166 }
167 break;
168
169 case TokenNumber:
170 case TokenString:
171 {
172 if(Tree->Current && Tree->Current->Token->Type == (token_type)'=')
173 {
174 Token->Type = TokenIdentifierAssignmentValue;
175
176 if(Tree->Current->Parent && Tree->Current->Parent->Token->Type != TokenIdentifier)
177 {
178 Ground(Token);
179 }
180 }
181
182 NodePushChild(Tree, SyntaxNode);
183 }
184 break;
185
186 case TokenDoubleEqual:
187 {
188 NodePushChild(Tree, SyntaxNode);
189
190 if(!IsNilSyntaxNode(Tree->Current->Parent))
191 {
192 Tree->Current->First = Tree->Current->Parent;
193 Tree->Current->Last = Tree->Current->Next;
194 Tree->Current->Parent = Tree->Current;
195 }
196 }
197 break;
198
199 case TokenGreaterEqual:
200 case TokenLesserEqual:
201 case(token_type)'<':
202 case(token_type)'>':
203 {
204 NodePushChild(Tree, SyntaxNode);
205 Tree->Current = SyntaxNode;
206 }
207 break;
208
209 case(token_type)'(':
210 {
211 syntax_node *Current = Tree->Current;
212 Tree->Current->First = PeekToOffset(Tree->Current, 1, 0);
213
214 while(Tree->Current->Token->Type != (token_type)')' && !IsNilSyntaxNode(Tree->Current->Next))
215 {
216 Current = Current->Next;
217 }
218 if(Current == &nil_syntax_node)
219 {
220 print("Forgot to close paran");
221 }
222 }
223 break;
224
225 case(token_type)')':
226 {
227 while(Tree->Current &&
228 Tree->Current != &nil_syntax_node &&
229 Tree->Current->Token->Type != (token_type)'(')
230 {
231 Tree->Current = Tree->Current->Parent;
232 }
233
234 if(Tree->Current && Tree->Current->Parent)
235 {
236 Tree->Current = Tree->Current->Parent;
237 }
238 }
239 break;
240
241 case(token_type)'{':
242 {
243 syntax_node *Node = &nil_syntax_node;
244
245 for(i32 index = 0; PeekToOffset(Tree->Current, index, 0); ++index)
246 {
247 Tree->Current->First = Tree->Current->Next;
248 // TODO(nasr): was doing something here
249 }
250 }
251 break;
252
253 case(token_type)'}':
254 {
255 if(Tree->Current && Tree->Current->Parent)
256 {
257 Tree->Current = Tree->Current->Parent;
258 }
259 }
260 break;
261
262 case(token_type)';':
263 {
264 Tree->Current->Last = Tree->Current;
265 Tree->Current = Tree->Current->Parent;
266 }
267 break;
268
269 case TokenFunc:
270 {
271 // TODO(nasr): define the function body
272 NodePushChild(Tree, SyntaxNode);
273 Tree->Current = SyntaxNode;
274 }
275 break;
276
277 case TokenReturn:
278 {
279 if(Tree->Current &&
280 Tree->Current->Parent &&
281 Tree->Current->Parent->Token->Type != TokenFunc)
282 {
283 Ground(Token);
284 }
285
286 NodePushChild(Tree, SyntaxNode);
287 Tree->Current = SyntaxNode;
288 }
289 break;
290
291 case TokenIf:
292 {
293 NodePushChild(Tree, SyntaxNode);
294 Tree->Current = SyntaxNode;
295 }
296 break;
297
298 case TokenElse:
299 {
300 // TODO(nasr): handle no body
301 NodePushChild(Tree, SyntaxNode);
302 }
303 break;
304
305 case TokenWhile:
306 case TokenFor:
307 {
308 NodePushChild(Tree, SyntaxNode);
309 Tree->Current = SyntaxNode;
310 }
311 break;
312
313 case TokenBreak:
314 {
315 token_type Type = Tree->Current->Parent->Token->Type;
316
317 if(Type != TokenFor && Type != TokenWhile)
318 {
319 Ground(Token);
320 print("Break statement not allowed here");
321 }
322 NodePushChild(Tree, SyntaxNode);
323 }
324 break;
325
326 case TokenContinue:
327 {
328 NodePushChild(Tree, SyntaxNode);
329 }
330 break;
331
332 case TokenExpression:
333 case TokenParam:
334 {
335 NodePushChild(Tree, SyntaxNode);
336 Tree->Current = SyntaxNode;
337 }
338 break;
339
340 case TokenStar:
341 {
342 // TODO(nasr): once we get to better visualizations i think
343 NodePushChild(Tree, SyntaxNode);
344 }
345 break;
346
347 case TokenUndefined:
348 {
349 Ground(Token);
350 NodePushChild(Tree, SyntaxNode);
351 }
352 break;
353
354 default:
355 {
356 Ground(Token);
357 NodePushChild(Tree, SyntaxNode);
358 }
359 break;
360 }
361 }
362
363 return Tree;
364}
diff --git a/source/fajr_parser/fajr_parser.h b/source/fajr_parser/fajr_parser.h
new file mode 100644
index 0000000..d83dde2
--- /dev/null
+++ b/source/fajr_parser/fajr_parser.h
@@ -0,0 +1,60 @@
1#ifndef EDITOR_PARSER_H
2#define EDITOR_PARSER_H
3
4typedef enum syntax_node_type syntax_node_type;
5enum syntax_node_type
6{
7 SyntaxNodeLiteral,
8 SyntaxNodeIdentifier,
9 SyntaxNodeBinary,
10
11 SyntaxNodeAssignment,
12 SyntaxNodeReturn,
13 SyntaxNodeFunction,
14 SyntaxNodeUnwanted,
15};
16
17typedef struct syntax_node syntax_node;
18struct syntax_node
19{
20 syntax_node *First;
21 syntax_node *Last;
22 syntax_node *Parent;
23 syntax_node *Next;
24
25 token *Token;
26
27 syntax_node_type Type;
28};
29
30typedef struct concrete_syntax_tree concrete_syntax_tree;
31struct concrete_syntax_tree
32{
33 syntax_node *Root;
34 syntax_node *Current;
35};
36
37// TODO(nasr): implement this later together with file handling
38read_only global_variable
39syntax_node nil_syntax_node =
40{
41.First = &nil_syntax_node,
42.Last = &nil_syntax_node,
43.Parent = &nil_syntax_node,
44.Next = &nil_syntax_node,
45.Token = &nil_token,
46};
47
48read_only global_variable
49concrete_syntax_tree nil_concrete_syntax_tree =
50{
51.Root = &nil_syntax_node,
52.Current = &nil_syntax_node,
53};
54
55#define PeekForward(Node, Type, NilNode) \
56 for(; (Node) && (Node) != &(NilNode); (Node) = (Node)->Next) \
57 if((Node)->Token->Type == (Type)) \
58 break;
59
60#endif // EDITOR_PARSER_H