Started removing some of the old wrong operator parsing code, implemented operator...
[fridhskrift.git] / intermediary / intermediary.cpp
blob0a22b82912bafdc5bcb8318392289f20a1e2d557
1 #include <stack>
2 #include <ail/file.hpp>
3 #include <ail/string.hpp>
4 #include <frith/intermediary.hpp>
5 #include <frith/lexer.hpp>
7 namespace frith
9 intermediary_translator::intermediary_translator():
10 running(false)
14 bool intermediary_translator::load_module(std::string const & path, std::string const & name, std::string & error_message);
16 std::string content;
17 if(!ail::read_file(path, content))
19 error_message = "Unable to read file \"" + path + "\"";
20 return false;
23 module module_output;
24 bool success = translate_data(module_output, content, error_message);
25 if(!success)
26 return false;
28 return true;
31 bool intermediary_translator::name_is_used(std::string const & name)
33 return current_node->exists(name);
36 std::string const & intermediary_translator::get_declaration_name()
38 return *lines[line_offset][1].string;
41 bool intermediary_translator::name_collision_check()
43 std::string const & name = get_declaration_name();
44 bool output = name_is_used(name);
45 if(output)
46 error("Name \"" + name + "\" has already been used by another function or class in the current scope");
47 return output;
50 symbol_tree_node & intermediary_translator::add_name(symbol::type symbol_type)
52 std::string const & name = get_declaration_name();
53 symbol_tree_node & new_node = current_node->children[name];
54 new_node = symbol_tree_node(symbol_type);
55 new_node.parent = current_node;
56 current_node = &new_node;
57 return new_node;
60 match_result::type intermediary_translator::process_body(function * current_function)
62 indentation++;
64 bool is_class = (current_function == 0);
66 if(is_class)
67 nested_class_level++;
69 while(true)
71 process_line_result::type result;
72 result = process_line(current_function);
73 if(result == match_result::error)
74 return process_line_result::error;
75 else if(result == process_line_result::end_of_block)
77 if(indentation > 0)
78 indentation--;
79 if(is_class)
80 nested_class_level--;
81 current_node = current_node->parent;
82 return match_result::match;
87 match_result::type intermediary_translator::process_class()
89 lexeme_container & lexemes = lines[line_offset].lexemes;
90 if(!(lexemes.size() == 2 && lexemes[0].type == lexeme_type::class_operator && lexemes[1].type == lexeme_type::name))
91 return match_result::no_match;
93 if(name_collision_check())
94 return match_result::error;
96 add_name(symbol::class_symbol);
98 return process_body(true);
101 match_result::type intermediary_translator::process_function()
103 lexeme_container & lexemes = lines[line_offset].lexemes;
104 if(!(lexemes.size() >= 2 && lexemes[0].type == lexeme_type::function_declaration))
105 return match_result::no_match;
107 for(std::size_t i = 1, end = lexemes.size(); i < end; i++)
109 if(lexemes[i].type != lexeme_type::name)
111 error("Encountered an invalid lexeme type in a function declaration - at this point only names are permitted");
112 return match_result::error;
116 if(name_collision_check())
117 return match_result::error;
119 function & current_function = *add_name(symbol::class_symbol).function_pointer;
120 for(std::size_t i = 2, end = lexemes.size(); i < end; i++)
121 current_function.arguments.push_back(*lexemes[i].string);
123 return process_body(false);
126 bool process_brackets(lexeme_container & lexemes, std::size_t & i, std::size_t end, parse_tree_symbols & arguments)
128 std::size_t bracket_start = i;
130 word bracket_level = 0;
132 for(std::size_t i = offset; i < end; i++)
134 switch(current_lexeme.type)
136 case lexeme_type::bracket_start:
137 if(bracket_level == 0)
138 bracket_start = i;
139 bracket_level++;
140 break;
142 case lexeme_type::bracket_start_call:
143 bracket_level++;
144 break;
146 case lexeme_type::bracket_end:
147 bracket_level--;
148 if(bracket_level == 0)
150 parse_tree_symbol new_argument;
151 if(!parse_statement(lexemes, bracket_start, i, new_argument))
152 return false;
153 arguments.push_back(new_argument);
154 return true;
156 break;
160 if(bracket_level > 0)
161 return error("Unmatched opening bracket");
163 return true;
166 void resolve_binary_operations(parse_tree_symbols & symbols, lexeme_container & binary_operators, parse_tree_node & output)
170 bool intermediary_translator::parse_statement(lexeme_container & lexemes, std::size_t offset, std::size_t end, parse_tree_node & output)
172 bool got_last_group = false;
173 lexeme_group::type last_group;
175 void set_last_group(lexeme_group::type new_last_group)
177 last_group = new_last_group;
178 got_last_group = true;
181 if(offset == end)
182 return error("Empty statement in line");
184 for(std::size_t i = offset; i < end; i++)
186 lexeme & current_lexeme = lexemes[i];
188 switch(current_lexeme.type)
190 case lexeme_type::bracket_start:
191 if(!process_brackets(lexemes, i, end, arguments))
192 return false;
193 set_last_group(lexeme_group::argument);
194 break;
196 case lexeme_type::bracket_start_call:
197 //process the call
198 set_last_group(lexeme_group::argument);
199 break;
201 case lexeme_type::bracket_end:
202 return error("Unmatched closing bracket");
205 lexeme_group::type group;
206 if(!get_lexeme_group(current_lexeme.type, group))
207 return error("Invalid lexeme type in statement");
209 switch(group)
211 case lexeme_group::argument:
213 if(got_last_group && last_group == lexeme_group::argument)
214 return error("Encountered two arguments without an operator between them");
216 parse_tree_node argument_node;
217 lexeme_to_argument_node(current_lexeme, argument_node);
218 break;
221 case lexeme_group::unary_operator:
222 if(got_last_group && last_group == lexeme_group::argument)
223 return error("Encountered an argument followed by an unary operator without a binary operator between them");
224 break;
226 case lexeme_group::binary_operator:
227 if(got_last_group)
229 switch(last_group)
231 case lexeme_group::unary_operator:
232 return error("Encountered a unary operator followed by a binary operator");
234 case lexeme_group::binary_operator:
235 return error("Encountered two sequential binary operators");
238 break;
241 set_last_group(group);
244 if(last_group != lexeme_group::argument)
245 return error("An operator is missing an argument");
247 return true;
250 bool intermediary_translator::process_statement(function & current_function)
254 process_line_result::type intermediary_translator::process_line(function * active_function)
256 line_of_code & current_line = lines[line_offset];
257 if(current_line.indentation_level > indentation)
259 error("Unexpected increase in the indentation level");
260 return process_line_result::error;
263 match_result::type result = process_class();
264 if(result == match_result::error)
265 return process_line_result::error;
266 else if(result == match_result::no_match)
268 if(active_function)
270 result = process_function();
271 if(result == match_result::error)
272 return process_line_result::error;
273 else if(result == match_result::no_match)
275 function & current_function = *active_function;
276 if(!process_statement(current_function))
277 return process_line_result::error;
280 else
282 error("Regular statements and assignments need to be placed within functions");
283 return process_line_result::error;
287 line_offset++;
289 if(line_offset == line_end)
291 //end of file -> end of the module entry function block
292 return process_line_result::end_of_block;
295 line_of_code & next_line = lines[line_offset];
297 if(next_line.indentation_level < indentation)
299 //end of block
300 return process_line_result::end_of_block;
302 else
303 return process_line_result::ok;
306 bool intermediary_translator::translate_data(module & target_module, std::string const & data, std::string const & module_name, std::string & error_message_output)
308 lines = std::vector<line_of_code>();
309 lexer current_lexer(data, lines, error_message);
310 if(!current_lexer.parse())
311 return false;
313 current_node = &target_module.symbols;
314 indentation_level = 0;
315 nested_class_level = 0;
317 while(line_offset < line_end)
321 return true;
324 bool intermediary_translator::error(std::string const & message)
326 error_message = "Line " + ail::number_to_string(lines[line_offset].line) + ": " + message;
327 return false;