I believe to have implemented functions... also got the operator precedence the wrong...
[frith-skrift.git] / intermediary / intermediary.cpp
blob4d6b95a64c6440c10b7354e895907c8c0acc6f06
1 #include <stack>
2 #include <ail/file.hpp>
3 #include <ail/string.hpp>
4 #include <ail/string.hpp>
5 #include <frith/intermediary.hpp>
6 #include <frith/lexer.hpp>
8 namespace frith
10 intermediary_translator::intermediary_translator():
11 running(false)
15 bool intermediary_translator::load_module(std::string const & path, std::string const & name, std::string & error_message);
17 std::string content;
18 if(!ail::read_file(path, content))
20 error_message = "Unable to read file \"" + path + "\"";
21 return false;
24 module module_output;
25 bool success = translate_data(module_output, content, error_message);
26 if(!success)
27 return false;
29 return true;
32 bool intermediary_translator::name_is_used(std::string const & name)
34 return current_node->exists(name);
37 std::string const & intermediary_translator::get_declaration_name()
39 return *lines[line_offset][1].string;
42 bool intermediary_translator::name_collision_check()
44 std::string const & name = get_declaration_name();
45 bool output = name_is_used(name);
46 if(output)
47 error("Name \"" + name + "\" has already been used by another function or class in the current scope");
48 return output;
51 symbol_tree_node & intermediary_translator::add_name(symbol::type symbol_type)
53 std::string const & name = get_declaration_name();
54 symbol_tree_node & new_node = current_node->children[name];
55 new_node = symbol_tree_node(symbol_type);
56 new_node.parent = current_node;
57 current_node = &new_node;
58 return new_node;
61 match_result::type intermediary_translator::process_body(function * current_function)
63 indentation++;
65 bool is_class = (current_function == 0);
67 if(is_class)
68 nested_class_level++;
70 while(true)
72 process_line_result::type result;
73 result = process_line(current_function);
74 if(result == match_result::error)
75 return process_line_result::error;
76 else if(result == process_line_result::end_of_block)
78 if(indentation > 0)
79 indentation--;
80 if(is_class)
81 nested_class_level--;
82 current_node = current_node->parent;
83 return match_result::match;
88 match_result::type intermediary_translator::process_class()
90 lexeme_container & lexemes = lines[line_offset].lexemes;
91 if(!(lexemes.size() == 2 && lexemes[0].type == lexeme_type::class_operator && lexemes[1].type == lexeme_type::name))
92 return match_result::no_match;
94 if(name_collision_check())
95 return match_result::error;
97 add_name(symbol::class_symbol);
99 return process_body(true);
102 match_result::type intermediary_translator::process_function()
104 lexeme_container & lexemes = lines[line_offset].lexemes;
105 if(!(lexemes.size() >= 2 && lexemes[0].type == lexeme_type::function_declaration))
106 return match_result::no_match;
108 for(std::size_t i = 1, end = lexemes.size(); i < end; i++)
110 if(lexemes[i].type != lexeme_type::name)
112 error("Encountered an invalid lexeme type in a function declaration - at this point only names are permitted");
113 return match_result::error;
117 if(name_collision_check())
118 return match_result::error;
120 function & current_function = *add_name(symbol::class_symbol).function_pointer;
121 for(std::size_t i = 2, end = lexemes.size(); i < end; i++)
122 current_function.arguments.push_back(*lexemes[i].string);
124 return process_body(false);
127 void operator_resolution(parse_tree_nodes & input, parse_tree_node & output)
129 if(input.size() != 1)
131 output = input[0];
132 return;
135 bool got_an_operator = false;
136 word extremum;
137 std::size_t extremum_offset;
139 for(std::size_t i = 0, end = input.size(); i < end; i++)
141 word precedence;
142 parse_tree_node & current_node = input[i];
143 if(get_parse_tree_node_precedence(current_node, precedence))
147 !got_an_operator ||
148 precedence > extremum ||
149 (is_right_to_left_operator(current_node) && precedence == extremum)
152 got_an_operator = true;
153 extremum = precedence;
154 extremum_offset = i;
159 if(!got_an_operator)
160 throw ail::exception("Failed to perform operator resolution");
162 parse_tree_node & operator_node = input[extremum_offset];
163 std::size_t next_offset = extremum_offset + 1;
164 switch(operator_node.type)
166 case parse_tree_node_type::unary_operator_node:
167 std::size_t argument_offset = next_offset;
168 parse_tree_unary_operator_node & unary_operator_node = *operator_node.unary_operator_pointer;
169 unary_operator_node.argument = input.at(argument_offset);
170 input.erase(input.begin() + argument_offset);
171 break;
173 case parse_tree_node_type::binary_operator_node:
174 parse_tree_binary_operator_node & binary_operator_node = *operator_node.binary_operator_pointer;
176 parse_tree_nodes
177 left_side,
178 right_side;
180 std::copy(input.begin(), input.begin() + extremum_offset, left_side.begin());
181 std::copy(input.begin() + next_offset, input.end(), right_side.begin());
183 operator_resolution(left_side, binary_operator_node.left_argument);
184 operator_resolution(right_side, binary_operator_node.right_argument);
186 output = operator_node;
187 break;
189 case parse_tree_node_type::call:
190 //this is questionable
191 if(extremum_offset != 1)
192 throw ail::exception("Invalid call offset encountered during operator resolution");
193 operator_node.call_pointer->function = input[0];
194 input.erase(input.begin());
195 break;
197 default:
198 throw ail::exception("Invalid operator node type encountered during operator resolution");
202 bool intermediary_translator::parse_statement(lexeme_container & lexemes, std::size_t & offset, parse_tree_nodes & output, bool allow_multi_statements, lexeme_type::type terminator)
204 bool got_last_group = false;
205 lexeme_group::type last_group;
207 parse_tree_nodes arguments;
209 void set_last_group(lexeme_group::type new_last_group)
211 last_group = new_last_group;
212 got_last_group = true;
215 void add_unary_node(lexeme & current_lexeme)
217 parse_tree_node unary_operator_node;
218 lexeme_to_unary_operator_node(current_lexeme, unary_operator_node);
219 arguments.push_back(unary_operator_node);
222 void add_negation_lexeme()
224 add_unary_node(lexeme(lexeme_type::negation));
227 void process_node_group()
229 parse_tree_node new_node;
230 operator_resolution(arguments, new_node);
231 output.push_back(new_node);
234 for(std::size_t & i = offset, end = lexemes.size(); i < end; i++)
236 lexeme & current_lexeme = lexemes[i];
238 if(current_lexeme.type == terminator)
240 i++;
241 break;
244 switch(current_lexeme.type)
246 case lexeme_type::bracket_start:
248 parse_tree_nodes content;
249 if(got_last_group && last_group == lexeme_group::argument)
251 parse_statement(lexemes, offset, content, true, lexeme_type::bracket_end);
252 parse_tree_node call;
253 call.is_call();
254 call.call_pointer->arguments = content;
255 arguments.push_back(call);
257 else
259 parse_statement(lexemes, offset, content, false, lexeme_type::bracket_end);
260 arguments.push_back(content[0]);
262 set_last_group(lexeme_group::argument);
263 break;
266 case lexeme_type::bracket_end:
267 return error("Unmatched closing bracket");
269 case lexeme_type::array_start:
271 parse_tree_nodes elements;
272 parse_statement(lexemes, offset, content, true, lexeme_type::array_end);
273 arguments.push_back(parse_tree_node(elements));
274 set_last_group(lexeme_group::argument);
275 break;
278 case lexeme_type::array_end:
279 return error("Unmatched curled brace");
282 lexeme_group::type group;
283 if(!get_lexeme_group(current_lexeme.type, group))
284 return error("Invalid lexeme type in statement");
286 switch(group)
288 case lexeme_group::argument:
290 if(!allow_multi_statements && !got_last_group && last_group == lexeme_group::argument)
291 return error("Encountered two arguments without an operator between them");
293 parse_tree_node argument_node;
294 lexeme_to_argument_node(current_lexeme, argument_node);
295 arguments.push_back(argument_node);
297 if(allow_multi_statements)
299 process_node_group();
300 arguments.clear();
301 got_last_group = false;
302 continue;
304 break;
307 case lexeme_group::unary_operator:
308 if(got_last_group && last_group == lexeme_group::argument)
309 return error("Encountered an argument followed by an unary operator without a binary operator between them");
310 add_unary_node(current_lexeme);
311 break;
313 case lexeme_group::binary_operator:
314 if(got_last_group)
316 switch(last_group)
318 case lexeme_group::unary_operator:
319 return error("Encountered a unary operator followed by a binary operator");
321 case lexeme_group::binary_operator:
322 if(current_lexeme.type == lexeme_type::subtraction)
323 add_negation_lexeme();
324 else
325 return error("Encountered two sequential binary operators");
326 break;
329 else
331 if(current_lexeme.type == lexeme_type::subtraction)
332 add_negation_lexeme();
333 else
334 return error("Encountered a binary operator in the beginning of a statement");
335 break;
337 parse_tree_node binary_operator_node;
338 lexeme_to_binary_operator_node(current_lexeme, binary_operator_node);
339 arguments.push_back(binary_operator_node);
340 break;
343 set_last_group(group);
346 if(!got_last_group)
347 return error("Empty statement");
349 if(last_group != lexeme_group::argument)
350 return error("An operator is missing an argument");
352 process_node_group();
354 return true;
357 bool intermediary_translator::process_statement(function & current_function)
361 process_line_result::type intermediary_translator::process_line(function * active_function)
363 line_of_code & current_line = lines[line_offset];
364 if(current_line.indentation_level > indentation)
366 error("Unexpected increase in the indentation level");
367 return process_line_result::error;
370 match_result::type result = process_class();
371 if(result == match_result::error)
372 return process_line_result::error;
373 else if(result == match_result::no_match)
375 if(active_function)
377 result = process_function();
378 if(result == match_result::error)
379 return process_line_result::error;
380 else if(result == match_result::no_match)
382 function & current_function = *active_function;
383 if(!process_statement(current_function))
384 return process_line_result::error;
387 else
389 error("Regular statements and assignments need to be placed within functions");
390 return process_line_result::error;
394 line_offset++;
396 if(line_offset == line_end)
398 //end of file -> end of the module entry function block
399 return process_line_result::end_of_block;
402 line_of_code & next_line = lines[line_offset];
404 if(next_line.indentation_level < indentation)
406 //end of block
407 return process_line_result::end_of_block;
409 else
410 return process_line_result::ok;
413 bool intermediary_translator::translate_data(module & target_module, std::string const & data, std::string const & module_name, std::string & error_message_output)
415 lines = std::vector<line_of_code>();
416 lexer current_lexer(data, lines, error_message);
417 if(!current_lexer.parse())
418 return false;
420 current_node = &target_module.symbols;
421 indentation_level = 0;
422 nested_class_level = 0;
424 while(line_offset < line_end)
428 return true;
431 bool intermediary_translator::error(std::string const & message)
433 error_message = "Line " + ail::number_to_string(lines[line_offset].line) + ": " + message;
434 return false;