aboutsummaryrefslogtreecommitdiffstats
path: root/src/treewalk/parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/treewalk/parser.c')
-rw-r--r--src/treewalk/parser.c139
1 files changed, 139 insertions, 0 deletions
diff --git a/src/treewalk/parser.c b/src/treewalk/parser.c
new file mode 100644
index 0000000..a2f0f71
--- /dev/null
+++ b/src/treewalk/parser.c
@@ -0,0 +1,139 @@
1#include "parser.h"
2
3Token
4peek_token(const Visitor *visitor) {
5 return visitor->tokens[visitor->current];
6}
7
8Token
9next_token(Visitor *visitor) {
10 return visitor->tokens[visitor->current++];
11}
12
13bool
14has_next_token(const Visitor *visitor) {
15 return visitor->current < array_size(visitor->tokens);
16}
17
18Object *
19parse_fixnum(Token tok) {
20 ssize_t num = 0;
21 int sign = 1;
22 for (size_t i = 0; i < tok.value.n; i++) {
23 char c = tok.value.start[i];
24 if (c == '-') {
25 sign = -1;
26 continue;
27 }
28 num = num * 10 + (c - '0');
29 }
30
31 Object *obj = make_fixnum(num * sign);
32 push_root(obj);
33 return obj;
34}
35
36Object *
37parse_list(Visitor *vs) {
38 Token tok = peek_token(vs);
39 if (tok.type == TOKEN_EOF) {
40 return obj_err;
41 }
42 Object *root = make_pair(obj_nil, obj_nil);
43 push_root(root);
44 Object *next_obj = parse_tree(vs);
45 if (next_obj == obj_err) {
46 return obj_err;
47 }
48 root->car = next_obj;
49 Object *list = root;
50 while (has_next_token(vs)) {
51 Token tok = peek_token(vs);
52 if (tok.type == TOKEN_RPAREN) {
53 next_token(vs);
54 break;
55 }
56 if (tok.type == TOKEN_EOF) {
57 return obj_err;
58 }
59 next_obj = parse_tree(vs);
60 if (next_obj == obj_err) {
61 return obj_err;
62 }
63 list->cdr = make_pair(next_obj, obj_nil);
64 list = list->cdr;
65 }
66 return root;
67}
68
69Object *
70parse_tree(Visitor *vs) {
71 Token tok = next_token(vs);
72 switch (tok.type) {
73 case TOKEN_FIXNUM: {
74 return parse_fixnum(tok);
75 } break;
76 case TOKEN_TRUE: {
77 return obj_true;
78 } break;
79 case TOKEN_FALSE: {
80 return obj_false;
81 } break;
82 case TOKEN_RPAREN: {
83 error_push((Error){
84 .type = ERR_TYPE_PARSER,
85 .value = ERR_UNBALANCED_PAREN,
86 .line = tok.line,
87 .col = tok.column,
88 });
89 return obj_err;
90 } break;
91 case TOKEN_QUOTE: {
92 Object *base = make_pair(obj_quote, obj_nil);
93 base->cdr = make_pair(obj_nil, obj_nil);
94 push_root(base);
95 Object *next_obj = parse_tree(vs);
96 if (next_obj == obj_err) {
97 return obj_err;
98 }
99 base->cdr->car = next_obj;
100 return base;
101 } break;
102 case TOKEN_LPAREN: {
103 Object *obj = parse_list(vs);
104 if (obj == obj_err) {
105 error_push((Error){
106 .type = ERR_TYPE_PARSER,
107 .value = ERR_UNBALANCED_PAREN,
108 .line = tok.line,
109 .col = tok.column,
110 });
111 }
112 return obj;
113 } break;
114 case TOKEN_STRING: {
115 Object *obj = make_string();
116 push_root(obj);
117 append_string(obj, tok.value);
118 return obj;
119 } break;
120 case TOKEN_SYMBOL: {
121 Object *obj = make_symbol(tok.value);
122 push_root(obj);
123 return obj;
124 } break;
125 case TOKEN_NIL: {
126 return obj_nil;
127 } break;
128 default: {
129 break;
130 } break;
131 }
132 error_push((Error){
133 .type = ERR_TYPE_PARSER,
134 .value = ERR_EOF_REACHED,
135 .line = tok.line,
136 .col = tok.column,
137 });
138 return obj_err;
139}