2 #include <ail/file.hpp>
3 #include <ail/string.hpp>
4 #include <ail/string.hpp>
5 #include <fridh/intermediary.hpp>
6 #include <fridh/lexer.hpp>
10 intermediary_translator::intermediary_translator():
15 bool intermediary_translator::load_module(std::string
const & path
, std::string
const & name
, std::string
& error_message
);
18 if(!ail::read_file(path
, content
))
20 error_message
= "Unable to read file \"" + path
+ "\"";
25 bool success
= translate_data(module_output
, content
, error_message
);
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 void intermediary_translator::name_collision_check()
44 std::string
const & name
= get_declaration_name();
45 if(name_is_used(name
))
46 error("Name \"" + name
+ "\" has already been used by another function or class in the current scope");
49 symbol_tree_node
& intermediary_translator::add_name(symbol::type symbol_type
)
51 std::string
const & name
= get_declaration_name();
52 symbol_tree_node
& new_node
= current_node
->children
[name
];
53 new_node
= symbol_tree_node(symbol_type
);
54 new_node
.parent
= current_node
;
55 current_node
= &new_node
;
59 void intermediary_translator::process_body(function
* current_function
)
63 bool is_class
= (current_function
== 0);
70 if(process_line(current_function
))
76 current_node
= current_node
->parent
;
82 bool intermediary_translator::process_class()
84 lexeme_container
& lexemes
= lines
[line_offset
].lexemes
;
85 if(!(lexemes
.size() == 2 && lexemes
[0].type
== lexeme_type::class_operator
&& lexemes
[1].type
== lexeme_type::name
))
88 name_collision_check();
90 add_name(symbol::class_symbol
);
96 bool intermediary_translator::process_function()
98 lexeme_container
& lexemes
= lines
[line_offset
].lexemes
;
99 if(!(lexemes
.size() >= 2 && lexemes
[0].type
== lexeme_type::function_declaration
))
102 for(std::size_t i
= 1, end
= lexemes
.size(); i
< end
; i
++)
103 if(lexemes
[i
].type
!= lexeme_type::name
)
104 error("Encountered an invalid lexeme type in a function declaration - at this point only names are permitted");
106 name_collision_check();
108 function
& current_function
= *add_name(symbol::class_symbol
).function_pointer
;
109 for(std::size_t i
= 2, end
= lexemes
.size(); i
< end
; i
++)
110 current_function
.arguments
.push_back(*lexemes
[i
].string
);
116 void operator_resolution(parse_tree_nodes
& input
, parse_tree_node
& output
)
118 void call_check(std::size_t extremum_offset
)
120 if(extremum_offset
!= 1)
121 throw ail::exception("Invalid call offset encountered during operator resolution");
124 if(input
.size() != 1)
130 bool got_an_operator
= false;
132 std::size_t extremum_offset
;
134 for(std::size_t i
= 0, end
= input
.size(); i
< end
; i
++)
137 parse_tree_node
& current_node
= input
[i
];
138 if(get_parse_tree_node_precedence(current_node
, precedence
))
143 precedence
> extremum
||
144 (is_right_to_left_operator(current_node
) && precedence
== extremum
)
147 got_an_operator
= true;
148 extremum
= precedence
;
155 throw ail::exception("Failed to perform operator resolution");
157 parse_tree_node
& operator_node
= input
[extremum_offset
];
158 std::size_t next_offset
= extremum_offset
+ 1;
159 switch(operator_node
.type
)
161 case parse_tree_node_type::unary_operator_node
:
162 std::size_t argument_offset
= next_offset
;
163 parse_tree_unary_operator_node
& unary_operator_node
= *operator_node
.unary_operator_pointer
;
164 unary_operator_node
.argument
= input
.at(argument_offset
);
165 input
.erase(input
.begin() + argument_offset
);
168 case parse_tree_node_type::binary_operator_node
:
169 parse_tree_binary_operator_node
& binary_operator_node
= *operator_node
.binary_operator_pointer
;
175 std::copy(input
.begin(), input
.begin() + extremum_offset
, left_side
.begin());
176 std::copy(input
.begin() + next_offset
, input
.end(), right_side
.begin());
178 operator_resolution(left_side
, binary_operator_node
.left_argument
);
179 operator_resolution(right_side
, binary_operator_node
.right_argument
);
181 output
= operator_node
;
184 case parse_tree_node_type::call
:
185 //this is questionable
186 call_check(extremum_offset
);
187 operator_node
.call_pointer
->function
= input
[0];
188 input
.erase(input
.begin());
191 case parse_tree_node_type::call_operator
:
192 case parse_tree_node_type::spaced_call_operator
:
193 call_check(extremum_offset
);
194 operator_node
.is_call();
195 operator_node
.call_pointer
->function
= input
[0];
196 input
.erase(input
.begin());
197 if(operator_node
.type
!= parse_tree_node_type::spaced_call_operator
&& next_offset
!= input
.size())
200 operator_node
.call_pointer
->arguments
.push_back(input
[next_offset
]);
201 input
.erase(input
.end() - 1);
206 throw ail::exception("Invalid operator node type encountered during operator resolution");
210 void intermediary_translator::parse_statement(lexeme_container
& lexemes
, std::size_t & offset
, parse_tree_nodes
& output
, bool allow_multi_statements
, lexeme_type::type terminator
)
212 bool got_last_group
= false;
213 lexeme_group::type last_group
;
215 parse_tree_nodes arguments
;
217 void set_last_group(lexeme_group::type new_last_group
)
219 last_group
= new_last_group
;
220 got_last_group
= true;
223 void add_unary_node(lexeme
& current_lexeme
)
225 parse_tree_node unary_operator_node
;
226 lexeme_to_unary_operator_node(current_lexeme
, unary_operator_node
);
227 arguments
.push_back(unary_operator_node
);
230 void add_negation_lexeme()
232 add_unary_node(lexeme(lexeme_type::negation
));
235 void process_node_group()
237 parse_tree_node new_node
;
238 operator_resolution(arguments
, new_node
);
239 output
.push_back(new_node
);
242 symbol_prefix::type prefix
= symbol_prefix::none
;
244 for(std::size_t & i
= offset
, end
= lexemes
.size(); i
< end
; i
++)
246 lexeme
& current_lexeme
= lexemes
[i
];
248 if(current_lexeme
.type
== terminator
)
253 else if(prefix
!= symbol_prefix::none
&& current_lexeme
.type
== lexeme_type::name
)
254 error("Invalid use of a symbol prefix");
256 switch(current_lexeme
.type
)
258 case lexeme_type::scope_operator
:
259 prefix
= symbol_prefix::scope_operator
;
262 case lexeme_type::class_operator
:
263 prefix
= symbol_prefix::class_operator
;
266 case lexeme_type::bracket_start
:
268 parse_tree_nodes content
;
269 if(got_last_group
&& last_group
== lexeme_group::argument
)
271 parse_statement(lexemes
, offset
, content
, true, lexeme_type::bracket_end
);
272 parse_tree_node call
;
274 call
.call_pointer
->arguments
= content
;
275 arguments
.push_back(call
);
279 parse_statement(lexemes
, offset
, content
, false, lexeme_type::bracket_end
);
280 arguments
.push_back(content
[0]);
282 set_last_group(lexeme_group::argument
);
286 case lexeme_type::bracket_end
:
287 error("Unmatched closing bracket");
289 case lexeme_type::array_start
:
291 parse_tree_nodes elements
;
292 parse_statement(lexemes
, offset
, content
, true, lexeme_type::array_end
);
293 arguments
.push_back(parse_tree_node(elements
));
294 set_last_group(lexeme_group::argument
);
298 case lexeme_type::array_end
:
299 error("Unmatched curled brace");
301 case lexeme_type::call_operator
:
302 arguments
.push_back(parse_tree_node(parse_tree_node_type::call_operator
));
303 set_last_group(lexeme_group::call_operator
);
306 case lexeme_type::spaced_call_operator
:
307 arguments
.push_back(parse_tree_node(parse_tree_node_type::spaced_call_operator
));
308 set_last_group(lexeme_group::call_operator
);
312 lexeme_group::type group
;
313 if(!get_lexeme_group(current_lexeme
.type
, group
))
314 error("Invalid lexeme type in statement");
318 case lexeme_group::argument
:
320 if(!allow_multi_statements
&& !got_last_group
&& last_group
== lexeme_group::argument
)
321 error("Encountered two arguments without an operator between them");
323 parse_tree_node argument_node
;
324 lexeme_to_argument_node(current_lexeme
, argument_node
);
325 if(current_lexeme
.type
== lexeme_type::name
)
327 argument_node
.symbol_pointer
->type
= prefix
;
328 if(prefix
!= symbol_prefix::none
)
332 argument_node
.type
== parse_tree_node_type::binary_operator_node
&&
333 argument_node
.binary_operator_pointer
->type
== binary_operator_type::selection
335 error("Encountered a symbol prefix after a selection operator");
336 prefix
= symbol_prefix::none
;
339 arguments
.push_back(argument_node
);
341 if(allow_multi_statements
)
343 process_node_group();
345 got_last_group
= false;
351 case lexeme_group::unary_operator
:
352 if(got_last_group
&& last_group
== lexeme_group::argument
)
353 error("Encountered an argument followed by an unary operator without a binary operator between them");
354 add_unary_node(current_lexeme
);
357 case lexeme_group::binary_operator
:
362 case lexeme_group::unary_operator
:
363 error("Encountered a unary operator followed by a binary operator");
365 case lexeme_group::binary_operator
:
366 if(current_lexeme
.type
== lexeme_type::subtraction
)
367 add_negation_lexeme();
369 error("Encountered two sequential binary operators");
375 if(current_lexeme
.type
== lexeme_type::subtraction
)
376 add_negation_lexeme();
378 error("Encountered a binary operator in the beginning of a statement");
381 parse_tree_node binary_operator_node
;
382 lexeme_to_binary_operator_node(current_lexeme
, binary_operator_node
);
383 arguments
.push_back(binary_operator_node
);
387 set_last_group(group
);
391 error("Empty statement");
393 if(last_group
!= lexeme_group::argument
)
394 error("An operator is missing an argument");
396 process_node_group();
399 void intermediary_translator::process_statement(function
& current_function
)
403 bool intermediary_translator::process_line(function
* active_function
)
405 line_of_code
& current_line
= lines
[line_offset
];
406 if(current_line
.indentation_level
> indentation
)
407 error("Unexpected increase in the indentation level");
413 if(!process_function())
415 function
& current_function
= *active_function
;
416 process_statement(current_function
);
420 error("Regular statements and assignments need to be placed within functions");
425 if(line_offset
== line_end
)
427 //end of file -> end of the module entry function block
431 line_of_code
& next_line
= lines
[line_offset
];
433 if(next_line
.indentation_level
< indentation
)
442 bool intermediary_translator::translate_data(module
& target_module
, std::string
const & data
, std::string
const & module_name
, std::string
& error_message_output
)
444 lines
= std::vector
<line_of_code
>();
445 lexer
current_lexer(data
, lines
, error_message
);
446 if(!current_lexer
.parse())
449 current_node
= &target_module
.symbols
;
450 indentation_level
= 0;
451 nested_class_level
= 0;
453 while(line_offset
< line_end
)
460 void intermediary_translator::error(std::string
const & message
)
462 throw ail::exception("Line " + ail::number_to_string(lines
[line_offset
].line
) + ": " + message
);