Symbol node allocation was missing
[fridhskrift.git] / parser / parser.cpp
blob3416a8dc17ae04ed182708e61f154e147890a188
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;
52 symbol_tree_node & new_node = *new_node_pointer;
53 new_node = symbol_tree_node(symbol_type);
54 new_node.parent = current_node;
55 current_node = &new_node;
56 return new_node;
59 void parser::process_body(executable_units * output)
61 line_offset++;
62 indentation_level++;
64 bool is_class = (output == 0);
66 if(is_class)
67 nested_class_level++;
69 while(line_offset < line_end)
71 bool end;
72 if(is_class)
73 end = process_line(0);
74 else
76 executable_unit new_unit;
77 process_line(&new_unit);
78 output->push_back(new_unit);
80 if(end)
82 if(indentation_level > 0)
83 indentation_level--;
84 if(is_class)
85 nested_class_level--;
86 current_node = current_node->parent;
87 break;
92 bool parser::process_class()
94 lexeme_container & lexemes = lines[line_offset].lexemes;
95 if(!(lexemes.size() == 2 && lexemes[0].type == lexeme_type::class_operator && lexemes[1].type == lexeme_type::name))
96 return false;
98 name_collision_check();
100 add_name(symbol::class_symbol);
102 process_body(0);
103 return true;
106 bool parser::process_function(function * output)
108 lexeme_container & lexemes = lines[line_offset].lexemes;
109 if(!(lexemes.size() >= 2 && lexemes[0].type == lexeme_type::function_declaration))
110 return false;
112 for(std::size_t i = 1, end = lexemes.size(); i < end; i++)
113 if(lexemes[i].type != lexeme_type::name)
114 error("Encountered an invalid lexeme type in a function declaration - at this point only names are permitted");
116 name_collision_check();
118 function * current_function;
119 if(output)
120 current_function = output;
121 else
122 current_function = add_name(symbol::class_symbol).function_pointer;
124 for(std::size_t i = 2, end = lexemes.size(); i < end; i++)
125 current_function->arguments.push_back(*lexemes[i].string);
127 process_body(&current_function->body);
128 return true;
131 void parser::process_offset_atomic_statement(parse_tree_node & output, std::size_t offset)
133 lexeme_container & lexemes = lines[line_offset].lexemes;
134 parse_tree_nodes nodes;
135 process_atomic_statement(lexemes, offset, nodes);
136 output = nodes[0];
137 line_offset++;
140 void parser::process_composite_term(parse_tree_node & output)
142 process_offset_atomic_statement(output, 1);
145 bool parser::process_line(executable_unit * output)
147 line_of_code & current_line = lines[line_offset];
148 if(current_line.indentation_level > indentation_level)
149 error("Unexpected increase in the indentation level");
151 if(!process_class())
153 if(output)
155 if(!process_function())
156 process_statement(*output);
158 else
159 error("Regular statements and assignments need to be placed within functions");
162 line_offset++;
164 if(line_offset == line_end)
166 //end of file -> end of the module entry function block
167 return true;
170 line_of_code & next_line = lines[line_offset];
172 //end of block?
173 return next_line.indentation_level < indentation_level;
176 bool parser::translate_data(module & target_module, std::string const & data, std::string const & module_name, std::string & error_message_output)
180 lines = lines_of_code();
181 lexer current_lexer(data, lines);
183 if(!current_lexer.parse(error_message_output))
184 return false;
186 current_node = &target_module.symbols;
187 indentation_level = 0;
188 nested_class_level = 0;
189 line_offset = 0;
191 process_body(&target_module.entry_function.body);
193 return true;
195 catch(ail::exception & exception)
197 error_message_output = exception.get_message();
198 return false;
202 void parser::error(std::string const & message)
204 throw ail::exception("Line " + ail::number_to_string(lines[line_offset].line) + ": " + message);