bugfixes to interpreter
[philodendron.git] / runtime / interpreter.c
blob3dd54aaaa0cb9cdd9e32a25c5c878b3f0a97e4fd
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include "interpreter.h"
6 struct parse_stack_frame *init_new_stack_frame(struct parse_state *parse_state, struct rtn *rtn)
8 struct parse_stack_frame *frame = &parse_state->parse_stack[parse_state->parse_stack_length++];
9 frame->rtn = rtn;
10 frame->rtn_state = &rtn->states[0];
11 frame->slots.rtn = rtn;
12 frame->slots.num_slots = rtn->num_slots;
13 frame->slots.slots = malloc(sizeof(struct parse_val)*frame->slots.num_slots);
14 return frame;
17 struct parse_stack_frame *pop_stack_frame(struct parse_state *parse_state)
19 struct parse_stack_frame *frame = &parse_state->parse_stack[parse_state->parse_stack_length-1];
20 free(frame->slots.slots);
21 parse_state->parse_stack_length--;
22 if(parse_state->parse_stack_length == 0)
24 return NULL; /* the parse is over */
26 else
28 frame--;
29 frame->rtn_state = frame->rtn_transition->dest_state;
30 return frame;
34 void reset_dfa_match(struct parse_state *parse_state)
36 struct parse_stack_frame *frame = &parse_state->parse_stack[parse_state->parse_stack_length-1];
37 parse_state->dfa = frame->rtn_state->term_dfa;
38 parse_state->dfa_state = &parse_state->dfa->states[0];
39 parse_state->match_begin = parse_state->offset;
40 parse_state->last_match_state = NULL;
43 void do_rtn_transition(struct parse_state *parse_state, int match_begin, int match_len, char *terminal)
45 struct parse_stack_frame *frame = &parse_state->parse_stack[parse_state->parse_stack_length-1];
46 struct parse_val val = {PARSE_VAL_TERMINAL, {.terminal = {match_begin, match_len}}};
47 bool found_transition = false;
49 /* is this an ignored terminal? if so, just skip it */
50 for(int i = 0; i < frame->rtn->num_ignore; i++)
52 if(frame->rtn->ignore_terminals[i] == terminal)
54 reset_dfa_match(parse_state);
55 return;
59 /* find a transition out of this RTN state on this terminal */
60 for(int i = 0; i < frame->rtn_state->num_transitions; i++)
62 struct rtn_transition *t = &frame->rtn_state->transitions[i];
63 if(t->transition_type == TERMINAL_TRANSITION && t->edge.terminal_name == terminal)
65 frame->slots.slots[t->slotnum] = val;
66 frame->rtn_state = t->dest_state;
67 found_transition = true;
68 break;
70 else if(t->transition_type == DECISION && t->edge.decision->terminal_name == terminal)
72 struct decision *d = t->edge.decision;
74 for(int i = 0; i < d->num_actions; i++)
76 struct rtn_transition *t2 = &frame->rtn_state->transitions[d->actions[i]];
78 if(t2->transition_type == NONTERM_TRANSITION)
80 if(parse_state->parse_stack_length == parse_state->parse_stack_size)
82 printf("Need to reallocate parse stack!!\n");
83 exit(1);
85 frame->rtn_transition = t2;
86 frame = init_new_stack_frame(parse_state, t2->edge.nonterminal);
88 else if(t2->transition_type == TERMINAL_TRANSITION)
90 frame->slots.slots[t2->slotnum] = val;
91 frame->rtn_state = t2->dest_state;
94 found_transition = true;
95 break;
99 if(found_transition)
101 while(parse_state->parse_stack_length > 0 && frame->rtn_state->is_final)
102 frame = pop_stack_frame(parse_state);
104 if(parse_state->parse_stack_length > 0)
105 reset_dfa_match(parse_state);
107 else
109 printf("Syntax error -- no RTN transition!!\n");
114 void parse(struct parse_state *parse_state)
116 bool user_cancelled = false;
118 while(!parse_state->buffer->is_eof && !user_cancelled && parse_state->parse_stack_length > 0)
120 int ch = parse_state->buffer->buf[parse_state->offset];
121 //printf("Offset: %d, char %c\n", parse_state->offset, ch);
122 int found_transition = 0;
124 /* We've read one character, which should cause one transition in the DFA for terminals.
125 * Find the appropriate transition, and put the DFA in its new state. */
126 for(int i = 0; i < parse_state->dfa_state->num_transitions; i++)
128 struct intfa_transition *t = &parse_state->dfa_state->transitions[i];
130 if(ch >= t->ch_low && ch <= t->ch_high)
132 parse_state->dfa_state = t->dest_state;
133 found_transition = 1;
134 break;
138 if(found_transition)
140 if(parse_state->dfa_state->final)
142 parse_state->last_match_state = parse_state->dfa_state;
143 parse_state->last_match_end = parse_state->offset;
145 parse_state->offset++;
147 else
149 /* if there was a previous match, fall back to that. otherwise this character represents
150 * a syntax error. */
151 if(parse_state->last_match_state)
153 /* we have a terminal. do RTN transitions as appropriate */
154 //int terminal_len = parse_state->last_match_end-parse_state->match_begin+1;
155 //char terminal[terminal_len];
156 //memcpy(terminal, parse_state->buffer->buf+parse_state->match_begin, terminal_len);
157 //terminal[terminal_len] = '\0';
158 //printf("Recognized a terminal (%s) (%s)\n", parse_state->last_match_state->final, terminal);
159 parse_state->offset = parse_state->last_match_end + 1;
160 do_rtn_transition(parse_state, parse_state->match_begin, parse_state->last_match_end,
161 parse_state->last_match_state->final);
163 else
165 printf("Syntax error!");
172 * Local Variables:
173 * c-file-style: "bsd"
174 * c-basic-offset: 4
175 * indent-tabs-mode: nil
176 * End:
177 * vim:et:sts=4:sw=4