Skip to content

Commit

Permalink
add google test+mock, integrate cli11
Browse files Browse the repository at this point in the history
  • Loading branch information
amanuel2 committed Jun 10, 2024
1 parent 4741533 commit 1f62d85
Show file tree
Hide file tree
Showing 22 changed files with 315 additions and 119 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# This starter workflow is for a CMake project running on a single platform. There is a different starter workflow if you need cross-platform coverage.
# See: https://github.com/actions/starter-workflows/blob/main/ci/cmake-multi-platform.yml
name: CMake on a single platform
name: status

on:
push:
Expand Down Expand Up @@ -31,9 +31,3 @@ jobs:
# Build your program with the given configuration
run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}}

- name: Test
working-directory: ${{github.workspace}}/build
# Execute tests defined by the CMake configuration.
# See https://cmake.org/cmake/help/latest/manual/ctest.1.html for more detail
run: ctest -C ${{env.BUILD_TYPE}}

File renamed without changes.
7 changes: 6 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,9 @@ build/

# executables
tests/riftlangtest
lib/riftlang
lib/riftlang

# libraries
*.a
*.so
*.so.*
6 changes: 5 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@
"queue": "cpp",
"codecvt": "cpp",
"set": "cpp",
"__memory": "cpp"
"__memory": "cpp",
"condition_variable": "cpp",
"memory": "cpp",
"print": "cpp",
"stack": "cpp"
}
}
9 changes: 7 additions & 2 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.0)
cmake_minimum_required(VERSION 3.5)

# Built using Clang 🐐
set(CMAKE_CXX_COMPILER_ID "Clang")
Expand Down Expand Up @@ -34,4 +34,9 @@ include_directories(${CMAKE_SOURCE_DIR}/external)

add_subdirectory(lib)
enable_testing()
add_subdirectory(tests)
add_subdirectory(tests)

# Google {Test&Mock}
add_subdirectory(external/googletest)
include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR})
include_directories(${gmock_SOURCE_DIR}/include ${gmock_SOURCE_DIR})
Empty file added external/CMakeLists.txt
Empty file.
5 changes: 4 additions & 1 deletion include/ast/expr.hh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace rift
{
namespace Expr
{
/// @note forward declrations
__DEFAULT_FORWARD_VA(
Visitor,
Binary,
Expand Down Expand Up @@ -73,7 +74,9 @@ namespace rift
std::unique_ptr<Expr<T>> left;
std::unique_ptr<Expr<T>> right;

inline T accept(const Visitor<T>& visitor) override {return visitor.visit_binary(this);}
inline T accept(const Visitor<T>& visitor) override {
return visitor.visit_binary(this);
}
};

/// @class Grouping
Expand Down
15 changes: 10 additions & 5 deletions include/ast/printer.hh
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,20 @@ namespace rift
/// @param expr The expression to print.
/// @return string representation of the expression.
string print(ExprStr *expr);

private:

/// @brief Wraps the given expression in parentheses.
/// @param name The name of the expression.
/// @param exprs The expressions to wrap.
/// @return The wrapped expression.
string parenthesize(string name, std::vector<ExprStr*> expr);

private:

/// @brief Wraps the given expression in square brackets.
/// @param exprs The expressions to wrap.
/// @return The wrapped expression.
string group(std::vector<ExprStr*> expr);

VisitorPrinter *visitor;
};

Expand All @@ -45,14 +51,13 @@ namespace rift
{
public:
VisitorPrinter(Printer &printer);
~VisitorPrinter() = default;
virtual ~VisitorPrinter() = default;

string visit_binary(Binary<string> *expr) const;
string visit_grouping(Grouping<string> *expr) const;
string visit_literal(Literal<string> *expr) const;
string visit_unary(Unary<string> *expr) const;

private:

Printer *printer;
};
}
Expand Down
21 changes: 19 additions & 2 deletions include/driver/driver.hh
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#pragma once
#include <cli/cli.hh>

namespace rift
{
Expand All @@ -11,10 +12,26 @@ namespace rift
Driver() = default;
~Driver() = default;

/// @brief Runs the driver.
/// @brief Parses the command line arguments.
/// @param argc The number of arguments.
/// @param argv The arguments.
void run(int argc, char **argv);
/// @return 0 if the program exits successfully.
int parse(int argc, char **argv);

/// @brief Runs the driver.
void init();
private:
CLI::App app{"rift"};

#pragma mark - Command Line Options
/// @brief The version of the program.
void version();

/// @brief Runs the compiler
void runFile();

/// @brief Runs the interpreter
void runPrompt();
};
}
}
13 changes: 9 additions & 4 deletions include/scanner/scanner.hh
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace rift
struct Scanner
{
std::string source;
std::vector<Token> tokens = std::vector<Token>();
std::vector<Token> tokens;
std::unordered_map<std::string, Type> keywords;
static unsigned start, curr, line;

Expand All @@ -34,27 +34,32 @@ namespace rift
/// @param cnt The number of tokens to scan
void scan_tokens(unsigned cnt);

/// @fn scan_source
/// @brief Scans the source code and returns a list of tokens
void scan_source();
private:

#pragma mark - Token Management

void addToken(Type type) {addToken(type, NULL);};
void addToken(Type type) { addToken(type, ""); };
void addToken(Type type, std::string literal) {
tokens.push_back(Token(type, source.substr(start, curr-start), literal, line));
}

#pragma mark - Helper Functions (Inline)

inline bool atEnd() { return this->curr >= source.size(); }
inline char advance() { return source.at(curr++); }
inline char advance() { return (!atEnd()) ? source.at(curr++) : '\0'; }
inline bool isDigit(char c) { return c>='0' && c<='9'; }
inline bool isAlpha(char c) { return (c>='a' && c<='z') || (c>='A' && c<='Z') || c=='_'; }
inline bool isAlphaNumeric(char c) { return isAlpha(c) || isDigit(c); }

/// @brief Peeks at the current character
inline bool peek(char expected) { return curr<source.size() && source.at(curr) == expected; };
inline bool peek(char expected) { return !atEnd() && source.at(curr) == expected; };
/// @brief Peeks at the current character with an offset
inline bool peek_off(char expected, int offset) { return curr+offset<source.size() && source.at(curr+offset) == expected; };
/// @brief Peeks at the current character
inline char peek() { return !atEnd() ? source.at(curr) : '\0'; };
/// @brief Peeks at the next character
inline char peekNext() { return curr+1<source.size() ? source.at(curr+1) : '\0'; };
/// @brief Peeks at the next 2 characters
Expand Down
1 change: 1 addition & 0 deletions lib/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ add_executable(
)
target_compile_options(riftlang PRIVATE -Wpedantic -Wall -Wextra -Werror -Wmisleading-indentation)

add_library(riftlib STATIC ${SOURCES})
11 changes: 10 additions & 1 deletion lib/ast/printer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,15 @@ namespace rift
return result;
}

string Printer::group(vec expr)
{
string result = "[";
for (auto &e : expr)
result += " " + e->accept(*this->visitor);
result += "]";
return result;
}

#pragma mark - Visitor

VisitorPrinter::VisitorPrinter(Printer &printer)
Expand All @@ -60,7 +69,7 @@ namespace rift
{
vec v;
v.push_back(expr->expr.get());
return printer->parenthesize("group", v);
return printer->group(v);
}

string VisitorPrinter::visit_literal(Literal<string> *expr) const
Expand Down
67 changes: 42 additions & 25 deletions lib/driver/driver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,18 @@ namespace rift
std::cout << lines << std::endl;
}

void runFile(char* path)
void Driver::runFile()
{
CLI::results_t args = app.remaining();
std::string path;

if (!args.empty()) {
for (auto arg : args) path = arg;
} else {
std::cout << "File flag provided without arguments." << std::endl;
return;
}

std::ifstream file(std::string(path), std::ios::binary | std::ios::ate);

if (file) {
Expand All @@ -42,22 +52,8 @@ namespace rift
}
}

void runPrompt()
void Driver::runPrompt()
{
// left, op, right
rift::scanner::Token token = rift::scanner::Token(TokenType::PLUS,"+", "", 1);
rift::ast::Expr::Binary<std::string> expr = rift::ast::Expr::Binary<std::string>(
std::make_unique<rift::ast::Expr::Unary<std::string>>(
rift::scanner::Token(TokenType::MINUS,"-", "", 1),
std::make_unique<rift::ast::Expr::Literal<std::string>>("1")
),
rift::scanner::Token(TokenType::PLUS,"+", "", 1),
std::make_unique<rift::ast::Expr::Literal<std::string>>("2")
);

rift::ast::Printer printer = rift::ast::Printer();
std::cout << printer.print(&expr) << std::endl;

while(true)
{
std::string input = "";
Expand All @@ -69,19 +65,40 @@ namespace rift
}
}

void Driver::version()
{
std::string versionString = std::string("Rift version ") + "0.0.1" + "\n\n(c) Aman 2024";
app.set_version_flag("--version,-v", versionString);
app.footer("(c) Aman 2024");
}

# pragma mark - Driver

void Driver::run(int argc, char **argv)
int Driver::parse(int argc, char **argv)
{
if (argc > 2) {
std::cout << "Usage: rift" << std::endl;
} else if (argc == 2) {
// file
runFile(argv[1]);
} else {
// prompt
runPrompt();
try {
app.parse(argc, argv);
} catch (const CLI::ParseError &parseError) {
return app.exit(parseError);
}
// return 0;
// if (argc > 2) {
// std::cout << "Usage: rift" << std::endl;
// } else if (argc == 2) {
// // file
// runFile(argv[1]);
// } else {
// // prompt
// runPrompt();
// }
return 0;
}

void Driver::init()
{
app.add_flag_callback("--version,-v", [this]() { version(); }, "Print the version of the Rift language");
app.add_flag_callback("--prompt,-p", [this]() { runPrompt(); }, "Run the Rift prompt");
app.add_flag_callback("--file,-f", [this]() { runFile(); }, "Run a Rift source file");
}
}
}
4 changes: 2 additions & 2 deletions lib/main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@
int main(int argc, char **argv)
{
rift::driver::Driver driver;
driver.run(argc, argv);
return 0;
driver.init();
return driver.parse(argc, argv);
}
31 changes: 20 additions & 11 deletions lib/scanner/scanner.cc
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@ namespace rift
unsigned Scanner::line = 1;

Scanner::Scanner(const std::string& source) {
this->source = source;
this->source = std::string(source);
this->tokens = std::vector<Token>();

keywords = std::unordered_map<std::string, Type>();
keywords["and"] = Type::AND;
Expand Down Expand Up @@ -66,7 +67,7 @@ namespace rift
}

void Scanner::num() {
while (isDigit(advance()));
while (isDigit(peek())) advance();
if (peek('.') && isDigit(peekNext())) {
advance();
while (isDigit(advance()));
Expand All @@ -86,18 +87,10 @@ namespace rift

#pragma mark - Public API

void Scanner::scan_tokens(unsigned cnt)
{
while (cnt) {
start = curr;
scan_token();
cnt-=1;
}
}

void Scanner::scan_token()
{
char c = advance();
// if(c == ' ') return;
switch(c) {
case '(': addToken(Type::LEFT_PAREN);break;
case ')': addToken(Type::RIGHT_PAREN);break;
Expand Down Expand Up @@ -129,5 +122,21 @@ namespace rift
break;
};
}

void Scanner::scan_tokens(unsigned cnt)
{
while (cnt--) {
start = curr;
scan_token();
}
}

void Scanner::scan_source()
{
while (!atEnd()) {
start = curr;
scan_token();
}
}
}
}
Loading

0 comments on commit 1f62d85

Please sign in to comment.