basic tests
This commit is contained in:
parent
2a04b62f45
commit
4ae6c97904
25 changed files with 158 additions and 25 deletions
6
makefile
6
makefile
|
|
@ -17,11 +17,13 @@ build/lexer.cpp build/lexer.hpp: src/lexer.l build/parser.hpp src/scanner.hpp sr
|
|||
build/%.o: build/%.cpp
|
||||
$(CXX) -c $(ARGS) $< -o $@
|
||||
|
||||
build/%.o: src/%.cpp | build
|
||||
$(CXX) -c $(ARGS) $< -o $@
|
||||
build/main.o: src/main.cpp build src/codegen.hpp
|
||||
$(CXX) -c $(ARGS) src/main.cpp -o build/main.o
|
||||
|
||||
src/ast.hpp: src/ast/base.hpp src/ast/expressions.hpp src/ast/literals.hpp src/ast/operators.hpp src/ast/statements.hpp src/ast/string_utils.hpp
|
||||
|
||||
src/codegen.hpp : src/ast.hpp
|
||||
|
||||
build:
|
||||
mkdir -p build
|
||||
|
||||
|
|
|
|||
125
src/codegen.hpp
Normal file
125
src/codegen.hpp
Normal file
|
|
@ -0,0 +1,125 @@
|
|||
#pragma once
|
||||
#include "ast.hpp"
|
||||
#include <sstream>
|
||||
|
||||
class RubyGenerator
|
||||
{
|
||||
std::ostringstream output;
|
||||
int indent_level = 0;
|
||||
|
||||
void write_indent()
|
||||
{
|
||||
for (int i = 0; i < indent_level; i++)
|
||||
{
|
||||
output << " ";
|
||||
}
|
||||
}
|
||||
|
||||
void write(const std::string &s)
|
||||
{
|
||||
output << s;
|
||||
}
|
||||
|
||||
public:
|
||||
std::string generate(const Module &module)
|
||||
{
|
||||
output.str("");
|
||||
indent_level = 0;
|
||||
|
||||
for (const auto &stmt : module.body)
|
||||
{
|
||||
generate_stmt(*stmt);
|
||||
}
|
||||
|
||||
return output.str();
|
||||
}
|
||||
|
||||
private:
|
||||
void generate_stmt(const Stmt &stmt)
|
||||
{
|
||||
if (auto *expr_stmt = dynamic_cast<const ExprStmt *>(&stmt))
|
||||
{
|
||||
write_indent();
|
||||
generate_expr(*expr_stmt->expr);
|
||||
write("\n");
|
||||
}
|
||||
else if (auto *assign = dynamic_cast<const Assign *>(&stmt))
|
||||
{
|
||||
write_indent();
|
||||
generate_expr(*assign->target);
|
||||
write(" = ");
|
||||
generate_expr(*assign->value);
|
||||
write("\n");
|
||||
}
|
||||
else if (auto *if_stmt = dynamic_cast<const If *>(&stmt))
|
||||
{
|
||||
write_indent();
|
||||
write("if ");
|
||||
generate_expr(*if_stmt->condition);
|
||||
write("\n");
|
||||
|
||||
indent_level++;
|
||||
for (const auto &s : if_stmt->then_body)
|
||||
{
|
||||
generate_stmt(*s);
|
||||
}
|
||||
indent_level--;
|
||||
|
||||
if (!if_stmt->else_body.empty())
|
||||
{
|
||||
write("else\n");
|
||||
indent_level++;
|
||||
for (const auto &s : if_stmt->else_body)
|
||||
{
|
||||
generate_stmt(*s);
|
||||
}
|
||||
indent_level--;
|
||||
}
|
||||
|
||||
write("end\n");
|
||||
}
|
||||
else if (auto *ret = dynamic_cast<const Return *>(&stmt))
|
||||
{
|
||||
write_indent();
|
||||
write("return ");
|
||||
if (ret->value)
|
||||
{
|
||||
generate_expr(*ret->value);
|
||||
}
|
||||
write("\n");
|
||||
}
|
||||
}
|
||||
void generate_expr(const Expr &expr)
|
||||
{
|
||||
if (auto *num = dynamic_cast<const Number *>(&expr))
|
||||
{
|
||||
write(num->value);
|
||||
}
|
||||
else if (auto *id = dynamic_cast<const Identifier *>(&expr))
|
||||
{
|
||||
write(id->name);
|
||||
}
|
||||
else if (auto *str = dynamic_cast<const String *>(&expr))
|
||||
{
|
||||
write("\"" + str->value + "\"");
|
||||
}
|
||||
else if (auto *binop = dynamic_cast<const BinOp *>(&expr))
|
||||
{
|
||||
generate_expr(*binop->left);
|
||||
write(" " + binop->op.symbol() + " ");
|
||||
generate_expr(*binop->right);
|
||||
}
|
||||
else if (auto *call = dynamic_cast<const Call *>(&expr))
|
||||
{
|
||||
generate_expr(*call->func);
|
||||
write("(");
|
||||
for (size_t i = 0; i < call->args.size(); i++)
|
||||
{
|
||||
if (i > 0)
|
||||
write(", ");
|
||||
generate_expr(*call->args[i]);
|
||||
}
|
||||
write(")");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -1,6 +1,7 @@
|
|||
#include "parser.hpp"
|
||||
#include "scanner.hpp"
|
||||
#include "ast.hpp"
|
||||
#include "codegen.hpp"
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
|
|
@ -71,5 +72,9 @@ int main(int argc, char *argv[])
|
|||
if (ast_dump)
|
||||
{
|
||||
std::cout << ast_root->dump();
|
||||
return 0;
|
||||
}
|
||||
|
||||
RubyGenerator generator;
|
||||
std::cout << generator.generate(*ast_root);
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
obj.method()
|
||||
Loading…
Add table
Add a link
Reference in a new issue