Worked out the post fix operator issue, I think. Just realised that I forgot to tag...
[fridhskrift.git] / parser / statement.cpp
bloba3e7776ddb9f0636e9ea256ab12e95be68972a42
1 #include <ail/file.hpp>
2 #include <ail/string.hpp>
3 #include <fridh/parser.hpp>
4 #include <fridh/lexer.hpp>
6 namespace fridh
8 void set_last_group(lexeme_group::type new_last_group, lexeme_group::type & last_group, bool & got_last_group)
10 last_group = new_last_group;
11 got_last_group = true;
14 void add_unary_node(lexeme & current_lexeme, parse_tree_nodes & arguments)
16 parse_tree_node unary_operator_node;
17 lexeme_to_unary_operator_node(current_lexeme, unary_operator_node);
18 arguments.push_back(unary_operator_node);
21 void add_negation_lexeme(parse_tree_nodes & arguments)
23 add_unary_node(lexeme(lexeme_type::negation), arguments);
26 void parser::process_node_group(parse_tree_nodes & arguments, parse_tree_nodes & output)
28 parse_tree_node new_node;
29 operator_resolution(arguments, new_node);
30 output.push_back(new_node);
33 void parser::process_atomic_statement(lexeme_container & lexemes, std::size_t & offset, parse_tree_nodes & output, bool allow_multi_statements, lexeme_type::type terminator)
35 bool got_last_group = false;
36 lexeme_group::type last_group;
38 parse_tree_nodes arguments;
40 symbol_prefix::type prefix = symbol_prefix::none;
42 for(std::size_t & i = offset, end = lexemes.size(); i < end; i++)
44 lexeme & current_lexeme = lexemes[i];
46 if(current_lexeme.type == terminator)
48 i++;
49 break;
51 else if(prefix != symbol_prefix::none && current_lexeme.type != lexeme_type::name)
52 double_lexeme_error("Invalid use of a symbol prefix", i);
54 switch(current_lexeme.type)
56 case lexeme_type::scope_operator:
57 prefix = symbol_prefix::scope_operator;
58 continue;
60 case lexeme_type::class_operator:
61 prefix = symbol_prefix::class_operator;
62 continue;
64 case lexeme_type::bracket_start:
66 parse_tree_nodes content;
67 if(got_last_group && last_group == lexeme_group::argument)
69 process_atomic_statement(lexemes, offset, content, true, lexeme_type::bracket_end);
70 parse_tree_node call;
71 call.is_call();
72 call.call_pointer->arguments = content;
73 arguments.push_back(call);
75 else
77 process_atomic_statement(lexemes, offset, content, false, lexeme_type::bracket_end);
78 arguments.push_back(content[0]);
80 set_last_group(lexeme_group::argument, last_group, got_last_group);
81 break;
84 case lexeme_type::bracket_end:
85 error("Unmatched closing bracket");
87 case lexeme_type::array_start:
89 parse_tree_nodes elements;
90 process_atomic_statement(lexemes, offset, elements, true, lexeme_type::array_end);
91 arguments.push_back(parse_tree_node(elements));
92 set_last_group(lexeme_group::argument, last_group, got_last_group);
93 break;
96 case lexeme_type::array_end:
97 error("Unmatched curled brace");
99 case lexeme_type::call_operator:
100 arguments.push_back(parse_tree_node(parse_tree_node_type::call_operator));
101 set_last_group(lexeme_group::call_operator, last_group, got_last_group);
102 continue;
104 case lexeme_type::spaced_call_operator:
105 arguments.push_back(parse_tree_node(parse_tree_node_type::spaced_call_operator));
106 set_last_group(lexeme_group::call_operator, last_group, got_last_group);
107 continue;
109 case lexeme_type::iterator:
110 arguments.push_back(parse_tree_node(parse_tree_node_type::iterator));
111 set_last_group(lexeme_group::argument, last_group, got_last_group);
112 continue;
115 lexeme_group::type group;
116 if(!get_lexeme_group(current_lexeme.type, group))
117 single_lexeme_error("Invalid lexeme type in statement", i);
119 switch(group)
121 case lexeme_group::argument:
123 if(got_last_group && last_group == lexeme_group::argument)
125 if(allow_multi_statements)
127 process_node_group(arguments, output);
128 arguments.clear();
129 got_last_group = false;
131 else
132 double_lexeme_error("Encountered two arguments without an operator between them", i);
135 parse_tree_node argument_node;
136 lexeme_to_argument_node(current_lexeme, argument_node);
137 if(current_lexeme.type == lexeme_type::name)
139 argument_node.symbol_pointer->type = prefix;
140 if(prefix != symbol_prefix::none)
144 argument_node.type == parse_tree_node_type::binary_operator_node &&
145 argument_node.binary_operator_pointer->type == binary_operator_type::selection
147 double_lexeme_error("Encountered a symbol prefix after a selection operator", i);
148 prefix = symbol_prefix::none;
151 arguments.push_back(argument_node);
152 break;
155 case lexeme_group::unary_operator:
156 if(got_last_group && last_group == lexeme_group::argument)
157 double_lexeme_error("Encountered an argument followed by an unary operator without a binary operator between them", i);
158 add_unary_node(current_lexeme, arguments);
159 break;
161 case lexeme_group::binary_operator:
163 if(got_last_group)
165 switch(last_group)
167 case lexeme_group::unary_operator:
168 double_lexeme_error("Encountered a unary operator followed by a binary operator", i);
170 case lexeme_group::binary_operator:
171 if(current_lexeme.type == lexeme_type::subtraction)
172 add_negation_lexeme(arguments);
173 else
174 double_lexeme_error("Encountered two sequential binary operators", i);
175 break;
178 else
180 if(current_lexeme.type == lexeme_type::subtraction)
181 add_negation_lexeme(arguments);
182 else
183 single_lexeme_error("Encountered a binary operator in the beginning of a statement", i);
184 break;
187 parse_tree_node binary_operator_node;
188 lexeme_to_binary_operator_node(current_lexeme, binary_operator_node);
189 arguments.push_back(binary_operator_node);
190 break;
193 case lexeme_group::post_fix_operator:
194 if(got_last_group)
196 if(last_group != lexeme_group::argument)
197 single_lexeme_error("Encountered a post fix operator after a non-argument", i);
199 else
200 single_lexeme_error("A post fix operator requires a previous argument", i);
202 add_unary_node(current_lexeme, arguments);
203 set_last_group(lexeme_group::argument, last_group, got_last_group);
204 continue;
207 set_last_group(group, last_group, got_last_group);
210 if(!got_last_group)
211 error("Empty statement");
213 if(last_group != lexeme_group::argument)
214 error("An operator is missing an argument");
216 process_node_group(arguments, output);