A scope is now only left after a function or a class - I erroneously went up when...
[fridhskrift.git] / parser / parser.cpp
blobac8927b26a7d87776c960b21b9b7859de572b183
1 #include <ail/file.hpp>
2 #include <ail/string.hpp>
3 #include <fridh/parser.hpp>
4 #include <fridh/lexer.hpp>
6 namespace fridh
8 parser::parser():
9 running(false)
13 bool parser::process_module(std::string const & path, std::string const & name, module & output, std::string & error_message)
15 std::string content;
16 if(!ail::read_file(path, content))
18 error_message = "Unable to read file \"" + path + "\"";
19 return false;
22 module module_output;
23 bool success = translate_data(module_output, content, name, error_message);
24 if(!success)
25 return false;
27 return true;
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;
57 return new_node;
60 void parser::process_body(executable_units * output, bool increment)
62 if(increment)
64 line_offset++;
65 indentation_level++;
67 std::cout << "process_body" << std::endl;
70 bool is_class = (output == 0);
72 if(is_class)
73 nested_class_level++;
75 while(line_offset < line_end)
77 bool end;
78 if(is_class)
79 end = process_line(0);
80 else
82 executable_unit new_unit;
83 end = process_line(&new_unit);
84 output->push_back(new_unit);
86 if(end)
88 if(indentation_level == 0 && line_offset != line_end - 1)
89 error("Internal error: Invalid indentation level calculated");
91 indentation_level--;
93 if(is_class)
94 nested_class_level--;
96 break;
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))
105 return false;
107 name_collision_check();
109 add_name(symbol::class_symbol);
111 process_body(0);
113 scope_up();
115 return true;
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))
122 return false;
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;
131 if(output)
132 current_function = output;
133 else
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(&current_function->body);
141 scope_up();
143 return true;
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);
151 output = nodes[0];
153 line_offset++;
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())
172 if(output)
173 process_statement(*output);
174 else
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
181 return true;
184 line_of_code & next_line = lines[line_offset];
186 //end of block?
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))
198 return false;
200 current_node = &target_module.symbols;
201 indentation_level = 0;
202 nested_class_level = 0;
203 line_offset = 0;
204 line_end = lines.size();
206 process_body(&target_module.entry_function.body, false);
208 return true;
210 catch(ail::exception & exception)
212 error_message_output = module_name + ": " + exception.get_message();
213 return false;
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;