Skip to content

Commit

Permalink
facing insane cpp issues
Browse files Browse the repository at this point in the history
  • Loading branch information
amanuel2 committed Jun 13, 2024
1 parent 96b4d4a commit 76073d8
Show file tree
Hide file tree
Showing 15 changed files with 489 additions and 73 deletions.
4 changes: 3 additions & 1 deletion .vscode/settings.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@
"condition_variable": "cpp",
"memory": "cpp",
"print": "cpp",
"stack": "cpp"
"stack": "cpp",
"list": "cpp",
"unordered_set": "cpp"
}
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ See `LICENSE` for more information.

# Roadmap

- Lexer
- Le
- Parser
- Compiler
- JIT
Expand Down
12 changes: 5 additions & 7 deletions include/ast/expr.hh
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@

#pragma once
#include "../scanner/tokens.hh"
#include "../utils/macros.hh"
#include <scanner/tokens.hh>
#include <utils/macros.hh>

#include <any>
#include <iostream>
#include <stdlib.h>
#include <memory>
Expand All @@ -24,9 +25,6 @@ namespace rift
Unary
);

// template <typename T = void>
// class Visitor;
// class Binary;
/// @class Expr
/// @brief Base class for all expressions
/// @details Types of expression include
Expand Down Expand Up @@ -97,8 +95,8 @@ namespace rift
class Literal: public Expr<T>
{
public:
Literal(const char* value): value(value) {};
const char* value;
Literal(std::any value): value(value) {};
std::any value;

inline T accept(const Visitor<T> &visitor) override {return visitor.visit_literal(this);}
};
Expand Down
66 changes: 66 additions & 0 deletions include/parser/parser.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@

#pragma once

#include <memory>
#include <vector>
#include <exception>
#include <scanner/tokens.hh>
#include <reader/reader.hh>
#include <ast/expr.hh>

using namespace rift::scanner;
using namespace rift::reader;

using GenExpr = rift::ast::Expr::Expr<rift::scanner::Token>;

namespace rift
{
namespace parser
{
class Parser : public Reader<Token>
{
public:
Parser(const std::vector<Token> &tokens) : Reader<Token>(tokens), tokens(tokens) {};
~Parser() = default;
protected:
std::vector<Token> tokens;
std::exception exception;

private:
#pragma mark - Grammar Evaluators

/// @note rules in order of precedence

/// @example 1 + 2 * 3
std::unique_ptr<GenExpr> expression();
/// @example 1 == 1, 1 != 2
std::unique_ptr<GenExpr> equality();
/// @example 1 > 2, 1 <= 2
std::unique_ptr<GenExpr> comparison();
/// @example 1 + 2, 1 - 2
std::unique_ptr<GenExpr> term();
/// @example 1 * 2, 1 / 2
std::unique_ptr<GenExpr> factor();
/// @example -1, !1
std::unique_ptr<GenExpr> unary();
/// @example 1, "string", true, false, nil
std::unique_ptr<GenExpr> primary();

void synchronize();

std::unique_ptr<GenExpr> parse();
};

class ParserException : public ReaderException
{
public:
ParserException(const std::string &message) : message(message) {}
~ParserException() = default;

const char *what() const noexcept override { return message.c_str(); }

private:
std::string message;
};
}
}
80 changes: 80 additions & 0 deletions include/reader/reader.hh
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@

#pragma once

#include <error/error.hh>
#include <exception>

namespace rift
{
namespace reader
{

class ReaderException;

/// @class Reader
/// @tparam T The type of the reader <Token(Parser), Char(Scanner)>
/// @brief The base class for reading through lines with utilities
template <typename T>
class Reader
{
public:
Reader(const std::vector<T> &source): source(source) {start=0;curr=0;line=1;};
~Reader() = default;

protected:
std::vector<T> source;
unsigned start, curr, line;

#pragma mark - Reader Methods

inline bool atEnd() { return this->curr >= source.size(); }
inline T advance() { return (!atEnd()) ? source.at(curr++) : T(); }
// inline typename std::enable_if<std::is_same<T, char>::value, T>::type advance() { return (!atEnd()) ? source.at(curr++) : '\0'; }
// inline typename std::enable_if<!std::is_same<T, char>::value, T>::type advance() { return (!atEnd()) ? source.at(curr++) : nullptr; }

/// @brief Peeks at the current character
inline bool peek(T expected) { return !atEnd() && source.at(curr) == expected; };
/// @brief Peeks at the current character with an offset
inline bool peek_off(T expected, int offset) { return curr+offset<source.size() && source.at(curr+offset) == expected; };
/// @brief Peeks at the current character
inline T peek() { return !atEnd() ? source.at(curr) : T(); };
/// @brief Peeks at the next character
inline T peekNext() { return curr+1<source.size() ? source.at(curr+1) : T(); };
/// @brief Peeks at the next 2 characters
inline bool peek3(T expected) { return peek_off(expected, 0) && peek_off(expected, 1) && peek_off(expected, 2); }
/// @brief Peeks the previous character
inline T peekPrev() { return curr-1>=0 ? source.at(curr-1) : T(); };

/// @brief Scans a comment and advances the cursor
inline void scanComment() { while (peek('\n')) advance();};
/// @brief Consumes a T and advances the cursor (Error if not found)
inline T consume (T expected, std::unique_ptr<ReaderException> error) {
if (peek(expected)) return advance();
rift::error::report(line, "consume", "expected " << expected);
if (error) throw error;
}
/// @brief Matches a T from a set of T's{token, character} and advances the cursor
inline bool match(std::vector<T> expected) {
for (auto &c : expected) {
if (peek(c)) {
advance();
return true;
}
}
return false;
}

inline bool match_one(T expected) { return peek(expected) ? advance() : false; }
};

/// @class ReaderException
/// @brief The base exception for the reader (implement in derived classes)
class ReaderException
{
public:
ReaderException() = default;
~ReaderException() = default;
virtual const char* what() const noexcept { return "BaseException"; }
};
}
}
30 changes: 7 additions & 23 deletions include/scanner/scanner.hh
Original file line number Diff line number Diff line change
@@ -1,28 +1,30 @@
#pragma once

#include "tokens.hh"
#include "../error/error.hh"
#include <error/error.hh>
#include <reader/reader.hh>
#include <string>
#include <stdlib.h>
#include <map>

#include <unordered_map>
#include <vector>

using namespace rift::reader;
typedef rift::scanner::Token Token;
typedef rift::scanner::TokenType Type;
namespace rift
{
namespace scanner
{
struct Scanner
struct Scanner : public Reader<char>
{
std::string source;
std::vector<char> source;
std::vector<Token> tokens;
std::unordered_map<std::string, Type> keywords;
static unsigned start, curr, line;

Scanner(const std::string& source);
Scanner(const std::vector<char>& source);
~Scanner(){}

/// @fn scan_token
Expand All @@ -43,33 +45,15 @@ namespace rift

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));
tokens.push_back(Token(type, std::string(source.begin()+start, source.begin()+curr), literal, line));
}

#pragma mark - Helper Functions (Inline)

inline bool atEnd() { return this->curr >= source.size(); }
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 !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
inline bool peek3(char expected) { return peek_off(expected, 0) && peek_off(expected, 1) && peek_off(expected, 2); }

/// @brief Scans a comment and advances the cursor
inline void scanComment() { while (peek('\n')) advance();};
/// @brief Matches a character and advances the cursor
inline bool match(char expected) { return !atEnd() && (source.at(curr)==expected ? curr++ : false); }

#pragma mark - Token Scanners

/// @brief Scans a string literal
Expand Down
89 changes: 68 additions & 21 deletions include/scanner/tokens.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@

#pragma once
#include <string>
#include <any>

namespace rift
{
Expand All @@ -11,23 +12,53 @@ namespace rift
enum TokenType
{
// Single-character tokens
LEFT_PAREN, RIGHT_PAREN, LEFT_BRACE, RIGHT_BRACE,
COMMA, DOT, MINUS, PLUS, SEMICOLON, SLASH, STAR,
LEFT_PAREN,
RIGHT_PAREN,
LEFT_BRACE,
RIGHT_BRACE,
COMMA,
DOT,
MINUS,
PLUS,
SEMICOLON,
SLASH,
STAR,

// One or two character tokens
BANG, BANG_EQUAL,
EQUAL, EQUAL_EQUAL,
GREATER, GREATER_EQUAL,
LESS, LESS_EQUAL,
SEPARATOR, WHITESPACE,
BANG,
BANG_EQUAL,
EQUAL,
EQUAL_EQUAL,
GREATER,
GREATER_EQUAL,
LESS,
LESS_EQUAL,
SEPARATOR,
WHITESPACE,
OPERATOR,

// Literals
IDENTIFIER, STRINGLITERAL, NUMERICLITERAL,
IDENTIFIER,
STRINGLITERAL,
NUMERICLITERAL,

// Keywords
AND, CLASS, ELSE, FALSE, FUN, FOR, IF, NIL, OR,
PRINT, RETURN, SUPER, THIS, TRUE, VAR, WHILE,
AND,
CLASS,
ELSE,
FALSE,
FUN,
FOR,
IF,
NIL,
OR,
PRINT,
RETURN,
SUPER,
THIS,
TRUE,
VAR,
WHILE,

EOFF
};
Expand All @@ -37,20 +68,36 @@ namespace rift
struct Token
{
TokenType type;
std::string text, lexeme, literal;
std::string text, lexeme;
std::any literal;

int line;

Token(TokenType type, std::string lexeme, std::string literal, int line)
Token(TokenType type, std::string lexeme, std::any literal, int line)
{
this->type = type; this->lexeme = lexeme;
this->literal = literal; this->line = line;
this->type = type;
this->lexeme = lexeme;
this->literal = literal;
this->line = line;
}
private:
/// @brief Converts a TokenType to a string
std::string convertTypeString(TokenType type);
/// @brief Converts a Token to a string
std::string to_string();

Token() : type(TokenType::EOFF), lexeme(""), literal(0), line(0) {}

/// @brief Converts a TokenType to a string
static std::string convertTypeString(TokenType type);
/// @brief Converts a Token to a string
std::string to_string() const;

// friend std::ostream &operator<<(std::ostream &os, const Token &token);
bool operator==(const Token &token);
};
}
}

// std::ostream& operator<<(std::ostream& os, const Token& token) {
// os << std::string("Token(Type=") << token.convertTypeString(token.type)
// /*<< ", Lexeme=\"" << token.lexeme
// << "\", Literal=" << token.literal.type().name()
// << ", Line=" << token.line << ")"*/;
// return os;
// }

}
Loading

0 comments on commit 76073d8

Please sign in to comment.