Decouple AST nodes from representation.
1. adding getters to all node properties. 2. extracting an Emitter interface. 3. moving all C++ codegen features to a CppEmitter. All list template specializations typedefs have been removed for increased readability. A dependency on Boost is introduced for boost::optional, which is required in the AST getters API.
This commit is contained in:
parent
0fb3ea5dd6
commit
b0a01d2fb7
|
@ -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})
|
||||
|
||||
|
|
381
CppEmitter.cpp
Normal file
381
CppEmitter.cpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <string>
|
||||
|
||||
#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<Statement> 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<SimpleExpression const*>(&node.getExpression()) == nullptr)
|
||||
&&
|
||||
(dynamic_cast<FunctionCall const*>(&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<Expression> 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<FunArg> 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<SimpleExpression const*>(&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);
|
||||
}
|
||||
|
93
CppEmitter.hpp
Normal file
93
CppEmitter.hpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Emitter.hpp"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
|
||||
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<FunArg> const& funargs);
|
||||
void emitFunctionArglist(PointerList<Expression> const& args);
|
||||
void emitStatements(PointerList<Statement> const& node);
|
||||
|
||||
void indent();
|
||||
void dedent();
|
||||
|
||||
std::ostream &stream;
|
||||
int indent_chars;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
113
Emitter.hpp
Normal file
113
Emitter.hpp
Normal file
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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
|
||||
|
|
@ -78,7 +78,7 @@
|
|||
bool boolval;
|
||||
Type typeval;
|
||||
Statement* statementval;
|
||||
StatementList* statlistval;
|
||||
PointerList<Statement>* statlistval;
|
||||
Assert* assertval;
|
||||
FunctionCall* callval;
|
||||
Print* printval;
|
||||
|
@ -90,16 +90,16 @@
|
|||
Assignment* assignval;
|
||||
Loop* loopval;
|
||||
BranchCase *caseval;
|
||||
BranchCaseList *caselistval;
|
||||
PointerList<BranchCase> *caselistval;
|
||||
Return* returnval;
|
||||
Expression* expressionval;
|
||||
ExpressionList* exprlistval;
|
||||
PointerList<Expression>* exprlistval;
|
||||
SemiExpression *semiexpval;
|
||||
Id* idval;
|
||||
Number* numericval;
|
||||
Function* funval;
|
||||
FunArg *argval;
|
||||
FunArgList *arglistval;
|
||||
PointerList<FunArg> *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<FunArg>();
|
||||
}
|
||||
| PARAMS args_decl {
|
||||
$$ = $2;
|
||||
}
|
||||
;
|
||||
args_decl:
|
||||
arg_decl {
|
||||
$$ = new FunArgList();
|
||||
$$ = new PointerList<FunArg>();
|
||||
$$->push_back($1);
|
||||
}
|
||||
| args_decl COMMA arg_decl {
|
||||
|
@ -182,7 +187,7 @@ main:
|
|||
;
|
||||
statements:
|
||||
/* epsilon */ {
|
||||
$$ = new StatementList();
|
||||
$$ = new PointerList<Statement>();
|
||||
}
|
||||
| statements statement {
|
||||
if ($2 != nullptr) {
|
||||
|
@ -271,7 +276,7 @@ branch_body:
|
|||
;
|
||||
cases:
|
||||
case_stmt {
|
||||
$$ = new BranchCaseList();
|
||||
$$ = new PointerList<BranchCase>();
|
||||
$$->push_back($1);
|
||||
}
|
||||
| cases CASE_END case_stmt {
|
||||
|
@ -291,7 +296,7 @@ fun_call:
|
|||
;
|
||||
call_args:
|
||||
/* epsilon */ {
|
||||
$$ = new ExpressionList();
|
||||
$$ = new PointerList<Expression>();
|
||||
}
|
||||
| PARAMS call_arglist {
|
||||
$$ = $2;
|
||||
|
@ -299,7 +304,7 @@ call_args:
|
|||
;
|
||||
call_arglist:
|
||||
expression {
|
||||
$$ = new ExpressionList();
|
||||
$$ = new PointerList<Expression>();
|
||||
$$->push_back($1);
|
||||
}
|
||||
| call_arglist COMMA expression {
|
||||
|
|
267
Nodes.cpp
267
Nodes.cpp
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#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<SimpleExpression*>(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<SimpleExpression*>(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);
|
||||
}
|
||||
}
|
||||
|
470
Nodes.hpp
470
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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "Emitter.hpp"
|
||||
#include "Pointers.hpp"
|
||||
|
||||
#include <functional>
|
||||
#include <unordered_set>
|
||||
#include <boost/optional.hpp>
|
||||
|
||||
#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<Statement>, public Emittable {
|
||||
public:
|
||||
virtual void emit(std::ostream &stream, int indent = 0);
|
||||
};
|
||||
|
||||
|
||||
template <class T>
|
||||
class ListEmittable: public PointerList<T>, 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<Expression> {
|
||||
};
|
||||
|
||||
|
||||
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<std::string> value;
|
||||
};
|
||||
|
||||
|
||||
class IdList: public ListEmittable<Id> {
|
||||
};
|
||||
|
||||
|
||||
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<Expression const&> getExpression() const {
|
||||
maybe_return(expression);
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<Expression> 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<Statement> *b, Expression *c): body(b), condition(c) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
}
|
||||
|
||||
PointerList<Statement> const& getBody() const {
|
||||
return *body;
|
||||
}
|
||||
|
||||
Expression const& getCondition() const {
|
||||
return *condition;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<StatementList> body;
|
||||
Pointer<PointerList<Statement>> body;
|
||||
Pointer<Expression> 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<Expression const&> getInitializer() const {
|
||||
maybe_return(init);
|
||||
}
|
||||
|
||||
Type getType() const {
|
||||
return type;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<Id> 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<Id> 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> 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<Id> 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> 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<Expression> *a): name(n), args(a) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
}
|
||||
|
||||
Id const& getName() const {
|
||||
return *name;
|
||||
}
|
||||
|
||||
PointerList<Expression> const& getArgs() const {
|
||||
return *args;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<Id> name;
|
||||
Pointer<ExpressionList> args;
|
||||
Pointer<PointerList<Expression>> args;
|
||||
};
|
||||
|
||||
|
||||
class BranchCase: public Emittable {
|
||||
public:
|
||||
BranchCase(SemiExpression *c, StatementList *b): condition(c), body(b) {}
|
||||
virtual ~BranchCase() {}
|
||||
BranchCase(SemiExpression *c, PointerList<Statement> *b): condition(c), body(b) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
}
|
||||
|
||||
SemiExpression const& getCondition() const {
|
||||
return *condition;
|
||||
}
|
||||
|
||||
PointerList<Statement> const& getBody() const {
|
||||
return *body;
|
||||
}
|
||||
|
||||
virtual void emit(std::ostream &stream, int indent = 0);
|
||||
private:
|
||||
Pointer<SemiExpression> condition;
|
||||
Pointer<StatementList> body;
|
||||
Pointer<PointerList<Statement>> body;
|
||||
};
|
||||
|
||||
|
||||
typedef PointerList<BranchCase> BranchCaseList;
|
||||
|
||||
|
||||
class Branch: public Statement {
|
||||
public:
|
||||
struct Body {
|
||||
class Body {
|
||||
public:
|
||||
Body(BranchCaseList *c, StatementList *e = nullptr): cases(c), els(e) {}
|
||||
Body(PointerList<BranchCase> *c, PointerList<Statement> *e = nullptr): cases(c), els(e) {}
|
||||
|
||||
PointerList<BranchCase> const& getCases() const {
|
||||
return *cases;
|
||||
}
|
||||
|
||||
boost::optional<PointerList<Statement> const&> getElse() const {
|
||||
maybe_return(els);
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<BranchCaseList> cases;
|
||||
Pointer<StatementList> els;
|
||||
|
||||
friend class Branch;
|
||||
Pointer<PointerList<BranchCase>> cases;
|
||||
Pointer<PointerList<Statement>> 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<Id> 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<Statement> *s): body(s) {}
|
||||
|
||||
virtual void emit(Emitter *emitter) const {
|
||||
emitter->emit(*this);
|
||||
}
|
||||
|
||||
PointerList<Statement> const& getBody() const {
|
||||
return *body;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<StatementList> body;
|
||||
Pointer<PointerList<Statement>> 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<Id> name;
|
||||
|
@ -299,23 +400,36 @@ private:
|
|||
};
|
||||
|
||||
|
||||
typedef ListEmittable<FunArg> FunArgList;
|
||||
|
||||
|
||||
class Function: public Emittable {
|
||||
public:
|
||||
Function(Id *n, Type r, FunArgList *a, StatementList *b):
|
||||
Function(Id *n, Type r, PointerList<FunArg> *a, PointerList<Statement> *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<FunArg> const& getArgs() const {
|
||||
return *args;
|
||||
}
|
||||
|
||||
PointerList<Statement> const& getBody() const {
|
||||
return *body;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<Id> name;
|
||||
Type type;
|
||||
Pointer<FunArgList> args;
|
||||
Pointer<StatementList> body;
|
||||
Pointer<PointerList<FunArg>> args;
|
||||
Pointer<PointerList<Statement>> 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<std::string>()(name) ^ std::hash<bool>()(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<monicelli::Module> {
|
||||
struct hash<monicelli::Module> {
|
||||
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<Main>(m);
|
||||
|
@ -376,6 +501,18 @@ public:
|
|||
delete m;
|
||||
}
|
||||
|
||||
boost::optional<Main const&> getMain() const {
|
||||
maybe_return(main);
|
||||
}
|
||||
|
||||
PointerList<Function> const& getFunctions() const {
|
||||
return functions;
|
||||
}
|
||||
|
||||
std::unordered_set<Module> const& getModules() const {
|
||||
return modules;
|
||||
}
|
||||
|
||||
private:
|
||||
Pointer<Main> main;
|
||||
PointerList<Function> 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<Expression> 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<Expression> 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
|
||||
|
||||
|
|
5
main.cpp
5
main.cpp
|
@ -19,6 +19,7 @@
|
|||
|
||||
#include "Scanner.hpp"
|
||||
#include "Parser.hpp"
|
||||
#include "CppEmitter.hpp"
|
||||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
Reference in New Issue
Block a user