diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6d95090..26332d9 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,11 +55,16 @@ elseif(BISON_VERSION VERSION_LESS 3.0)
message("== Bison 2.5 was found. You have to apply cmake/bison2.patch...")
endif()
-## 3. Build
+## 3. Boost components
+
+find_package(Boost 1.54 REQUIRED)
+
+## 4. Build
include_directories(
${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
+ ${Boost_INCLUDE_DIRS}
)
add_definitions(-Wall -Wno-deprecated-register -std=c++0x -DYYDEBUG=0 -O2)
@@ -70,6 +75,10 @@ add_flex_bison_dependency(Scanner Parser)
add_executable(
mcc
- main.cpp Nodes.cpp ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS}
+ main.cpp
+ ${BISON_Parser_OUTPUTS} ${FLEX_Scanner_OUTPUTS}
+ CppEmitter.cpp
)
+target_link_libraries(mcc ${Boost_LIBRARIES})
+
diff --git a/CppEmitter.cpp b/CppEmitter.cpp
new file mode 100644
index 0000000..15ceada
--- /dev/null
+++ b/CppEmitter.cpp
@@ -0,0 +1,381 @@
+/*
+ * Monicelli: an esoteric language compiler
+ *
+ * Copyright (C) 2014 Stefano Sanfilippo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include
+
+#include "Nodes.hpp"
+#include "CppEmitter.hpp"
+#include "Pointers.hpp"
+
+using namespace monicelli;
+
+
+static const std::string STATEMENT_TERMINATOR = ";\n";
+static const std::string BLOCK = " ";
+static const int BLOCK_SIZE = 4;
+
+
+void CppEmitter::indent() {
+ indent_chars += BLOCK_SIZE;
+}
+
+void CppEmitter::dedent() {
+ indent_chars -= BLOCK_SIZE;
+}
+
+void CppEmitter::emitIndent() {
+ for (int i = 0; i < indent_chars; ++i) {
+ stream << BLOCK;
+ }
+}
+
+void CppEmitter::emit(Program const& program) {
+ for (Module m: program.getModules()) {
+ m.emit(this);
+ stream << "\n";
+ }
+
+ if (!program.getModules().empty()) {
+ stream << "\n";
+ }
+
+ for (Function *function: program.getFunctions()) {
+ emitFunctionSignature(*function);
+ stream << ";\n";
+ }
+
+ if (!program.getFunctions().empty()) {
+ stream << "\n";
+ }
+
+ for (Function *function: program.getFunctions()) {
+ function->emit(this);
+ }
+
+ if (program.getMain()) {
+ program.getMain()->emit(this);
+ }
+}
+
+void CppEmitter::emitStatements(PointerList const& node) {
+ for (Statement *s: node) {
+ s->emit(this);
+ stream << STATEMENT_TERMINATOR;
+ }
+}
+
+void CppEmitter::emit(Main const& main) {
+ stream << "int main() {\n";
+ emitStatements(main.getBody());
+ stream << "}\n";
+}
+
+void CppEmitter::emit(Id const& id) {
+ stream << id.getValue();
+}
+
+void CppEmitter::emit(Integer const& num) {
+ stream << num.getValue();
+}
+
+void CppEmitter::emit(Float const& num) {
+ stream << num.getValue();
+}
+
+void CppEmitter::emit(Return const& node) {
+ stream << "return";
+
+ if (node.getExpression()) {
+ stream << ' ';
+ node.getExpression()->emit(this);
+ }
+}
+
+void CppEmitter::emit(Print const& node) {
+ bool needsBraces =
+ (dynamic_cast(&node.getExpression()) == nullptr)
+ &&
+ (dynamic_cast(&node.getExpression()) == nullptr)
+ ;
+
+ stream << "std::cout << ";
+ if (needsBraces) {
+ stream << '(';
+ }
+
+ node.getExpression().emit(this);
+
+ if (needsBraces) {
+ stream << ')';
+ }
+ stream << " << std::endl";
+}
+
+void CppEmitter::emit(Input const& node) {
+ stream << "std::cout << \"";
+ node.getVariable().emit(this);
+ stream << "? \";\n";
+ stream << "std::cin >> ";
+ node.getVariable().emit(this);
+}
+
+void CppEmitter::emit(Abort const&) {
+ stream << "std::exit(1)";
+}
+
+void CppEmitter::emit(Assert const& node) {
+ stream << "assert(";
+ node.getExpression().emit(this);
+ stream << ")";
+}
+
+void CppEmitter::emit(Loop const& loop) {
+ stream << "do {\n";
+ emitStatements(loop.getBody());
+ stream << "} while (";
+ loop.getCondition().emit(this);
+ stream << ")";
+}
+
+void CppEmitter::emit(BranchCase const& node) {
+ node.getCondition().emit(this);
+ stream << ") {\n";
+ emitStatements(node.getBody());
+ stream << "}";
+}
+
+void CppEmitter::emit(Branch const& branch) {
+ auto &body = branch.getBody();
+ auto &var = branch.getVar();
+
+ stream << "if (";
+ var.emit(this);
+
+ if (body.getCases().size() > 0) {
+ BranchCase *last = body.getCases().back();
+ for (BranchCase *cas: body.getCases()) {
+ cas->emit(this);
+ if (cas != last) {
+ stream << " else if (";
+ var.emit(this);
+ }
+ }
+ }
+
+ if (!body.getElse()) {
+ return;
+ }
+
+ stream << " else {\n";
+ emitStatements(*body.getElse());
+ stream << "}";
+}
+
+void CppEmitter::emit(Assignment const& assignment) {
+ assignment.getName().emit(this);
+ stream << " = ";
+ assignment.getValue().emit(this);
+}
+
+
+void CppEmitter::emitFunctionArglist(PointerList const& args) {
+ Expression *last = args.back();
+ for (Expression const* arg: args) {
+ arg->emit(this);
+ if (arg != last) {
+ stream << ", ";
+ }
+ }
+}
+
+
+void CppEmitter::emit(FunctionCall const& funcall) {
+ funcall.getName().emit(this);
+ stream << "(";
+ emitFunctionArglist(funcall.getArgs());
+ stream << ")";
+}
+
+void CppEmitter::emit(Function const& function) {
+ emitFunctionSignature(function);
+ stream << " {\n";
+ emitStatements(function.getBody());
+ stream << "}\n\n";
+}
+
+std::ostream& operator<<(std::ostream &stream, Type const& type) {
+ switch (type) {
+ case Type::INT:
+ stream << "int";
+ break;
+ case Type::CHAR:
+ stream << "char";
+ break;
+ case Type::FLOAT:
+ stream << "float";
+ break;
+ case Type::BOOL:
+ stream << "bool";
+ break;
+ case Type::DOUBLE:
+ stream << "double";
+ break;
+ case Type::VOID:
+ stream << "void";
+ break;
+ }
+
+ return stream;
+}
+
+void CppEmitter::emitFunctionParams(PointerList const& funargs) {
+ FunArg *last = funargs.back();
+
+ for (FunArg const* funarg: funargs) {
+ stream << funarg->getType() << (funarg->isPointer()? "* ": " ");
+ funarg->getName().emit(this);
+ if (funarg != last) {
+ stream << ", ";
+ }
+ }
+}
+
+void CppEmitter::emit(Module const& module) {
+ bool system = (module.getType() == Module::SYSTEM);
+ stream << "#include " << (system? '<': '"') << module.getName() << (system? '>': '"');
+}
+
+void CppEmitter::emitFunctionSignature(Function const& function) {
+ stream << function.getType() << ' ';
+ function.getName().emit(this);
+ stream << "(";
+ emitFunctionParams(function.getArgs());
+ stream << ")";
+}
+
+void CppEmitter::emit(VarDeclaration const& decl) {
+ stream << decl.getType() << ' ';
+ if (decl.isPointer()) stream << '*';
+ decl.getId().emit(this);
+
+ if (decl.getInitializer()) {
+ stream << " = ";
+ decl.getInitializer()->emit(this);
+ }
+}
+
+void CppEmitter::emitExp(char const* symbol, ExpNode const& node) {
+ node.getLeft().emit(this);
+ stream << ' ' << symbol << ' ';
+ node.getRight().emit(this);
+}
+
+void CppEmitter::emitSemiExp(char const* symbol, SemiExpNode const& node) {
+ bool braces = (dynamic_cast(&node.getLeft()) == nullptr);
+
+ stream << ' ' << symbol << ' ';
+ if (braces) stream << "(";
+ node.getLeft().emit(this);
+ if (braces) stream << ")";
+}
+
+void CppEmitter::emit(ExpLt const& node) {
+ emitExp("<", node);
+}
+
+void CppEmitter::emit(ExpGt const& node) {
+ emitExp(">", node);
+}
+
+void CppEmitter::emit(ExpLte const& node) {
+ emitExp("<=", node);
+}
+
+void CppEmitter::emit(ExpGte const& node) {
+ emitExp(">=", node);
+}
+
+void CppEmitter::emit(ExpPlus const& node) {
+ emitExp("+", node);
+}
+
+void CppEmitter::emit(ExpMinus const& node) {
+ emitExp("-", node);
+}
+
+void CppEmitter::emit(ExpTimes const& node) {
+ emitExp("*", node);
+}
+
+void CppEmitter::emit(ExpDiv const& node) {
+ emitExp("/", node);
+}
+
+void CppEmitter::emit(ExpShl const& node) {
+ emitExp("<<", node);
+}
+
+void CppEmitter::emit(ExpShr const& node) {
+ emitExp(">>", node);
+}
+
+void CppEmitter::emit(SemiExpEq const& node) {
+ emitSemiExp("==", node);
+}
+
+void CppEmitter::emit(SemiExpLt const& node) {
+ emitSemiExp("<", node);
+}
+
+void CppEmitter::emit(SemiExpGt const& node) {
+ emitSemiExp(">", node);
+}
+
+void CppEmitter::emit(SemiExpLte const& node) {
+ emitSemiExp("<=", node);
+}
+
+void CppEmitter::emit(SemiExpGte const& node) {
+ emitSemiExp(">=", node);
+}
+
+void CppEmitter::emit(SemiExpPlus const& node) {
+ emitSemiExp("+", node);
+}
+
+void CppEmitter::emit(SemiExpMinus const& node) {
+ emitSemiExp("-", node);
+}
+
+void CppEmitter::emit(SemiExpTimes const& node) {
+ emitSemiExp("*", node);
+}
+
+void CppEmitter::emit(SemiExpDiv const& node) {
+ emitSemiExp("/", node);
+}
+
+void CppEmitter::emit(SemiExpShl const& node) {
+ emitSemiExp("<<", node);
+}
+
+void CppEmitter::emit(SemiExpShr const& node) {
+ emitSemiExp(">>", node);
+}
+
diff --git a/CppEmitter.hpp b/CppEmitter.hpp
new file mode 100644
index 0000000..3df8696
--- /dev/null
+++ b/CppEmitter.hpp
@@ -0,0 +1,93 @@
+#ifndef CPPEMITTER_HPP
+#define CPPEMITTER_HPP
+
+/*
+ * Monicelli: an esoteric language compiler
+ *
+ * Copyright (C) 2014 Stefano Sanfilippo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+#include "Emitter.hpp"
+
+#include
+
+
+namespace monicelli {
+
+class CppEmitter: public Emitter {
+public:
+ CppEmitter(std::ostream *stream): stream(*stream), indent_chars(0) {}
+
+ virtual void emit(Id const&) override;
+ virtual void emit(Integer const&) override;
+ virtual void emit(Float const&) override;
+ virtual void emit(Return const&) override;
+ virtual void emit(Loop const&) override;
+ virtual void emit(VarDeclaration const&) override;
+ virtual void emit(Assignment const&) override;
+ virtual void emit(Print const&) override;
+ virtual void emit(Input const&) override;
+ virtual void emit(Abort const&) override;
+ virtual void emit(Assert const&) override;
+ virtual void emit(FunctionCall const&) override;
+ virtual void emit(BranchCase const&) override;
+ virtual void emit(Branch const&) override;
+ virtual void emit(Main const&) override;
+ virtual void emit(Function const&) override;
+ virtual void emit(Module const&) override;
+ virtual void emit(Program const&) override;
+ virtual void emit(ExpLt const&) override;
+ virtual void emit(ExpGt const&) override;
+ virtual void emit(ExpLte const&) override;
+ virtual void emit(ExpGte const&) override;
+ virtual void emit(ExpPlus const&) override;
+ virtual void emit(ExpMinus const&) override;
+ virtual void emit(ExpTimes const&) override;
+ virtual void emit(ExpDiv const&) override;
+ virtual void emit(ExpShl const&) override;
+ virtual void emit(ExpShr const&) override;
+ virtual void emit(SemiExpEq const&) override;
+ virtual void emit(SemiExpLt const&) override;
+ virtual void emit(SemiExpGt const&) override;
+ virtual void emit(SemiExpLte const&) override;
+ virtual void emit(SemiExpGte const&) override;
+ virtual void emit(SemiExpPlus const&) override;
+ virtual void emit(SemiExpMinus const&) override;
+ virtual void emit(SemiExpTimes const&) override;
+ virtual void emit(SemiExpDiv const&) override;
+ virtual void emit(SemiExpShl const&) override;
+ virtual void emit(SemiExpShr const&) override;
+
+private:
+ void emitIndent();
+ void emitExp(char const* symbol, ExpNode const& node);
+ void emitSemiExp(char const* symbol, SemiExpNode const& node);
+ void emitFunctionSignature(Function const& function);
+ void emitFunctionParams(PointerList const& funargs);
+ void emitFunctionArglist(PointerList const& args);
+ void emitStatements(PointerList const& node);
+
+ void indent();
+ void dedent();
+
+ std::ostream &stream;
+ int indent_chars;
+};
+
+}
+
+#endif
+
diff --git a/Emitter.hpp b/Emitter.hpp
new file mode 100644
index 0000000..66d6da3
--- /dev/null
+++ b/Emitter.hpp
@@ -0,0 +1,113 @@
+#ifndef EMITTER_HPP
+#define EMITTER_HPP
+
+/*
+ * Monicelli: an esoteric language compiler
+ *
+ * Copyright (C) 2014 Stefano Sanfilippo
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see .
+ */
+
+namespace monicelli {
+
+class Id;
+class Number;
+class Integer;
+class Float;
+class Return;
+class Loop;
+class VarDeclaration;
+class Assignment;
+class Print;
+class Input;
+class Abort;
+class Assert;
+class FunctionCall;
+class BranchCase;
+class Branch;
+class Main;
+class Function;
+class Module;
+class Program;
+class ExpLt;
+class ExpGt;
+class ExpLte;
+class ExpGte;
+class ExpPlus;
+class ExpMinus;
+class ExpTimes;
+class ExpDiv;
+class ExpShl;
+class ExpShr;
+class SemiExpEq;
+class SemiExpLt;
+class SemiExpGt;
+class SemiExpLte;
+class SemiExpGte;
+class SemiExpPlus;
+class SemiExpMinus;
+class SemiExpTimes;
+class SemiExpDiv;
+class SemiExpShl;
+class SemiExpShr;
+
+
+class Emitter {
+public:
+ virtual void emit(Id const&) = 0;
+ virtual void emit(Integer const&) = 0;
+ virtual void emit(Float const&) = 0;
+ virtual void emit(Return const&) = 0;
+ virtual void emit(Loop const&) = 0;
+ virtual void emit(VarDeclaration const&) = 0;
+ virtual void emit(Assignment const&) = 0;
+ virtual void emit(Print const&) = 0;
+ virtual void emit(Input const&) = 0;
+ virtual void emit(Abort const&) = 0;
+ virtual void emit(Assert const&) = 0;
+ virtual void emit(FunctionCall const&) = 0;
+ virtual void emit(BranchCase const&) = 0;
+ virtual void emit(Branch const&) = 0;
+ virtual void emit(Main const&) = 0;
+ virtual void emit(Function const&) = 0;
+ virtual void emit(Module const&) = 0;
+ virtual void emit(Program const&) = 0;
+ virtual void emit(ExpLt const&) = 0;
+ virtual void emit(ExpGt const&) = 0;
+ virtual void emit(ExpLte const&) = 0;
+ virtual void emit(ExpGte const&) = 0;
+ virtual void emit(ExpPlus const&) = 0;
+ virtual void emit(ExpMinus const&) = 0;
+ virtual void emit(ExpTimes const&) = 0;
+ virtual void emit(ExpDiv const&) = 0;
+ virtual void emit(ExpShl const&) = 0;
+ virtual void emit(ExpShr const&) = 0;
+ virtual void emit(SemiExpEq const&) = 0;
+ virtual void emit(SemiExpLt const&) = 0;
+ virtual void emit(SemiExpGt const&) = 0;
+ virtual void emit(SemiExpLte const&) = 0;
+ virtual void emit(SemiExpGte const&) = 0;
+ virtual void emit(SemiExpPlus const&) = 0;
+ virtual void emit(SemiExpMinus const&) = 0;
+ virtual void emit(SemiExpTimes const&) = 0;
+ virtual void emit(SemiExpDiv const&) = 0;
+ virtual void emit(SemiExpShl const&) = 0;
+ virtual void emit(SemiExpShr const&) = 0;
+};
+
+}
+
+#endif
+
diff --git a/Monicelli.ypp b/Monicelli.ypp
index 07c343c..10d43bd 100644
--- a/Monicelli.ypp
+++ b/Monicelli.ypp
@@ -78,7 +78,7 @@
bool boolval;
Type typeval;
Statement* statementval;
- StatementList* statlistval;
+ PointerList* statlistval;
Assert* assertval;
FunctionCall* callval;
Print* printval;
@@ -90,16 +90,16 @@
Assignment* assignval;
Loop* loopval;
BranchCase *caseval;
- BranchCaseList *caselistval;
+ PointerList *caselistval;
Return* returnval;
Expression* expressionval;
- ExpressionList* exprlistval;
+ PointerList* exprlistval;
SemiExpression *semiexpval;
Id* idval;
Number* numericval;
Function* funval;
FunArg *argval;
- FunArgList *arglistval;
+ PointerList *arglistval;
Main* mainval;
}
@@ -159,11 +159,16 @@ fun_return:
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
;
args:
- /* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; }
+ /* epsilon */ {
+ $$ = new PointerList();
+ }
+ | PARAMS args_decl {
+ $$ = $2;
+ }
;
args_decl:
arg_decl {
- $$ = new FunArgList();
+ $$ = new PointerList();
$$->push_back($1);
}
| args_decl COMMA arg_decl {
@@ -182,7 +187,7 @@ main:
;
statements:
/* epsilon */ {
- $$ = new StatementList();
+ $$ = new PointerList();
}
| statements statement {
if ($2 != nullptr) {
@@ -271,7 +276,7 @@ branch_body:
;
cases:
case_stmt {
- $$ = new BranchCaseList();
+ $$ = new PointerList();
$$->push_back($1);
}
| cases CASE_END case_stmt {
@@ -291,7 +296,7 @@ fun_call:
;
call_args:
/* epsilon */ {
- $$ = new ExpressionList();
+ $$ = new PointerList();
}
| PARAMS call_arglist {
$$ = $2;
@@ -299,7 +304,7 @@ call_args:
;
call_arglist:
expression {
- $$ = new ExpressionList();
+ $$ = new PointerList();
$$->push_back($1);
}
| call_arglist COMMA expression {
diff --git a/Nodes.cpp b/Nodes.cpp
deleted file mode 100644
index a499221..0000000
--- a/Nodes.cpp
+++ /dev/null
@@ -1,267 +0,0 @@
-/*
- * Monicelli: an esoteric language compiler
- *
- * Copyright (C) 2014 Stefano Sanfilippo
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-
-#include "Nodes.hpp"
-
-using namespace monicelli;
-
-static const std::string BLOCK = " ";
-
-std::ostream& monicelli::operator<<(std::ostream &stream, const Type &type) {
- switch (type) {
- case Type::INT:
- stream << "int";
- break;
- case Type::CHAR:
- stream << "char";
- break;
- case Type::FLOAT:
- stream << "float";
- break;
- case Type::BOOL:
- stream << "bool";
- break;
- case Type::DOUBLE:
- stream << "double";
- break;
- case Type::VOID:
- stream << "void";
- break;
- }
-
- return stream;
-}
-
-void emitIndent(std::ostream &stream, int indent) {
- for (int i = 0; i < indent; ++i) {
- stream << BLOCK;
- }
-}
-
-void Id::emit(std::ostream &stream, int indent) {
- stream << *value;
-}
-
-void Integer::emit(std::ostream &stream, int indent) {
- stream << value;
-}
-
-void Float::emit(std::ostream &stream, int indent) {
- stream << value;
-}
-
-void ExpNode::emit(std::ostream &stream, int indent) {
- left->emit(stream);
- stream << ' ' << getSym() << ' ';
- right->emit(stream);
-}
-
-void SemiExpNode::emit(std::ostream &stream, int indent) {
- SimpleExpression *e = dynamic_cast(left.get());
- bool braces = (e == nullptr);
-
- stream << ' ' << getSym() << ' ';
- if (braces) stream << "(";
- left->emit(stream);
- if (braces) stream << ")";
-}
-
-void StatementList::emit(std::ostream &stream, int indent) {
- for (Statement *s: *this) {
- emitIndent(stream, indent);
- s->emit(stream, indent);
- stream << ";\n";
- }
-}
-
-void Return::emit(std::ostream &stream, int indent) {
- stream << "return";
-
- if (expression != nullptr) {
- stream << ' ';
- expression->emit(stream);
- }
-}
-
-void Loop::emit(std::ostream &stream, int indent) {
- stream << "do {\n";
-
- body->emit(stream, indent + 1);
-
- emitIndent(stream, indent);
- stream << "} while (";
- condition->emit(stream);
- stream << ")";
-}
-
-void BranchCase::emit(std::ostream &stream, int indent) {
- condition->emit(stream);
- stream << ") {\n";
- body->emit(stream, indent);
- emitIndent(stream, indent - 1);
- stream << "}";
-}
-
-void Branch::emit(std::ostream &stream, int indent) {
- stream << "if (";
- var->emit(stream);
-
- if (body->cases->size() > 0) {
- BranchCase *last = body->cases->back();
- for (BranchCase *c: *body->cases) {
- c->emit(stream, indent + 1);
- if (c != last) {
- stream << " else if (";
- var->emit(stream);
- }
- }
- }
-
- if (body->els == nullptr) {
- return;
- }
-
- stream << " else {\n";
- body->els->emit(stream, indent + 1);
- emitIndent(stream, indent);
- stream << "}";
-}
-
-void VarDeclaration::emit(std::ostream &stream, int indent) {
- stream << type << ' ';
- if (point) stream << '*';
- name->emit(stream);
-
- if (init != nullptr) {
- stream << " = ";
- init->emit(stream);
- }
-}
-
-void Assignment::emit(std::ostream &stream, int indent) {
- name->emit(stream);
- stream << " = ";
- value->emit(stream);
-}
-
-void Print::emit(std::ostream &stream, int indent) {
- bool simpleExpression = (dynamic_cast(expression.get()) != nullptr);
-
- stream << "std::cout << ";
- if (!simpleExpression) {
- stream << '(';
- }
-
- expression->emit(stream);
-
- if (!simpleExpression) {
- stream << ')';
- }
- stream << " << std::endl";
-}
-
-void Input::emit(std::ostream &stream, int indent) {
- stream << "std::cout << \"";
- variable->emit(stream);
- stream << "? \";\n";
- emitIndent(stream, indent);
- stream << "std::cin >> ";
- variable->emit(stream);
-}
-
-void Abort::emit(std::ostream &stream, int indent) {
- stream << "std::exit(1)";
-}
-
-void Assert::emit(std::ostream &stream, int indent) {
- stream << "assert(";
- expression->emit(stream);
- stream << ")";
-}
-
-void FunctionCall::emit(std::ostream &stream, int indent) {
- name->emit(stream);
- stream << "(";
- args->emit(stream);
- stream << ")";
-}
-
-void FunArg::emit(std::ostream &stream, int indent) {
- stream << type << (pointer? "* ": " ");
- name->emit(stream);
-}
-
-void Function::emit(std::ostream &stream, int indent) {
- emitSignature(stream, indent);
- stream << " {\n";
- body->emit(stream, indent + 1);
- stream << "}\n\n";
-}
-
-void Function::emitSignature(std::ostream &stream, int indent) {
- emitIndent(stream, indent);
-
- stream << type << ' ';
- name->emit(stream);
- stream << "(";
- args->emit(stream);
- stream << ")";
-}
-
-void Module::emit(std::ostream &stream, int indent) {
- bool system = (type == Module::SYSTEM);
- stream << "#include " << (system? '<': '"') << name << (system? '>': '"');
-}
-
-void Main::emit(std::ostream &stream, int indent) {
- emitIndent(stream, indent);
-
- stream << "int main() {\n";
- body->emit(stream, indent + 1);
- stream << "}\n";
-}
-
-void Program::emit(std::ostream &stream, int indent) {
- for (Module m: modules) {
- m.emit(stream);
- stream << "\n";
- }
-
- if (!modules.empty()) {
- stream << "\n";
- }
-
- for (Function *f: functions) {
- f->emitSignature(stream);
- stream << ";\n";
- }
-
- if (!functions.empty()) {
- stream << "\n";
- }
-
- for (Function *f: functions) {
- f->emit(stream);
- }
-
- if (main != nullptr) {
- main->emit(stream);
- }
-}
-
diff --git a/Nodes.hpp b/Nodes.hpp
index c794803..b6c93e1 100644
--- a/Nodes.hpp
+++ b/Nodes.hpp
@@ -1,5 +1,5 @@
-#ifndef NODES_H
-#define NODES_H
+#ifndef NODES_HPP
+#define NODES_HPP
/*
* Monicelli: an esoteric language compiler
@@ -20,10 +20,15 @@
* along with this program. If not, see .
*/
+#include "Emitter.hpp"
#include "Pointers.hpp"
#include
#include
+#include
+
+#define maybe_return(val) \
+ if ((val) != nullptr) return *(val); else return boost::none;
namespace monicelli {
@@ -36,99 +41,66 @@ enum class Type {
VOID
};
-std::ostream& operator<<(std::ostream &stream, const Type &type);
-
-
class Emittable {
public:
- virtual void emit(std::ostream &stream, int indent = 0) = 0;
+ virtual ~Emittable() {}
+ virtual void emit(Emitter *emitter) const = 0;
};
class Statement: public Emittable {
public:
- virtual ~Statement() {}
+ virtual void emit(Emitter *) const {}
};
-
class SemiExpression: public Emittable {
public:
- virtual ~SemiExpression() {}
+ virtual void emit(Emitter *) const {}
};
-
class Expression: public Emittable {
public:
- virtual ~Expression() {}
+ virtual void emit(Emitter *) const {}
};
-public:
-};
-
-
-class StatementList: public PointerList, public Emittable {
-public:
- virtual void emit(std::ostream &stream, int indent = 0);
-};
-
-
-template
-class ListEmittable: public PointerList, public Emittable {
-public:
- virtual void emit(std::ostream &stream, int indent = 0) {
- if (this->size() > 0) {
- T *last = this->back(); // TODO wut?
- for (T *e: *this) {
- e->emit(stream);
- if (e != last) {
- stream << getSeparator();
- }
- }
- }
- }
-
-protected:
- virtual std::string getSeparator() const {
- return ", ";
- }
-};
-
-
-class ExpressionList: public ListEmittable {
-};
-
-
class SimpleExpression: public Expression {
+public:
+ virtual void emit(Emitter *) const {}
};
class Id: public SimpleExpression {
public:
explicit Id(std::string *c): value(c) {}
- virtual ~Id() {}
- virtual void emit(std::ostream &stream, int indent = 0);
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ std::string const& getValue() const {
+ return *value;
+ }
private:
Pointer value;
};
-class IdList: public ListEmittable {
-};
-
-
-class Number: public SimpleExpression {
-public:
- virtual void emit(std::ostream &stream, int indent = 0) {}
-};
+class Number: public SimpleExpression {};
class Integer: public Number {
public:
Integer(long i): value(i) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ long getValue() const {
+ return value;
+ }
private:
long value;
@@ -138,7 +110,14 @@ private:
class Float: public Number {
public:
Float(double f): value(f) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ double getValue() const {
+ return value;
+ }
private:
double value;
@@ -148,7 +127,14 @@ private:
class Return: public Statement {
public:
explicit Return(Expression *e): expression(e) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ boost::optional getExpression() const {
+ maybe_return(expression);
+ }
private:
Pointer expression;
@@ -157,11 +143,22 @@ private:
class Loop: public Statement {
public:
- Loop(StatementList *b, Expression *c): body(b), condition(c) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+ Loop(PointerList *b, Expression *c): body(b), condition(c) {}
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ PointerList const& getBody() const {
+ return *body;
+ }
+
+ Expression const& getCondition() const {
+ return *condition;
+ }
private:
- Pointer body;
+ Pointer> body;
Pointer condition;
};
@@ -170,7 +167,26 @@ class VarDeclaration: public Statement {
public:
VarDeclaration(Id *n, Type t, bool p, Expression *i):
name(n), point(p), init(i), type(t) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getId() const {
+ return *name;
+ }
+
+ bool isPointer() const {
+ return point;
+ }
+
+ boost::optional getInitializer() const {
+ maybe_return(init);
+ }
+
+ Type getType() const {
+ return type;
+ }
private:
Pointer name;
@@ -183,7 +199,18 @@ private:
class Assignment: public Statement {
public:
Assignment(Id *n, Expression *v): name(n), value(v) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getName() const {
+ return *name;
+ }
+
+ Expression const& getValue() const {
+ return *value;
+ }
private:
Pointer name;
@@ -194,7 +221,14 @@ private:
class Print: public Statement {
public:
explicit Print(Expression *e): expression(e) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Expression const& getExpression() const {
+ return *expression;
+ }
private:
Pointer expression;
@@ -204,7 +238,14 @@ private:
class Input: public Statement {
public:
explicit Input(Id *v): variable(v) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getVariable() const {
+ return *variable;
+ }
private:
Pointer variable;
@@ -213,14 +254,23 @@ private:
class Abort: public Statement {
public:
- virtual void emit(std::ostream &stream, int indent = 0);
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
};
class Assert: public Statement {
public:
explicit Assert(Expression *e): expression(e) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Expression const& getExpression() const {
+ return *expression;
+ }
private:
Pointer expression;
@@ -229,45 +279,80 @@ private:
class FunctionCall: public Statement, public Expression {
public:
- FunctionCall(Id *n, ExpressionList *a): name(n), args(a) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+ FunctionCall(Id *n, PointerList *a): name(n), args(a) {}
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getName() const {
+ return *name;
+ }
+
+ PointerList const& getArgs() const {
+ return *args;
+ }
private:
Pointer name;
- Pointer args;
+ Pointer> args;
};
class BranchCase: public Emittable {
public:
- BranchCase(SemiExpression *c, StatementList *b): condition(c), body(b) {}
- virtual ~BranchCase() {}
+ BranchCase(SemiExpression *c, PointerList *b): condition(c), body(b) {}
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ SemiExpression const& getCondition() const {
+ return *condition;
+ }
+
+ PointerList const& getBody() const {
+ return *body;
+ }
- virtual void emit(std::ostream &stream, int indent = 0);
private:
Pointer condition;
- Pointer body;
+ Pointer> body;
};
-typedef PointerList BranchCaseList;
-
-
class Branch: public Statement {
public:
- struct Body {
+ class Body {
public:
- Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {}
+ Body(PointerList *c, PointerList *e = nullptr): cases(c), els(e) {}
+
+ PointerList const& getCases() const {
+ return *cases;
+ }
+
+ boost::optional const&> getElse() const {
+ maybe_return(els);
+ }
private:
- Pointer cases;
- Pointer els;
-
- friend class Branch;
+ Pointer> cases;
+ Pointer> els;
};
Branch(Id *v, Branch::Body *b): var(v), body(b) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getVar() const {
+ return *var;
+ }
+
+ Branch::Body const& getBody() const {
+ return *body;
+ }
private:
Pointer var;
@@ -277,20 +362,36 @@ private:
class Main: public Emittable {
public:
- Main(StatementList *s): body(s) {}
- virtual void emit(std::ostream &stream, int indent = 0);
+ Main(PointerList *s): body(s) {}
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ PointerList const& getBody() const {
+ return *body;
+ }
private:
- Pointer body;
+ Pointer> body;
};
-class FunArg: public Emittable {
+class FunArg {
public:
FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {}
- virtual ~FunArg() {}
- virtual void emit(std::ostream &stream, int indent = 0);
+ Id const& getName() const {
+ return *name;
+ }
+
+ Type getType() const {
+ return type;
+ }
+
+ bool isPointer() const {
+ return pointer;
+ }
private:
Pointer name;
@@ -299,23 +400,36 @@ private:
};
-typedef ListEmittable FunArgList;
-
-
class Function: public Emittable {
public:
- Function(Id *n, Type r, FunArgList *a, StatementList *b):
+ Function(Id *n, Type r, PointerList *a, PointerList *b):
name(n), type(r), args(a), body(b) {}
- virtual ~Function() {}
- virtual void emit(std::ostream &stream, int indent = 0);
- void emitSignature(std::ostream &stream, int indent = 0);
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
+
+ Id const& getName() const {
+ return *name;
+ }
+
+ Type getType() const {
+ return type;
+ }
+
+ PointerList const& getArgs() const {
+ return *args;
+ }
+
+ PointerList const& getBody() const {
+ return *body;
+ }
private:
Pointer name;
Type type;
- Pointer args;
- Pointer body;
+ Pointer> args;
+ Pointer> body;
};
@@ -326,7 +440,10 @@ public:
};
Module(const std::string &n, Type s): name(n), type(s) {}
- virtual ~Module() {}
+
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
bool operator==(const Module &other) const noexcept {
return (name == other.name) && (type == other.type);
@@ -336,7 +453,13 @@ public:
return std::hash()(name) ^ std::hash()(type);
}
- virtual void emit(std::ostream &stream, int indent = 0);
+ std::string const& getName() const {
+ return name;
+ }
+
+ Type getType() const {
+ return type;
+ }
private:
std::string name;
@@ -348,7 +471,7 @@ private:
namespace std {
template<>
-class hash {
+struct hash {
public:
size_t operator ()(const monicelli::Module &e) const noexcept {
return e.hash();
@@ -361,7 +484,9 @@ namespace monicelli {
class Program: public Emittable {
public:
- virtual void emit(std::ostream &stream, int indent = 0);
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
+ }
void setMain(Main *m) {
main = Pointer(m);
@@ -376,6 +501,18 @@ public:
delete m;
}
+ boost::optional getMain() const {
+ maybe_return(main);
+ }
+
+ PointerList const& getFunctions() const {
+ return functions;
+ }
+
+ std::unordered_set const& getModules() const {
+ return modules;
+ }
+
private:
Pointer main;
PointerList functions;
@@ -386,10 +523,14 @@ private:
class ExpNode: public Expression {
public:
ExpNode(Expression *l, Expression *r): left(l), right(r) {}
- virtual void emit(std::ostream &stream, int indent = 0);
-protected:
- virtual std::string getSym() = 0;
+ Expression const& getLeft() const {
+ return *left;
+ }
+
+ Expression const& getRight() const {
+ return *right;
+ }
private:
Pointer left;
@@ -401,9 +542,8 @@ class ExpLt: public ExpNode {
public:
ExpLt(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "<";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -412,9 +552,8 @@ class ExpGt: public ExpNode {
public:
ExpGt(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return ">";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -423,9 +562,8 @@ class ExpLte: public ExpNode {
public:
ExpLte(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "<=";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -434,9 +572,8 @@ class ExpGte: public ExpNode {
public:
ExpGte(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return ">=";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -445,9 +582,8 @@ class ExpPlus: public ExpNode {
public:
ExpPlus(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "+";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -456,9 +592,8 @@ class ExpMinus: public ExpNode {
public:
ExpMinus(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "-";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -467,9 +602,8 @@ class ExpTimes: public ExpNode {
public:
ExpTimes(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "*";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -478,9 +612,8 @@ class ExpDiv: public ExpNode {
public:
ExpDiv(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "/";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -489,9 +622,8 @@ class ExpShl: public ExpNode {
public:
ExpShl(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return "<<";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -500,9 +632,8 @@ class ExpShr: public ExpNode {
public:
ExpShr(Expression *l, Expression *r): ExpNode(l, r) {}
-protected:
- virtual std::string getSym() {
- return ">>";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -510,10 +641,10 @@ protected:
class SemiExpNode: public SemiExpression {
public:
SemiExpNode(Expression *l): left(l) {}
- virtual void emit(std::ostream &stream, int indent = 0);
-protected:
- virtual std::string getSym() = 0;
+ Expression const& getLeft() const {
+ return *left;
+ }
private:
Pointer left;
@@ -525,9 +656,8 @@ class SemiExpEq: public SemiExpNode {
public:
SemiExpEq(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "==";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -536,9 +666,8 @@ class SemiExpLt: public SemiExpNode {
public:
SemiExpLt(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "<";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -547,9 +676,8 @@ class SemiExpGt: public SemiExpNode {
public:
SemiExpGt(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return ">";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -558,9 +686,8 @@ class SemiExpLte: public SemiExpNode {
public:
SemiExpLte(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "<=";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -569,9 +696,8 @@ class SemiExpGte: public SemiExpNode {
public:
SemiExpGte(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return ">=";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -580,9 +706,8 @@ class SemiExpPlus: public SemiExpNode {
public:
SemiExpPlus(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "+";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -591,9 +716,8 @@ class SemiExpMinus: public SemiExpNode {
public:
SemiExpMinus(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "-";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -602,9 +726,8 @@ class SemiExpTimes: public SemiExpNode {
public:
SemiExpTimes(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "*";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -613,9 +736,8 @@ class SemiExpDiv: public SemiExpNode {
public:
SemiExpDiv(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "/";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -624,9 +746,8 @@ class SemiExpShl: public SemiExpNode {
public:
SemiExpShl(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return "<<";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
@@ -635,13 +756,14 @@ class SemiExpShr: public SemiExpNode {
public:
SemiExpShr(Expression *l): SemiExpNode(l) {}
-protected:
- virtual std::string getSym() {
- return ">>";
+ virtual void emit(Emitter *emitter) const {
+ emitter->emit(*this);
}
};
} // namespace
+#undef maybe_return
+
#endif
diff --git a/main.cpp b/main.cpp
index 5a54e2a..70ef9e8 100644
--- a/main.cpp
+++ b/main.cpp
@@ -19,6 +19,7 @@
#include "Scanner.hpp"
#include "Parser.hpp"
+#include "CppEmitter.hpp"
#include
#include
@@ -35,7 +36,9 @@ int main(int argc, char **argv) {
#endif
parser.parse();
- program.emit(std::cout);
+ CppEmitter emitter(&std::cout);
+
+ program.emit(&emitter);
return 0;
}