1 #include <ail/file.hpp>
2 #include <ail/string.hpp>
3 #include <fridh/intermediary.hpp>
4 #include <fridh/lexer.hpp>
8 intermediary_translator::intermediary_translator():
13 bool intermediary_translator::load_module(std::string
const & path
, std::string
const & name
, std::string
& error_message
)
16 if(!ail::read_file(path
, content
))
18 error_message
= "Unable to read file \"" + path
+ "\"";
23 bool success
= translate_data(module_output
, content
, name
, error_message
);
30 bool intermediary_translator::name_is_used(std::string
const & name
)
32 return current_node
->exists(name
);
35 std::string
const & intermediary_translator::get_declaration_name()
37 return *lines
[line_offset
].lexemes
[1].string
;
40 void intermediary_translator::name_collision_check()
42 std::string
const & name
= get_declaration_name();
43 if(name_is_used(name
))
44 error("Name \"" + name
+ "\" has already been used by another function or class in the current scope");
47 symbol_tree_node
& intermediary_translator::add_name(symbol::type symbol_type
)
49 std::string
const & name
= get_declaration_name();
50 symbol_tree_node
& new_node
= *current_node
->children
[name
];
51 new_node
= symbol_tree_node(symbol_type
);
52 new_node
.parent
= current_node
;
53 current_node
= &new_node
;
57 void intermediary_translator::process_body(executable_units
* output
)
62 bool is_class
= (output
== 0);
67 while(line_offset
< line_end
)
71 end
= process_line(0);
74 executable_unit new_unit
;
75 process_line(&new_unit
);
76 output
->push_back(new_unit
);
80 if(indentation_level
> 0)
84 current_node
= current_node
->parent
;
90 bool intermediary_translator::process_class()
92 lexeme_container
& lexemes
= lines
[line_offset
].lexemes
;
93 if(!(lexemes
.size() == 2 && lexemes
[0].type
== lexeme_type::class_operator
&& lexemes
[1].type
== lexeme_type::name
))
96 name_collision_check();
98 add_name(symbol::class_symbol
);
104 bool intermediary_translator::process_function(function
* output
)
106 lexeme_container
& lexemes
= lines
[line_offset
].lexemes
;
107 if(!(lexemes
.size() >= 2 && lexemes
[0].type
== lexeme_type::function_declaration
))
110 for(std::size_t i
= 1, end
= lexemes
.size(); i
< end
; i
++)
111 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");
114 name_collision_check();
116 function
* current_function
;
118 current_function
= output
;
120 current_function
= add_name(symbol::class_symbol
).function_pointer
;
122 for(std::size_t i
= 2, end
= lexemes
.size(); i
< end
; i
++)
123 current_function
->arguments
.push_back(*lexemes
[i
].string
);
125 process_body(¤t_function
->body
);
129 void intermediary_translator::process_offset_atomic_statement(parse_tree_node
& output
, std::size_t offset
)
131 lexeme_container
& lexemes
= lines
[line_offset
].lexemes
;
132 parse_tree_nodes nodes
;
133 process_atomic_statement(lexemes
, offset
, nodes
);
138 void intermediary_translator::process_composite_term(parse_tree_node
& output
)
140 process_offset_atomic_statement(output
, 1);
143 bool intermediary_translator::process_line(executable_unit
* output
)
145 line_of_code
& current_line
= lines
[line_offset
];
146 if(current_line
.indentation_level
> indentation_level
)
147 error("Unexpected increase in the indentation level");
153 if(!process_function())
154 process_statement(*output
);
157 error("Regular statements and assignments need to be placed within functions");
162 if(line_offset
== line_end
)
164 //end of file -> end of the module entry function block
168 line_of_code
& next_line
= lines
[line_offset
];
171 return next_line
.indentation_level
< indentation_level
;
174 bool intermediary_translator::translate_data(module
& target_module
, std::string
const & data
, std::string
const & module_name
, std::string
& error_message_output
)
178 lines
= lines_of_code();
179 lexer
current_lexer(data
, lines
);
181 if(!current_lexer
.parse(error_message_output
))
184 current_node
= &target_module
.symbols
;
185 indentation_level
= 0;
186 nested_class_level
= 0;
188 process_function(&target_module
.entry_function
);
192 catch(ail::exception
& exception
)
194 error_message_output
= exception
.get_message();
199 void intermediary_translator::error(std::string
const & message
)
201 throw ail::exception("Line " + ail::number_to_string(lines
[line_offset
].line
) + ": " + message
);