Fixed all of the syntax problems. Dealing with 3 bizarre linking problems now.
[fridhskrift.git] / intermediary / intermediary.cpp
blobceab40234a85a11e1709bd251261c033ab8bdc38
1 #include <ail/file.hpp>
2 #include <ail/string.hpp>
3 #include <fridh/intermediary.hpp>
4 #include <fridh/lexer.hpp>
6 namespace fridh
8 intermediary_translator::intermediary_translator():
9 running(false)
13 bool intermediary_translator::load_module(std::string const & path, std::string const & name, 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 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;
54 return new_node;
57 void intermediary_translator::process_body(executable_units * output)
59 line_offset++;
60 indentation_level++;
62 bool is_class = (output == 0);
64 if(is_class)
65 nested_class_level++;
67 while(line_offset < line_end)
69 bool end;
70 if(is_class)
71 end = process_line(0);
72 else
74 executable_unit new_unit;
75 process_line(&new_unit);
76 output->push_back(new_unit);
78 if(end)
80 if(indentation_level > 0)
81 indentation_level--;
82 if(is_class)
83 nested_class_level--;
84 current_node = current_node->parent;
85 break;
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))
94 return false;
96 name_collision_check();
98 add_name(symbol::class_symbol);
100 process_body(0);
101 return true;
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))
108 return false;
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;
117 if(output)
118 current_function = output;
119 else
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(&current_function->body);
126 return true;
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);
134 output = nodes[0];
135 line_offset++;
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");
149 if(!process_class())
151 if(output)
153 if(!process_function())
154 process_statement(*output);
156 else
157 error("Regular statements and assignments need to be placed within functions");
160 line_offset++;
162 if(line_offset == line_end)
164 //end of file -> end of the module entry function block
165 return true;
168 line_of_code & next_line = lines[line_offset];
170 //end of block?
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))
182 return false;
184 current_node = &target_module.symbols;
185 indentation_level = 0;
186 nested_class_level = 0;
188 process_function(&target_module.entry_function);
190 return true;
192 catch(ail::exception & exception)
194 error_message_output = exception.get_message();
195 return false;
199 void intermediary_translator::error(std::string const & message)
201 throw ail::exception("Line " + ail::number_to_string(lines[line_offset].line) + ": " + message);