10 #define DBG(FN) printf("%s %s %s\n", FN, expression_types[state->expression->type], (state->expression->type == EX_FNCALL && state->expression->value.str_value) ? state->expression->value.str_value : "");
16 static char *expression_types[EX_FNCALL + 1] = {
25 static void print_expression(ParseExpression *expr, int indent)
27 for (int i = 0; i < indent; i++)
30 printf("%s ", expression_types[expr->type]);
32 if (expr->type == EX_INTLIT || expr->type == EX_ARGNUM)
33 printf("%d\n", expr->value.int_value);
35 printf("\"%s\"\n", expr->value.str_value);
37 if (expr->type == EX_FNCALL)
38 for (size_t i = 0; i < expr->num_children; i++)
39 print_expression(expr->children[i], indent + 1);
42 static void print_ast(AbstractSyntaxTree tree)
44 printf("\n[Abstract Syntax Tree]\n\n");
46 for (size_t f = 0; f < tree.num_functions; f++) {
47 ParseFunction *function = tree.functions[f];
49 printf("function %s\n", function->name);
50 print_expression(function->expression, 1);
55 static void buffer_append(ParseState *state, char c)
57 state->buffer = realloc(state->buffer, ++state->buffer_size);
58 state->buffer[state->buffer_size - 1] = c;
61 static char *buffer_terminate(ParseState *state)
63 buffer_append(state, '\0');
65 char *buffer = state->buffer;
68 state->buffer_size = 0;
73 static void start_arg(ParseState *state)
77 ParseExpression *parent = state->expression;
78 parent->children = realloc(parent->children, sizeof *parent->children * ++parent->num_children);
79 ParseExpression *child = parent->children[parent->num_children - 1] = malloc(sizeof *child);
81 child->type = EX_UNINIT;
82 child->parent = parent;
84 state->expression = child;
87 static bool continue_arg(ParseState *state, char c)
94 state->expression = state->expression->parent;
95 else if (! isspace(c))
101 static bool finish_arg(ParseState *state, char c)
103 state->expression = state->expression->parent;
105 if (state->expression)
106 continue_arg(state, c);
107 else if (! isspace(c))
113 static bool parse_expression_init(ParseState *state, char c)
124 case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
125 state->expression->type = EX_INTLIT;
126 buffer_append(state, c);
130 state->expression->type = EX_STRLIT;
134 state->expression->type = EX_ARGNUM;
138 state->expression->type = EX_FNNAME;
142 state->expression->type = EX_FNCALL;
143 state->expression->value.str_value = NULL;
144 buffer_append(state, c);
149 static bool parse_expression_finish(ParseState *state, char c)
153 if (state->expression->type == EX_ARGNUM && state->buffer_size == 0)
156 char *buffer_read = buffer_terminate(state);
158 if (state->expression->type == EX_INTLIT || state->expression->type == EX_ARGNUM) {
159 state->expression->value.int_value = atoi(buffer_read);
162 state->expression->value.str_value = buffer_read;
165 if (state->expression->type == EX_FNCALL) {
166 state->expression->num_children = 0;
167 state->expression->children = NULL;
172 return finish_arg(state, c);
174 if (c == ',' || c == ')')
175 return finish_arg(state, c);
177 state->expression = state->expression->parent;
183 static bool parse_expression_continue(ParseState *state, char c)
187 if (state->expression->type == EX_FNCALL && state->expression->value.str_value)
188 return continue_arg(state, c);
191 state->expression->type == EX_STRLIT
194 (state->expression->type == EX_FNCALL && c == '(')
195 || isspace(c) || c == ',' || c == ')'
198 return parse_expression_finish(state, c);
200 if ((state->expression->type == EX_INTLIT || state->expression->type == EX_ARGNUM) && ! isdigit(c))
203 if ((state->expression->type == EX_FNNAME || state->expression->type == EX_FNCALL) && (c == '&' || c == '$'))
206 buffer_append(state, c);
212 static bool parse_expression(ParseState *state, char c)
216 return state->expression->type == EX_UNINIT
217 ? parse_expression_init(state, c)
218 : parse_expression_continue(state, c);
221 static bool parse_function(ParseState *state, char c)
224 printf("%s\n", __FUNCTION__);
227 if (c == '\"' || c == '$' || c == ':' || c == ',' || c == '&' || c == '(' || c == ')' || isdigit(c))
231 buffer_append(state, c);
235 if (state->buffer_size == 0)
238 char *name = buffer_terminate(state);
240 state->expression = malloc(sizeof *state->expression);
241 state->expression->type = EX_UNINIT;
242 state->expression->parent = NULL;
244 state->tree.functions = realloc(state->tree.functions, sizeof *state->tree.functions * ++state->tree.num_functions);
245 *(state->tree.functions[state->tree.num_functions - 1] = malloc(sizeof(ParseFunction))) = (ParseFunction) {
247 .expression = state->expression,
253 static bool parse_character(ParseState *state, char c)
256 printf("\nparse_character ");
266 return state->expression
267 ? parse_expression(state, c)
268 : parse_function(state, c);
271 AbstractSyntaxTree parse_file(const char *filename)
285 FILE *f = fopen(filename, "r");
288 error("%s: unable to open\n", filename);
291 printf("[File %s]\n[Line %d]\n", filename, lines);
301 error("%s: I/O error\n", filename);
308 printf("\n[Line %d]\n", lines);
311 if (! parse_character(&state, c))
312 error("%s: syntax error in line %d\n", filename, lines);
315 if (state.buffer || state.expression)
316 error("%s: syntax error at end of file\n", filename);
321 print_ast(state.tree);