Skip to content

Commit

Permalink
feat: add -a flag to print the AST
Browse files Browse the repository at this point in the history
  • Loading branch information
mrunix00 committed Dec 6, 2023
1 parent 9e9f987 commit f38ca41
Show file tree
Hide file tree
Showing 4 changed files with 112 additions and 3 deletions.
20 changes: 17 additions & 3 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "parser/Parser.h"
#include "read.hpp"
#include "utils/StdOut.h"
#include "utils/printAST.h"
#include "utils/printTokens.h"
#include <getopt.h>
#include <iostream>
Expand All @@ -12,18 +13,25 @@ int main(int argc, char *argv[]) {
std::cout << "Yasi v0.0.0\n";

bool displayTokens = false;
bool displayAST = false;
StdOut *stdOut;

int opt;
while ((opt = getopt(argc, argv, "t")) != -1) {
while ((opt = getopt(argc, argv, "at")) != -1) {
switch (opt) {
case 't':
displayTokens = true;
stdOut = new StdOut;
break;
case 'a':
displayAST = true;
break;
}
}

if (displayTokens || displayAST) {
stdOut = new StdOut;
}

std::string userInput;
while (true) {
try {
Expand All @@ -38,7 +46,13 @@ int main(int argc, char *argv[]) {
if (displayTokens) {
printTokens(stdOut, tokens);
}
auto result = Evaluate::evaluate(Parser::parse(tokens));

auto ast = Parser::parse(tokens);
if (displayAST) {
print_ast(stdOut, ast);
}

auto result = Evaluate::evaluate(ast);
std::cout << result.token.token << '\n';
} catch (SyntaxError &error) {
std::cout << "SyntaxError (" << error.line
Expand Down
31 changes: 31 additions & 0 deletions src/utils/printAST.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
#include "printAST.h"
#include "parser/SyntaxTreeNode.h"
#include <string>

std::string parse_ast(SyntaxTreeNode ast, int level) {
std::string output;
std::string tabs;

for (int i = 0; i < level; i++) tabs = tabs + "\t";
tabs = tabs + "-> ";

if (!ast.children.empty()) {
output = tabs + "Node (" + ast.token.token + ")\n";
} else {
std::string type;
if (ast.token.type == Token::Integer) type = "Integer";
else if (ast.token.type == Token::String) type = "String";
else type = "Symbol";
return tabs + type + " (" + ast.token.token + ")\n";
}

for (const auto child: ast.children) {
output = output + parse_ast(child, level + 1);
}

return output;
}

void print_ast(OutputSource *outputSource, SyntaxTreeNode ast) {
outputSource->out(parse_ast(ast, 0));
}
10 changes: 10 additions & 0 deletions src/utils/printAST.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#ifndef YASI_PRINTAST_H
#define YASI_PRINTAST_H

#include "parser/SyntaxTreeNode.h"
#include "utils/OutputSource.h"

void print_ast(OutputSource *outputSource, SyntaxTreeNode ast);

#endif

54 changes: 54 additions & 0 deletions tests/print_ast_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#include "parser/SyntaxTreeNode.h"
#include "utils/OutputSource.h"
#include "utils/printAST.h"
#include "gmock/gmock.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include <memory>

class MockOutputSource : public OutputSource {
public:
MOCK_METHOD(void, out, (std::string out), (override));
};


TEST(print_ast_test, ShouldPrintSimpleAST) {
// (+ 1 2)
const SyntaxTreeNode ast = SyntaxTreeNode(
Token(Token::Symbol, "+"),
{
SyntaxTreeNode(Token(Token::Integer, "1")),
SyntaxTreeNode(Token(Token::Integer, "2")),
});
std::shared_ptr<MockOutputSource> mockOutputSource(new MockOutputSource);

EXPECT_CALL(*mockOutputSource, out("-> Node (+)\n"
"\t-> Integer (1)\n"
"\t-> Integer (2)\n"));
print_ast(mockOutputSource.get(), ast);
}

TEST(print_ast_test, ShouldPrintNestedAST) {
// (+ (* 5 2) 4)
const SyntaxTreeNode ast = SyntaxTreeNode(
Token(Token::Symbol, "+"),
{
SyntaxTreeNode(
Token(Token::Symbol, "*"),
{
SyntaxTreeNode(Token(Token::Integer, "5")),
SyntaxTreeNode(Token(Token::Integer, "2")),
}),
SyntaxTreeNode(Token(Token::Integer, "4")),
});
const std::string expectedOutput = "-> Node (+)\n"
"\t-> Node (*)\n"
"\t\t-> Integer (5)\n"
"\t\t-> Integer (2)\n"
"\t-> Integer (4)\n";

std::shared_ptr<MockOutputSource> mockOutputSource(new MockOutputSource);

EXPECT_CALL(*mockOutputSource, out(expectedOutput));
print_ast(mockOutputSource.get(), ast);
}

0 comments on commit f38ca41

Please sign in to comment.