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...")
|
message("== Bison 2.5 was found. You have to apply cmake/bison2.patch...")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
## 3. Build
|
## 3. Boost components
|
||||||
|
|
||||||
|
find_package(Boost 1.54 REQUIRED)
|
||||||
|
|
||||||
|
## 4. Build
|
||||||
|
|
||||||
include_directories(
|
include_directories(
|
||||||
${CMAKE_CURRENT_BINARY_DIR}
|
${CMAKE_CURRENT_BINARY_DIR}
|
||||||
${CMAKE_CURRENT_SOURCE_DIR}
|
${CMAKE_CURRENT_SOURCE_DIR}
|
||||||
|
${Boost_INCLUDE_DIRS}
|
||||||
)
|
)
|
||||||
|
|
||||||
add_definitions(-Wall -Wno-deprecated-register -std=c++0x -DYYDEBUG=0 -O2)
|
add_definitions(-Wall -Wno-deprecated-register -std=c++0x -DYYDEBUG=0 -O2)
|
||||||
|
@ -70,6 +75,10 @@ add_flex_bison_dependency(Scanner Parser)
|
||||||
|
|
||||||
add_executable(
|
add_executable(
|
||||||
mcc
|
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;
|
bool boolval;
|
||||||
Type typeval;
|
Type typeval;
|
||||||
Statement* statementval;
|
Statement* statementval;
|
||||||
StatementList* statlistval;
|
PointerList<Statement>* statlistval;
|
||||||
Assert* assertval;
|
Assert* assertval;
|
||||||
FunctionCall* callval;
|
FunctionCall* callval;
|
||||||
Print* printval;
|
Print* printval;
|
||||||
|
@ -90,16 +90,16 @@
|
||||||
Assignment* assignval;
|
Assignment* assignval;
|
||||||
Loop* loopval;
|
Loop* loopval;
|
||||||
BranchCase *caseval;
|
BranchCase *caseval;
|
||||||
BranchCaseList *caselistval;
|
PointerList<BranchCase> *caselistval;
|
||||||
Return* returnval;
|
Return* returnval;
|
||||||
Expression* expressionval;
|
Expression* expressionval;
|
||||||
ExpressionList* exprlistval;
|
PointerList<Expression>* exprlistval;
|
||||||
SemiExpression *semiexpval;
|
SemiExpression *semiexpval;
|
||||||
Id* idval;
|
Id* idval;
|
||||||
Number* numericval;
|
Number* numericval;
|
||||||
Function* funval;
|
Function* funval;
|
||||||
FunArg *argval;
|
FunArg *argval;
|
||||||
FunArgList *arglistval;
|
PointerList<FunArg> *arglistval;
|
||||||
Main* mainval;
|
Main* mainval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,16 @@ fun_return:
|
||||||
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
|
/* epsilon */ { $$ = Type::VOID; } | TYPENAME { $$ = $1; }
|
||||||
;
|
;
|
||||||
args:
|
args:
|
||||||
/* epsilon */ { $$ = new FunArgList(); }| PARAMS args_decl { $$ = $2; }
|
/* epsilon */ {
|
||||||
|
$$ = new PointerList<FunArg>();
|
||||||
|
}
|
||||||
|
| PARAMS args_decl {
|
||||||
|
$$ = $2;
|
||||||
|
}
|
||||||
;
|
;
|
||||||
args_decl:
|
args_decl:
|
||||||
arg_decl {
|
arg_decl {
|
||||||
$$ = new FunArgList();
|
$$ = new PointerList<FunArg>();
|
||||||
$$->push_back($1);
|
$$->push_back($1);
|
||||||
}
|
}
|
||||||
| args_decl COMMA arg_decl {
|
| args_decl COMMA arg_decl {
|
||||||
|
@ -182,7 +187,7 @@ main:
|
||||||
;
|
;
|
||||||
statements:
|
statements:
|
||||||
/* epsilon */ {
|
/* epsilon */ {
|
||||||
$$ = new StatementList();
|
$$ = new PointerList<Statement>();
|
||||||
}
|
}
|
||||||
| statements statement {
|
| statements statement {
|
||||||
if ($2 != nullptr) {
|
if ($2 != nullptr) {
|
||||||
|
@ -271,7 +276,7 @@ branch_body:
|
||||||
;
|
;
|
||||||
cases:
|
cases:
|
||||||
case_stmt {
|
case_stmt {
|
||||||
$$ = new BranchCaseList();
|
$$ = new PointerList<BranchCase>();
|
||||||
$$->push_back($1);
|
$$->push_back($1);
|
||||||
}
|
}
|
||||||
| cases CASE_END case_stmt {
|
| cases CASE_END case_stmt {
|
||||||
|
@ -291,7 +296,7 @@ fun_call:
|
||||||
;
|
;
|
||||||
call_args:
|
call_args:
|
||||||
/* epsilon */ {
|
/* epsilon */ {
|
||||||
$$ = new ExpressionList();
|
$$ = new PointerList<Expression>();
|
||||||
}
|
}
|
||||||
| PARAMS call_arglist {
|
| PARAMS call_arglist {
|
||||||
$$ = $2;
|
$$ = $2;
|
||||||
|
@ -299,7 +304,7 @@ call_args:
|
||||||
;
|
;
|
||||||
call_arglist:
|
call_arglist:
|
||||||
expression {
|
expression {
|
||||||
$$ = new ExpressionList();
|
$$ = new PointerList<Expression>();
|
||||||
$$->push_back($1);
|
$$->push_back($1);
|
||||||
}
|
}
|
||||||
| call_arglist COMMA expression {
|
| 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
|
#ifndef NODES_HPP
|
||||||
#define NODES_H
|
#define NODES_HPP
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Monicelli: an esoteric language compiler
|
* Monicelli: an esoteric language compiler
|
||||||
|
@ -20,10 +20,15 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "Emitter.hpp"
|
||||||
#include "Pointers.hpp"
|
#include "Pointers.hpp"
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
|
#include <boost/optional.hpp>
|
||||||
|
|
||||||
|
#define maybe_return(val) \
|
||||||
|
if ((val) != nullptr) return *(val); else return boost::none;
|
||||||
|
|
||||||
namespace monicelli {
|
namespace monicelli {
|
||||||
|
|
||||||
|
@ -36,99 +41,66 @@ enum class Type {
|
||||||
VOID
|
VOID
|
||||||
};
|
};
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream &stream, const Type &type);
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Emittable {
|
class Emittable {
|
||||||
public:
|
public:
|
||||||
virtual void emit(std::ostream &stream, int indent = 0) = 0;
|
virtual ~Emittable() {}
|
||||||
|
virtual void emit(Emitter *emitter) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Statement: public Emittable {
|
class Statement: public Emittable {
|
||||||
public:
|
public:
|
||||||
virtual ~Statement() {}
|
virtual void emit(Emitter *) const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class SemiExpression: public Emittable {
|
class SemiExpression: public Emittable {
|
||||||
public:
|
public:
|
||||||
virtual ~SemiExpression() {}
|
virtual void emit(Emitter *) const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Expression: public Emittable {
|
class Expression: public Emittable {
|
||||||
public:
|
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 {
|
class SimpleExpression: public Expression {
|
||||||
|
public:
|
||||||
|
virtual void emit(Emitter *) const {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Id: public SimpleExpression {
|
class Id: public SimpleExpression {
|
||||||
public:
|
public:
|
||||||
explicit Id(std::string *c): value(c) {}
|
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:
|
private:
|
||||||
Pointer<std::string> value;
|
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 {
|
class Integer: public Number {
|
||||||
public:
|
public:
|
||||||
Integer(long i): value(i) {}
|
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:
|
private:
|
||||||
long value;
|
long value;
|
||||||
|
@ -138,7 +110,14 @@ private:
|
||||||
class Float: public Number {
|
class Float: public Number {
|
||||||
public:
|
public:
|
||||||
Float(double f): value(f) {}
|
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:
|
private:
|
||||||
double value;
|
double value;
|
||||||
|
@ -148,7 +127,14 @@ private:
|
||||||
class Return: public Statement {
|
class Return: public Statement {
|
||||||
public:
|
public:
|
||||||
explicit Return(Expression *e): expression(e) {}
|
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:
|
private:
|
||||||
Pointer<Expression> expression;
|
Pointer<Expression> expression;
|
||||||
|
@ -157,11 +143,22 @@ private:
|
||||||
|
|
||||||
class Loop: public Statement {
|
class Loop: public Statement {
|
||||||
public:
|
public:
|
||||||
Loop(StatementList *b, Expression *c): body(b), condition(c) {}
|
Loop(PointerList<Statement> *b, Expression *c): body(b), condition(c) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
|
||||||
|
virtual void emit(Emitter *emitter) const {
|
||||||
|
emitter->emit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerList<Statement> const& getBody() const {
|
||||||
|
return *body;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression const& getCondition() const {
|
||||||
|
return *condition;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<StatementList> body;
|
Pointer<PointerList<Statement>> body;
|
||||||
Pointer<Expression> condition;
|
Pointer<Expression> condition;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -170,7 +167,26 @@ class VarDeclaration: public Statement {
|
||||||
public:
|
public:
|
||||||
VarDeclaration(Id *n, Type t, bool p, Expression *i):
|
VarDeclaration(Id *n, Type t, bool p, Expression *i):
|
||||||
name(n), point(p), init(i), type(t) {}
|
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:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
|
@ -183,7 +199,18 @@ private:
|
||||||
class Assignment: public Statement {
|
class Assignment: public Statement {
|
||||||
public:
|
public:
|
||||||
Assignment(Id *n, Expression *v): name(n), value(v) {}
|
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:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
|
@ -194,7 +221,14 @@ private:
|
||||||
class Print: public Statement {
|
class Print: public Statement {
|
||||||
public:
|
public:
|
||||||
explicit Print(Expression *e): expression(e) {}
|
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:
|
private:
|
||||||
Pointer<Expression> expression;
|
Pointer<Expression> expression;
|
||||||
|
@ -204,7 +238,14 @@ private:
|
||||||
class Input: public Statement {
|
class Input: public Statement {
|
||||||
public:
|
public:
|
||||||
explicit Input(Id *v): variable(v) {}
|
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:
|
private:
|
||||||
Pointer<Id> variable;
|
Pointer<Id> variable;
|
||||||
|
@ -213,14 +254,23 @@ private:
|
||||||
|
|
||||||
class Abort: public Statement {
|
class Abort: public Statement {
|
||||||
public:
|
public:
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(Emitter *emitter) const {
|
||||||
|
emitter->emit(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class Assert: public Statement {
|
class Assert: public Statement {
|
||||||
public:
|
public:
|
||||||
explicit Assert(Expression *e): expression(e) {}
|
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:
|
private:
|
||||||
Pointer<Expression> expression;
|
Pointer<Expression> expression;
|
||||||
|
@ -229,45 +279,80 @@ private:
|
||||||
|
|
||||||
class FunctionCall: public Statement, public Expression {
|
class FunctionCall: public Statement, public Expression {
|
||||||
public:
|
public:
|
||||||
FunctionCall(Id *n, ExpressionList *a): name(n), args(a) {}
|
FunctionCall(Id *n, PointerList<Expression> *a): name(n), args(a) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
|
||||||
|
virtual void emit(Emitter *emitter) const {
|
||||||
|
emitter->emit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
Id const& getName() const {
|
||||||
|
return *name;
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerList<Expression> const& getArgs() const {
|
||||||
|
return *args;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
Pointer<ExpressionList> args;
|
Pointer<PointerList<Expression>> args;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class BranchCase: public Emittable {
|
class BranchCase: public Emittable {
|
||||||
public:
|
public:
|
||||||
BranchCase(SemiExpression *c, StatementList *b): condition(c), body(b) {}
|
BranchCase(SemiExpression *c, PointerList<Statement> *b): condition(c), body(b) {}
|
||||||
virtual ~BranchCase() {}
|
|
||||||
|
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:
|
private:
|
||||||
Pointer<SemiExpression> condition;
|
Pointer<SemiExpression> condition;
|
||||||
Pointer<StatementList> body;
|
Pointer<PointerList<Statement>> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef PointerList<BranchCase> BranchCaseList;
|
|
||||||
|
|
||||||
|
|
||||||
class Branch: public Statement {
|
class Branch: public Statement {
|
||||||
public:
|
public:
|
||||||
struct Body {
|
class Body {
|
||||||
public:
|
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:
|
private:
|
||||||
Pointer<BranchCaseList> cases;
|
Pointer<PointerList<BranchCase>> cases;
|
||||||
Pointer<StatementList> els;
|
Pointer<PointerList<Statement>> els;
|
||||||
|
|
||||||
friend class Branch;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Branch(Id *v, Branch::Body *b): var(v), body(b) {}
|
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:
|
private:
|
||||||
Pointer<Id> var;
|
Pointer<Id> var;
|
||||||
|
@ -277,20 +362,36 @@ private:
|
||||||
|
|
||||||
class Main: public Emittable {
|
class Main: public Emittable {
|
||||||
public:
|
public:
|
||||||
Main(StatementList *s): body(s) {}
|
Main(PointerList<Statement> *s): body(s) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
|
||||||
|
virtual void emit(Emitter *emitter) const {
|
||||||
|
emitter->emit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
|
PointerList<Statement> const& getBody() const {
|
||||||
|
return *body;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<StatementList> body;
|
Pointer<PointerList<Statement>> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
class FunArg: public Emittable {
|
class FunArg {
|
||||||
public:
|
public:
|
||||||
FunArg(Id *n, Type t, bool p): name(n), type(t), pointer(p) {}
|
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:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
|
@ -299,23 +400,36 @@ private:
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
typedef ListEmittable<FunArg> FunArgList;
|
|
||||||
|
|
||||||
|
|
||||||
class Function: public Emittable {
|
class Function: public Emittable {
|
||||||
public:
|
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) {}
|
name(n), type(r), args(a), body(b) {}
|
||||||
virtual ~Function() {}
|
|
||||||
|
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(Emitter *emitter) const {
|
||||||
void emitSignature(std::ostream &stream, int indent = 0);
|
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:
|
private:
|
||||||
Pointer<Id> name;
|
Pointer<Id> name;
|
||||||
Type type;
|
Type type;
|
||||||
Pointer<FunArgList> args;
|
Pointer<PointerList<FunArg>> args;
|
||||||
Pointer<StatementList> body;
|
Pointer<PointerList<Statement>> body;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -326,7 +440,10 @@ public:
|
||||||
};
|
};
|
||||||
|
|
||||||
Module(const std::string &n, Type s): name(n), type(s) {}
|
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 {
|
bool operator==(const Module &other) const noexcept {
|
||||||
return (name == other.name) && (type == other.type);
|
return (name == other.name) && (type == other.type);
|
||||||
|
@ -336,7 +453,13 @@ public:
|
||||||
return std::hash<std::string>()(name) ^ std::hash<bool>()(type);
|
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:
|
private:
|
||||||
std::string name;
|
std::string name;
|
||||||
|
@ -348,7 +471,7 @@ private:
|
||||||
namespace std {
|
namespace std {
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class hash<monicelli::Module> {
|
struct hash<monicelli::Module> {
|
||||||
public:
|
public:
|
||||||
size_t operator ()(const monicelli::Module &e) const noexcept {
|
size_t operator ()(const monicelli::Module &e) const noexcept {
|
||||||
return e.hash();
|
return e.hash();
|
||||||
|
@ -361,7 +484,9 @@ namespace monicelli {
|
||||||
|
|
||||||
class Program: public Emittable {
|
class Program: public Emittable {
|
||||||
public:
|
public:
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
virtual void emit(Emitter *emitter) const {
|
||||||
|
emitter->emit(*this);
|
||||||
|
}
|
||||||
|
|
||||||
void setMain(Main *m) {
|
void setMain(Main *m) {
|
||||||
main = Pointer<Main>(m);
|
main = Pointer<Main>(m);
|
||||||
|
@ -376,6 +501,18 @@ public:
|
||||||
delete m;
|
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:
|
private:
|
||||||
Pointer<Main> main;
|
Pointer<Main> main;
|
||||||
PointerList<Function> functions;
|
PointerList<Function> functions;
|
||||||
|
@ -386,10 +523,14 @@ private:
|
||||||
class ExpNode: public Expression {
|
class ExpNode: public Expression {
|
||||||
public:
|
public:
|
||||||
ExpNode(Expression *l, Expression *r): left(l), right(r) {}
|
ExpNode(Expression *l, Expression *r): left(l), right(r) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
|
||||||
|
|
||||||
protected:
|
Expression const& getLeft() const {
|
||||||
virtual std::string getSym() = 0;
|
return *left;
|
||||||
|
}
|
||||||
|
|
||||||
|
Expression const& getRight() const {
|
||||||
|
return *right;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Expression> left;
|
Pointer<Expression> left;
|
||||||
|
@ -401,9 +542,8 @@ class ExpLt: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpLt(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpLt(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -412,9 +552,8 @@ class ExpGt: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpGt(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpGt(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -423,9 +562,8 @@ class ExpLte: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpLte(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpLte(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<=";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -434,9 +572,8 @@ class ExpGte: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpGte(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpGte(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">=";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -445,9 +582,8 @@ class ExpPlus: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpPlus(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpPlus(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "+";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -456,9 +592,8 @@ class ExpMinus: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpMinus(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpMinus(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -467,9 +602,8 @@ class ExpTimes: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpTimes(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpTimes(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "*";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -478,9 +612,8 @@ class ExpDiv: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpDiv(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpDiv(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "/";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -489,9 +622,8 @@ class ExpShl: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpShl(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpShl(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<<";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -500,9 +632,8 @@ class ExpShr: public ExpNode {
|
||||||
public:
|
public:
|
||||||
ExpShr(Expression *l, Expression *r): ExpNode(l, r) {}
|
ExpShr(Expression *l, Expression *r): ExpNode(l, r) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">>";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -510,10 +641,10 @@ protected:
|
||||||
class SemiExpNode: public SemiExpression {
|
class SemiExpNode: public SemiExpression {
|
||||||
public:
|
public:
|
||||||
SemiExpNode(Expression *l): left(l) {}
|
SemiExpNode(Expression *l): left(l) {}
|
||||||
virtual void emit(std::ostream &stream, int indent = 0);
|
|
||||||
|
|
||||||
protected:
|
Expression const& getLeft() const {
|
||||||
virtual std::string getSym() = 0;
|
return *left;
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Pointer<Expression> left;
|
Pointer<Expression> left;
|
||||||
|
@ -525,9 +656,8 @@ class SemiExpEq: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpEq(Expression *l): SemiExpNode(l) {}
|
SemiExpEq(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "==";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -536,9 +666,8 @@ class SemiExpLt: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpLt(Expression *l): SemiExpNode(l) {}
|
SemiExpLt(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -547,9 +676,8 @@ class SemiExpGt: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpGt(Expression *l): SemiExpNode(l) {}
|
SemiExpGt(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -558,9 +686,8 @@ class SemiExpLte: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpLte(Expression *l): SemiExpNode(l) {}
|
SemiExpLte(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<=";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -569,9 +696,8 @@ class SemiExpGte: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpGte(Expression *l): SemiExpNode(l) {}
|
SemiExpGte(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">=";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -580,9 +706,8 @@ class SemiExpPlus: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpPlus(Expression *l): SemiExpNode(l) {}
|
SemiExpPlus(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "+";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -591,9 +716,8 @@ class SemiExpMinus: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpMinus(Expression *l): SemiExpNode(l) {}
|
SemiExpMinus(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "-";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -602,9 +726,8 @@ class SemiExpTimes: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpTimes(Expression *l): SemiExpNode(l) {}
|
SemiExpTimes(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "*";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -613,9 +736,8 @@ class SemiExpDiv: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpDiv(Expression *l): SemiExpNode(l) {}
|
SemiExpDiv(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "/";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -624,9 +746,8 @@ class SemiExpShl: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpShl(Expression *l): SemiExpNode(l) {}
|
SemiExpShl(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return "<<";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -635,13 +756,14 @@ class SemiExpShr: public SemiExpNode {
|
||||||
public:
|
public:
|
||||||
SemiExpShr(Expression *l): SemiExpNode(l) {}
|
SemiExpShr(Expression *l): SemiExpNode(l) {}
|
||||||
|
|
||||||
protected:
|
virtual void emit(Emitter *emitter) const {
|
||||||
virtual std::string getSym() {
|
emitter->emit(*this);
|
||||||
return ">>";
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
#undef maybe_return
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
5
main.cpp
5
main.cpp
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "Scanner.hpp"
|
#include "Scanner.hpp"
|
||||||
#include "Parser.hpp"
|
#include "Parser.hpp"
|
||||||
|
#include "CppEmitter.hpp"
|
||||||
|
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
@ -35,7 +36,9 @@ int main(int argc, char **argv) {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
parser.parse();
|
parser.parse();
|
||||||
program.emit(std::cout);
|
CppEmitter emitter(&std::cout);
|
||||||
|
|
||||||
|
program.emit(&emitter);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue
Block a user