basic tests
This commit is contained in:
parent
2a04b62f45
commit
4ae6c97904
25 changed files with 158 additions and 25 deletions
10
makefile
10
makefile
|
|
@ -5,7 +5,7 @@ FLEX = flex
|
||||||
|
|
||||||
TARGET = build/py2rb
|
TARGET = build/py2rb
|
||||||
|
|
||||||
$(TARGET): build/parser.o build/lexer.o build/main.o
|
$(TARGET): build/parser.o build/lexer.o build/main.o
|
||||||
$(CXX) $^ -o $@
|
$(CXX) $^ -o $@
|
||||||
|
|
||||||
build/parser.cpp build/parser.hpp: src/parser.y | build
|
build/parser.cpp build/parser.hpp: src/parser.y | build
|
||||||
|
|
@ -17,11 +17,13 @@ build/lexer.cpp build/lexer.hpp: src/lexer.l build/parser.hpp src/scanner.hpp sr
|
||||||
build/%.o: build/%.cpp
|
build/%.o: build/%.cpp
|
||||||
$(CXX) -c $(ARGS) $< -o $@
|
$(CXX) -c $(ARGS) $< -o $@
|
||||||
|
|
||||||
build/%.o: src/%.cpp | build
|
build/main.o: src/main.cpp build src/codegen.hpp
|
||||||
$(CXX) -c $(ARGS) $< -o $@
|
$(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/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:
|
build:
|
||||||
mkdir -p build
|
mkdir -p build
|
||||||
|
|
||||||
|
|
@ -34,4 +36,4 @@ run: $(TARGET)
|
||||||
test: $(TARGET)
|
test: $(TARGET)
|
||||||
test/tester.sh
|
test/tester.sh
|
||||||
|
|
||||||
.PHONY: clean run test
|
.PHONY: clean run test
|
||||||
|
|
|
||||||
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 "parser.hpp"
|
||||||
#include "scanner.hpp"
|
#include "scanner.hpp"
|
||||||
#include "ast.hpp"
|
#include "ast.hpp"
|
||||||
|
#include "codegen.hpp"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
|
@ -71,5 +72,9 @@ int main(int argc, char *argv[])
|
||||||
if (ast_dump)
|
if (ast_dump)
|
||||||
{
|
{
|
||||||
std::cout << ast_root->dump();
|
std::cout << ast_root->dump();
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RubyGenerator generator;
|
||||||
|
std::cout << generator.generate(*ast_root);
|
||||||
}
|
}
|
||||||
|
|
@ -1 +1 @@
|
||||||
42
|
42
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
x
|
x
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
x = 5
|
x = 5
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
2 + 3
|
2 + 3
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
x = 2 + 3
|
x = 2 + 3
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1,2 @@
|
||||||
x = 5
|
x = 5
|
||||||
y = 10
|
y = 10
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
foo()
|
foo()
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
print(x, y)
|
print(x, y)
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
if x
|
if x
|
||||||
y = 5
|
y = 5
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@ if x
|
||||||
y = 5
|
y = 5
|
||||||
else
|
else
|
||||||
y = 10
|
y = 10
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
for i in items
|
for i in items
|
||||||
print(i)
|
print(i)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
while x
|
while x
|
||||||
x = x - 1
|
x = x - 1
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,3 @@
|
||||||
def add(a, b)
|
def add(a, b)
|
||||||
return a + b
|
return a + b
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@ if x
|
||||||
if y
|
if y
|
||||||
z = 1
|
z = 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
[1, 2, 3]
|
[1, 2, 3]
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
obj.method()
|
||||||
|
|
@ -1 +1 @@
|
||||||
lst[0]
|
lst[0]
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
"hello"
|
"hello"
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
x and y
|
x and y
|
||||||
|
|
|
||||||
|
|
@ -1 +1 @@
|
||||||
not x
|
not x
|
||||||
|
|
|
||||||
|
|
@ -3,4 +3,4 @@ class Point
|
||||||
@x = x
|
@x = x
|
||||||
@y = y
|
@y = y
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -2,4 +2,4 @@ class Counter
|
||||||
def increment
|
def increment
|
||||||
@count = @count + 1
|
@count = @count + 1
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue