2 #include <ail/file.hpp>
3 #include <ail/string.hpp>
4 #include <frith/intermediary.hpp>
5 #include <frith/lexer.hpp>
9 intermediary_translator::intermediary_translator():
14 bool intermediary_translator::load_module(std::string
const & path
, std::string
const & name
, std::string
& error_message
);
17 if(!ail::read_file(path
, content
))
19 error_message
= "Unable to read file \"" + path
+ "\"";
24 bool success
= translate_data(module_output
, content
, error_message
);
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
);
46 error("Name \"" + name
+ "\" has already been used by another function or class in the current scope");
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
;
60 match_result::type
intermediary_translator::process_body(function
* current_function
)
64 bool is_class
= (current_function
== 0);
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
)
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)
142 case lexeme_type::bracket_start_call
:
146 case lexeme_type::bracket_end
:
148 if(bracket_level
== 0)
150 parse_tree_symbol new_argument
;
151 if(!parse_statement(lexemes
, bracket_start
, i
, new_argument
))
153 arguments
.push_back(new_argument
);
160 if(bracket_level
> 0)
161 return error("Unmatched opening bracket");
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;
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
))
193 set_last_group(lexeme_group::argument
);
196 case lexeme_type::bracket_start_call
:
198 set_last_group(lexeme_group::argument
);
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");
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
);
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");
226 case lexeme_group::binary_operator
:
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");
241 set_last_group(group
);
244 if(last_group
!= lexeme_group::argument
)
245 return error("An operator is missing an argument");
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
)
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
;
282 error("Regular statements and assignments need to be placed within functions");
283 return process_line_result::error
;
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
)
300 return process_line_result::end_of_block
;
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())
313 current_node
= &target_module
.symbols
;
314 indentation_level
= 0;
315 nested_class_level
= 0;
317 while(line_offset
< line_end
)
324 bool intermediary_translator::error(std::string
const & message
)
326 error_message
= "Line " + ail::number_to_string(lines
[line_offset
].line
) + ": " + message
;