1 #include <ail/file.hpp>
2 #include <ail/string.hpp>
3 #include <fridh/parser.hpp>
4 #include <fridh/lexer.hpp>
13 bool parser::process_module(std::string
const & path
, std::string
const & name
, module
& output
, 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 parser::name_is_used(std::string
const & name
)
32 return current_node
->exists(name
);
35 std::string
const & parser::get_declaration_name()
37 return *lines
[line_offset
].lexemes
[1].string
;
40 void parser::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
& parser::add_name(symbol::type symbol_type
)
49 std::string
const & name
= get_declaration_name();
50 symbol_tree_node
* & new_node_pointer
= current_node
->children
[name
];
51 new_node_pointer
= new symbol_tree_node(symbol_type
);
52 symbol_tree_node
& new_node
= *new_node_pointer
;
53 std::cout
<< "Its parent is " << (void *)current_node
<< std::endl
;
54 new_node
.parent
= current_node
;
55 current_node
= new_node_pointer
;
56 std::cout
<< "current_node = " << (void *)new_node_pointer
<< std::endl
;
60 void parser::process_body(executable_units
* output
, bool increment
)
67 std::cout
<< "process_body" << std::endl
;
70 bool is_class
= (output
== 0);
75 while(line_offset
< line_end
)
79 end
= process_line(0);
82 executable_unit new_unit
;
83 end
= process_line(&new_unit
);
84 output
->push_back(new_unit
);
88 if(indentation_level
== 0 && line_offset
!= line_end
- 1)
89 error("Internal error: Invalid indentation level calculated");
101 bool parser::process_class()
103 lexeme_container
& lexemes
= get_lexemes();
104 if(!(lexemes
.size() == 2 && lexemes
[0].type
== lexeme_type::class_operator
&& lexemes
[1].type
== lexeme_type::name
))
107 name_collision_check();
109 add_name(symbol::class_symbol
);
118 bool parser::process_function(function
* output
)
120 lexeme_container
& lexemes
= get_lexemes();
121 if(!(lexemes
.size() >= 2 && lexemes
[0].type
== lexeme_type::function_declaration
))
124 for(std::size_t i
= 1, end
= lexemes
.size(); i
< end
; i
++)
125 if(lexemes
[i
].type
!= lexeme_type::name
)
126 error("Encountered an invalid lexeme type in a function declaration - at this point only names are permitted");
128 name_collision_check();
130 function
* current_function
;
132 current_function
= output
;
134 current_function
= add_name(symbol::function
).function_pointer
;
136 for(std::size_t i
= 2, end
= lexemes
.size(); i
< end
; i
++)
137 current_function
->arguments
.push_back(*lexemes
[i
].string
);
139 process_body(¤t_function
->body
);
146 void parser::process_offset_atomic_statement(parse_tree_node
& output
, std::size_t offset
)
148 lexeme_container
& lexemes
= get_lexemes();
149 parse_tree_nodes nodes
;
150 process_atomic_statement(lexemes
, offset
, nodes
);
154 std::cout
<< "process_offset_atomic_statement" << std::endl
;
157 void parser::process_composite_term(parse_tree_node
& output
)
159 process_offset_atomic_statement(output
, 1);
162 bool parser::process_line(executable_unit
* output
)
164 line_of_code
& current_line
= lines
[line_offset
];
165 std::cout
<< "Line " << current_line
.line
<< ": " << current_line
.indentation_level
<< std::endl
;
167 if(current_line
.indentation_level
> indentation_level
)
168 error("Unexpected increase in the indentation level (" + ail::number_to_string(indentation_level
) + " to " + ail::number_to_string(current_line
.indentation_level
) + ")");
170 if(!process_class() && !process_function())
173 process_statement(*output
);
175 error("Regular statements need to be placed within functions");
178 if(line_offset
== line_end
)
180 //end of file -> end of the module entry function block
184 line_of_code
& next_line
= lines
[line_offset
];
187 return next_line
.indentation_level
< indentation_level
;
190 bool parser::translate_data(module
& target_module
, std::string
const & data
, std::string
const & module_name
, std::string
& error_message_output
)
194 lines
= lines_of_code();
195 lexer
current_lexer(data
, lines
);
197 if(!current_lexer
.parse(error_message_output
))
200 current_node
= &target_module
.symbols
;
201 indentation_level
= 0;
202 nested_class_level
= 0;
204 line_end
= lines
.size();
206 process_body(&target_module
.entry_function
.body
, false);
210 catch(ail::exception
& exception
)
212 error_message_output
= module_name
+ ": " + exception
.get_message();
217 lexeme_container
& parser::get_lexemes()
219 return lines
[line_offset
].lexemes
;
222 void parser::error(std::string
const & message
)
224 throw ail::exception("Line " + ail::number_to_string(lines
[line_offset
].line
) + ": " + message
);
227 void parser::single_lexeme_error(std::string
const & message
, std::size_t offset
)
229 lexeme_container
& lexemes
= get_lexemes();
230 error(message
+ " (\"" + lexemes
[offset
].to_string() + "\")");
233 void parser::double_lexeme_error(std::string
const & message
, std::size_t offset
)
235 lexeme_container
& lexemes
= get_lexemes();
236 error(message
+ " (\"" + lexemes
[offset
- 1].to_string() + "\", \"" + lexemes
[offset
].to_string() + "\")");
239 void parser::scope_up()
241 std::cout
<< "current_node: " << (void *)current_node
<< " -> " << current_node
->parent
<< std::endl
;
242 current_node
= current_node
->parent
;