Fixed some further references to "intermediary", moved a few files into more fitting...
[fridhskrift.git] / parser / statement.cpp
blob3436ece454524c286c5bcdc847911c41b132a9b4
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 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 error("Invalid use of a symbol prefix");
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 error("Invalid lexeme type in statement");
119 switch(group)
121 case lexeme_group::argument:
123 if(!allow_multi_statements && !got_last_group && last_group == lexeme_group::argument)
124 error("Encountered two arguments without an operator between them");
126 parse_tree_node argument_node;
127 lexeme_to_argument_node(current_lexeme, argument_node);
128 if(current_lexeme.type == lexeme_type::name)
130 argument_node.symbol_pointer->type = prefix;
131 if(prefix != symbol_prefix::none)
135 argument_node.type == parse_tree_node_type::binary_operator_node &&
136 argument_node.binary_operator_pointer->type == binary_operator_type::selection
138 error("Encountered a symbol prefix after a selection operator");
139 prefix = symbol_prefix::none;
142 arguments.push_back(argument_node);
144 if(allow_multi_statements)
146 process_node_group(arguments, output);
147 arguments.clear();
148 got_last_group = false;
149 continue;
151 break;
154 case lexeme_group::unary_operator:
155 if(got_last_group && last_group == lexeme_group::argument)
156 error("Encountered an argument followed by an unary operator without a binary operator between them");
157 add_unary_node(current_lexeme, arguments);
158 break;
160 case lexeme_group::binary_operator:
161 if(got_last_group)
163 switch(last_group)
165 case lexeme_group::unary_operator:
166 error("Encountered a unary operator followed by a binary operator");
168 case lexeme_group::binary_operator:
169 if(current_lexeme.type == lexeme_type::subtraction)
170 add_negation_lexeme(arguments);
171 else
172 error("Encountered two sequential binary operators");
173 break;
176 else
178 if(current_lexeme.type == lexeme_type::subtraction)
179 add_negation_lexeme(arguments);
180 else
181 error("Encountered a binary operator in the beginning of a statement");
182 break;
184 parse_tree_node binary_operator_node;
185 lexeme_to_binary_operator_node(current_lexeme, binary_operator_node);
186 arguments.push_back(binary_operator_node);
187 break;
190 set_last_group(group, last_group, got_last_group);
193 if(!got_last_group)
194 error("Empty statement");
196 if(last_group != lexeme_group::argument)
197 error("An operator is missing an argument");
199 process_node_group(arguments, output);