Merge pull request #16 from rafalgrodzinski/7-add-logger

7 add logger
This commit is contained in:
Rafał
2025-07-03 22:55:23 +09:00
committed by GitHub
49 changed files with 832 additions and 550 deletions

2
.gitignore vendored
View File

@@ -3,5 +3,5 @@
brb
.vscode/settings.json
*.dSYM
#*.brc
*.brc
build/

35
src/Error.cpp Normal file
View File

@@ -0,0 +1,35 @@
#include "Error.h"
Error::Error(int line, int column, string lexme) :
kind(ErrorKind::LEXER_ERROR), line(line), column(column), lexme(lexme) { }
Error::Error(shared_ptr<Token> actualToken, optional<TokenKind> expectedTokenKind, optional<string> message) :
kind(ErrorKind::PARSER_ERROR), actualToken(actualToken), expectedTokenKind(expectedTokenKind), message(message) { }
ErrorKind Error::getKind() {
return kind;
}
int Error::getLine() {
return line;
}
int Error::getColumn() {
return column;
}
string Error::getLexme() {
return lexme;
}
shared_ptr<Token> Error::getActualToken() {
return actualToken;
}
optional<TokenKind> Error::getExpectedTokenKind() {
return expectedTokenKind;
}
optional<string> Error::getMessage() {
return message;
}

43
src/Error.h Normal file
View File

@@ -0,0 +1,43 @@
#ifndef ERROR_H
#define ERROR_H
#include <iostream>
class Token;
enum class TokenKind;
using namespace std;
enum class ErrorKind {
LEXER_ERROR,
PARSER_ERROR
};
class Error {
private:
ErrorKind kind;
int line;
int column;
string lexme;
shared_ptr<Token> actualToken;
optional<TokenKind> expectedTokenKind;
optional<string> message;
public:
Error(int line, int column, string lexme);
Error(shared_ptr<Token> actualToken, optional<TokenKind> expectedTokenKind, optional<string> message);
ErrorKind getKind();
int getLine();
int getColumn();
string getLexme();
shared_ptr<Token> getActualToken();
optional<TokenKind> getExpectedTokenKind();
optional<string> getMessage();
};
#endif

View File

@@ -1,5 +1,9 @@
#include "Lexer.h"
#include "Token.h"
#include "Error.h"
#include "Logger.h"
Lexer::Lexer(string source): source(source) {
}
@@ -8,34 +12,33 @@ vector<shared_ptr<Token>> Lexer::getTokens() {
currentLine = 0;
currentColumn = 0;
errors.clear();
vector<shared_ptr<Token>> tokens;
shared_ptr<Token> token;
do {
token = nextToken();
// Got a nullptr, shouldn't have happened
if (!token) {
cerr << "Failed to scan tokens" << endl;
exit(1);
if (token != nullptr) {
// Don't add new line as the first token
if (tokens.empty() && token->isOfKind({TokenKind::NEW_LINE}))
continue;
// Insert an additional new line just before end
if (token->getKind() == TokenKind::END && tokens.back()->getKind() != TokenKind::NEW_LINE)
tokens.push_back(make_shared<Token>(TokenKind::NEW_LINE, "\n", token->getLine(), token->getColumn()));
// filter out multiple new lines
if (tokens.empty() || token->getKind() != TokenKind::NEW_LINE || tokens.back()->getKind() != token->getKind())
tokens.push_back(token);
}
} while (token == nullptr || token->getKind() != TokenKind::END);
// Abort scanning if we got an error
if (!token->isValid()) {
cerr << "Unexpected character '" << token->getLexme() << "' at " << token->getLine() << ":" << token->getColumn() << endl;
exit(1);
}
if (!errors.empty()) {
for (shared_ptr<Error> &error : errors)
Logger::print(error);
exit(1);
}
// Don't add new line as the first token
if (tokens.empty() && token->isOfKind({TokenKind::NEW_LINE}))
continue;
// Insert an additional new line just before end
if (token->getKind() == TokenKind::END && tokens.back()->getKind() != TokenKind::NEW_LINE)
tokens.push_back(make_shared<Token>(TokenKind::NEW_LINE, "\n", token->getLine(), token->getColumn()));
// filter out multiple new lines
if (tokens.empty() || token->getKind() != TokenKind::NEW_LINE || tokens.back()->getKind() != token->getKind())
tokens.push_back(token);
} while (token->getKind() != TokenKind::END);
return tokens;
}
@@ -49,7 +52,7 @@ shared_ptr<Token> Lexer::nextToken() {
shared_ptr<Token> token;
// ignore // comment
token = match(TokenKind::INVALID, "//", false);
token = match(TokenKind::END, "//", false); // dummy token kind
if (token) {
currentIndex += 2;
do {
@@ -69,7 +72,7 @@ shared_ptr<Token> Lexer::nextToken() {
}
// ignore /* */ comment
token = match(TokenKind::INVALID, "/*", false);
token = match(TokenKind::END, "/*", false); // dummy token kind
if (token) {
shared_ptr<Token> newLineToken = nullptr; // we want to return the first new line we come accross
int depth = 1; // so we can embed comments inside each other
@@ -78,23 +81,25 @@ shared_ptr<Token> Lexer::nextToken() {
token = match(TokenKind::NEW_LINE, "\n", false);
newLineToken = newLineToken ? newLineToken : token;
if (token) {
continue;;
continue;
}
// eof
token = matchEnd();
if (token)
return make_shared<Token>(TokenKind::INVALID, "", currentLine, currentColumn);
if (token) {
markError();
return token;
}
// go deeper
token = match(TokenKind::INVALID, "/*", false);
token = match(TokenKind::END, "/*", false); // dummy token kind
if (token) {
depth++;
continue;
}
// go back
token = match(TokenKind::INVALID, "*/", false);
token = match(TokenKind::END, "*/", false); // dummy token kind
if (token) {
depth--;
}
@@ -265,10 +270,14 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
return matchInvalid();
markError();
return nullptr;
}
shared_ptr<Token> Lexer::match(TokenKind kind, string lexme, bool needsSeparator) {
if (currentIndex + lexme.length() > source.length())
return nullptr;
bool isMatching = source.compare(currentIndex, lexme.length(), lexme) == 0;
bool isSeparatorSatisfied = !needsSeparator || isSeparator(currentIndex + lexme.length());
@@ -359,8 +368,10 @@ shared_ptr<Token> Lexer::matchReal() {
while (nextIndex < source.length() && isDecDigit(nextIndex))
nextIndex++;
if (!isSeparator(nextIndex))
return matchInvalid();
if (!isSeparator(nextIndex)) {
markError();
return nullptr;
}
string lexme = source.substr(currentIndex, nextIndex - currentIndex);
shared_ptr<Token> token = make_shared<Token>(TokenKind::REAL, lexme, currentLine, currentColumn);
@@ -390,10 +401,6 @@ shared_ptr<Token> Lexer::matchEnd() {
return nullptr;
}
shared_ptr<Token> Lexer::matchInvalid() {
return make_shared<Token>(TokenKind::INVALID, source.substr(currentIndex, 1), currentLine, currentColumn);
}
bool Lexer::isWhiteSpace(int index) {
char character = source.at(index);
return character == ' ' || character == '\t';
@@ -451,7 +458,7 @@ bool Lexer::isSeparator(int index) {
}
}
void Lexer::advanceWithToken(shared_ptr<Token> token) {
void Lexer::advanceWithToken(shared_ptr<Token> token) {
if (token->getKind() == TokenKind::NEW_LINE) {
currentLine++;
currentColumn = 0;
@@ -459,4 +466,20 @@ bool Lexer::isSeparator(int index) {
currentColumn += token->getLexme().length();
}
currentIndex += token->getLexme().length();
}
}
void Lexer::markError() {
int startIndex = currentIndex;
int startColumn = currentColumn;
string lexme;
if (currentIndex < source.length()) {
do {
currentIndex++;
currentColumn++;
} while (!isSeparator(currentIndex));
lexme = source.substr(startIndex, currentIndex - startIndex);
} else {
lexme = "EOF";
}
errors.push_back(make_shared<Error>(currentLine, startColumn, lexme));
}

View File

@@ -3,7 +3,9 @@
#include <vector>
#include "Token.h"
class Token;
enum class TokenKind;
class Error;
using namespace std;
@@ -13,6 +15,7 @@ private:
int currentIndex;
int currentLine;
int currentColumn;
vector<shared_ptr<Error>> errors;
shared_ptr<Token> nextToken();
shared_ptr<Token> match(TokenKind kind, string lexme, bool needsSeparator);
@@ -22,7 +25,6 @@ private:
shared_ptr<Token> matchReal();
shared_ptr<Token> matchIdentifier();
shared_ptr<Token> matchEnd();
shared_ptr<Token> matchInvalid();
bool isWhiteSpace(int index);
bool isDecDigit(int index);
@@ -32,6 +34,8 @@ private:
bool isSeparator(int index);
void advanceWithToken(shared_ptr<Token> token);
void markError();
public:
Lexer(string source);
vector<shared_ptr<Token>> getTokens();

View File

@@ -63,10 +63,6 @@ int Token::getColumn() {
return column;
}
bool Token::isValid() {
return kind != TokenKind::INVALID;
}
bool Token::isOfKind(vector<TokenKind> kinds) {
for (TokenKind &kind : kinds) {
if (kind == this->kind)
@@ -75,82 +71,3 @@ bool Token::isOfKind(vector<TokenKind> kinds) {
return false;
}
string Token::toString() {
switch (kind) {
case TokenKind::PLUS:
return "+";
case TokenKind::MINUS:
return "-";
case TokenKind::STAR:
return "*";
case TokenKind::SLASH:
return "/";
case TokenKind::PERCENT:
return "%";
case TokenKind::EQUAL:
return "=";
case TokenKind::NOT_EQUAL:
return "";
case TokenKind::LESS:
return "<";
case TokenKind::LESS_EQUAL:
return "";
case TokenKind::GREATER:
return ">";
case TokenKind::GREATER_EQUAL:
return "";
case TokenKind::LEFT_PAREN:
return "(";
case TokenKind::RIGHT_PAREN:
return ")";
case TokenKind::COMMA:
return ",";
case TokenKind::COLON:
return ":";
case TokenKind::SEMICOLON:
return ";";
case TokenKind::LEFT_ARROW:
return "";
case TokenKind::RIGHT_ARROW:
return "";
case TokenKind::BOOL:
return "BOOL(" + lexme + ")";
case TokenKind::INTEGER_DEC:
return "INTEGER_DEC(" + lexme + ")";
case TokenKind::INTEGER_HEX:
return "INTEGER_HEX(" + lexme + ")";
case TokenKind::INTEGER_BIN:
return "INTEGER_BIN(" + lexme + ")";
case TokenKind::REAL:
return "REAL(" + lexme + ")";
case TokenKind::IDENTIFIER:
return "IDENTIFIER(" + lexme + ")";
case TokenKind::TYPE:
return "TYPE(" + lexme + ")";
case TokenKind::IF:
return "IF";
case TokenKind::ELSE:
return "ELSE";
case TokenKind::FUNCTION:
return "FUNCTION";
case TokenKind::RETURN:
return "RETURN";
case TokenKind::REPEAT:
return "REPEAT";
case TokenKind::M_EXTERN:
return "@EXTERN";
case TokenKind::NEW_LINE:
return "";
case TokenKind::END:
return "END";
case TokenKind::INVALID:
return "INVALID";
}
}

View File

@@ -46,9 +46,7 @@ enum class TokenKind {
M_EXTERN,
NEW_LINE,
END,
INVALID
END
};
class Token {
@@ -71,9 +69,7 @@ public:
string getLexme();
int getLine();
int getColumn();
bool isValid();
bool isOfKind(vector<TokenKind> kinds);
string toString();
};
#endif

437
src/Logger.cpp Normal file
View File

@@ -0,0 +1,437 @@
#include "Logger.h"
#include <iostream>
#include "Lexer/Token.h"
#include "Parser/Statement/Statement.h"
#include "Parser/Statement/StatementMetaExternFunction.h"
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
#include "Parser/Statement/StatementRepeat.h"
#include "Parser/Statement/StatementExpression.h"
#include "Parser/Expression/Expression.h"
#include "Parser/Expression/ExpressionBinary.h"
#include "Parser/Expression/ExpressionIfElse.h"
#include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionGrouping.h"
#include "Parser/Expression/ExpressionLiteral.h"
#include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionBlock.h"
#include "Error.h"
string Logger::toString(shared_ptr<Token> token) {
switch (token->getKind()) {
case TokenKind::PLUS:
return "+";
case TokenKind::MINUS:
return "-";
case TokenKind::STAR:
return "*";
case TokenKind::SLASH:
return "/";
case TokenKind::PERCENT:
return "%";
case TokenKind::EQUAL:
return "=";
case TokenKind::NOT_EQUAL:
return "";
case TokenKind::LESS:
return "<";
case TokenKind::LESS_EQUAL:
return "";
case TokenKind::GREATER:
return ">";
case TokenKind::GREATER_EQUAL:
return "";
case TokenKind::LEFT_PAREN:
return "(";
case TokenKind::RIGHT_PAREN:
return ")";
case TokenKind::COMMA:
return ",";
case TokenKind::COLON:
return ":";
case TokenKind::SEMICOLON:
return ";";
case TokenKind::LEFT_ARROW:
return "";
case TokenKind::RIGHT_ARROW:
return "";
case TokenKind::BOOL:
return "BOOL(" + token->getLexme() + ")";
case TokenKind::INTEGER_DEC:
return "INT_DEC(" + token->getLexme() + ")";
case TokenKind::INTEGER_HEX:
return "INT_HEX(" + token->getLexme() + ")";
case TokenKind::INTEGER_BIN:
return "INT_BIN(" + token->getLexme() + ")";
case TokenKind::REAL:
return "REAL(" + token->getLexme() + ")";
case TokenKind::IDENTIFIER:
return "ID(" + token->getLexme() + ")";
case TokenKind::TYPE:
return "TYPE(" + token->getLexme() + ")";
case TokenKind::IF:
return "IF";
case TokenKind::ELSE:
return "ELSE";
case TokenKind::FUNCTION:
return "FUN";
case TokenKind::RETURN:
return "RET";
case TokenKind::REPEAT:
return "REP";
case TokenKind::M_EXTERN:
return "@EXTERN";
case TokenKind::NEW_LINE:
return "";
case TokenKind::END:
return "END";
}
}
string Logger::toString(TokenKind tokenKind) {
switch (tokenKind) {
case TokenKind::PLUS:
return "+";
case TokenKind::MINUS:
return "-";
case TokenKind::STAR:
return "*";
case TokenKind::SLASH:
return "/";
case TokenKind::PERCENT:
return "%";
case TokenKind::EQUAL:
return "=";
case TokenKind::NOT_EQUAL:
return "";
case TokenKind::LESS:
return "<";
case TokenKind::LESS_EQUAL:
return "";
case TokenKind::GREATER:
return ">";
case TokenKind::GREATER_EQUAL:
return "";
case TokenKind::LEFT_PAREN:
return "(";
case TokenKind::RIGHT_PAREN:
return ")";
case TokenKind::COMMA:
return ",";
case TokenKind::COLON:
return ":";
case TokenKind::SEMICOLON:
return ";";
case TokenKind::LEFT_ARROW:
return "";
case TokenKind::RIGHT_ARROW:
return "";
case TokenKind::BOOL:
return "LITERAL(BOOLEAN)";
case TokenKind::INTEGER_DEC:
case TokenKind::INTEGER_HEX:
case TokenKind::INTEGER_BIN:
return "LITERAL(INTEGER)";
case TokenKind::REAL:
return "LITERAL(REAL)";
case TokenKind::IDENTIFIER:
return "LITERAL(ID)";
case TokenKind::TYPE:
return "TYPE";
case TokenKind::IF:
return "IF";
case TokenKind::ELSE:
return "ELSE";
case TokenKind::FUNCTION:
return "FUN";
case TokenKind::RETURN:
return "RET";
case TokenKind::REPEAT:
return "REP";
case TokenKind::M_EXTERN:
return "@EXTERN";
case TokenKind::NEW_LINE:
return "";
case TokenKind::END:
return "END";
}
}
string Logger::toString(shared_ptr<Statement> statement) {
switch (statement->getKind()) {
case StatementKind::META_EXTERN_FUNCTION:
return toString(dynamic_pointer_cast<StatementMetaExternFunction>(statement));
case StatementKind::VARIABLE:
return toString(dynamic_pointer_cast<StatementVariable>(statement));
case StatementKind::FUNCTION:
return toString(dynamic_pointer_cast<StatementFunction>(statement));
case StatementKind::BLOCK:
return toString(dynamic_pointer_cast<StatementBlock>(statement));
case StatementKind::ASSIGNMENT:
return toString(dynamic_pointer_cast<StatementAssignment>(statement));
case StatementKind::RETURN:
return toString(dynamic_pointer_cast<StatementReturn>(statement));
case StatementKind::REPEAT:
return toString(dynamic_pointer_cast<StatementRepeat>(statement));
case StatementKind::EXPRESSION:
return toString(dynamic_pointer_cast<StatementExpression>(statement));
}
}
string Logger::toString(shared_ptr<StatementMetaExternFunction> statement) {
string text;
string argsString;
for (int i = 0; i < statement->getArguments().size(); i++) {
auto arg = statement->getArguments().at(i);
argsString += format("ARG({}, {})", arg.first, toString(arg.second));
}
text += format("@EXTERN FUN(\"{}\"|{}|{})", statement->getName(), argsString, toString(statement->getReturnValueType()));
return text;
}
string Logger::toString(shared_ptr<StatementVariable> statement) {
return format("{}({}|{})", statement->getName(), toString(statement->getValueType()), toString(statement->getExpression()));
}
string Logger::toString(shared_ptr<StatementFunction> statement) {
string text;
string argsString;
for (int i = 0; i < statement->getArguments().size(); i++) {
auto arg = statement->getArguments().at(i);
argsString += format("ARG({}, {})", arg.first, toString(arg.second));
}
text += format("FUN(\"{}\"|{}|{}):\n", statement->getName(), argsString, toString(statement->getReturnValueType()));
text += toString(statement->getStatementBlock());
return text;
}
string Logger::toString(shared_ptr<StatementBlock> statement) {
string text;
for (int i=0; i<statement->getStatements().size(); i++) {
text += toString(statement->getStatements().at(i));
if (i < statement->getStatements().size() - 1)
text += "\n";
}
return text;
}
string Logger::toString(shared_ptr<StatementAssignment> statement) {
return format("{} <- {}", statement->getName(), toString(statement->getExpression()));
}
string Logger::toString(shared_ptr<StatementReturn> statement) {
string text = "RET";
if (statement->getExpression() != nullptr)
text += format("({})", toString(statement->getExpression()));
return text;
}
string Logger::toString(shared_ptr<StatementRepeat> statement) {
string text;
string initStatement;
string preCondition;
string postCondition;
if (statement->getInitStatement() != nullptr)
initStatement = toString(statement->getInitStatement());
if (statement->getPostConditionExpression() != nullptr)
preCondition = toString(statement->getPreConditionExpression());
if (statement->getPostConditionExpression() != nullptr)
postCondition = toString(statement->getPostConditionExpression());
text += format("REP({}|{}|{}):\n", initStatement, preCondition, postCondition);
text += toString(statement->getBodyBlockStatement());
return text;
}
string Logger::toString(shared_ptr<StatementExpression> statement) {
return format("EXPR({})", toString(statement->getExpression()));
}
string Logger::toString(ValueType valueType) {
switch (valueType) {
case ValueType::NONE:
return "NONE";
case ValueType::BOOL:
return "BOOL";
case ValueType::SINT32:
return "SINT32";
case ValueType::REAL32:
return "REAL32";
}
}
string Logger::toString(shared_ptr<Expression> expression) {
switch (expression->getKind()) {
case ExpressionKind::BINARY:
return toString(dynamic_pointer_cast<ExpressionBinary>(expression));
case ExpressionKind::IF_ELSE:
return toString(dynamic_pointer_cast<ExpressionIfElse>(expression));
case ExpressionKind::VAR:
return toString(dynamic_pointer_cast<ExpressionVariable>(expression));
case ExpressionKind::GROUPING:
return toString(dynamic_pointer_cast<ExpressionGrouping>(expression));
case ExpressionKind::LITERAL:
return toString(dynamic_pointer_cast<ExpressionLiteral>(expression));
case ExpressionKind::CALL:
return toString(dynamic_pointer_cast<ExpressionCall>(expression));
case ExpressionKind::BLOCK:
return toString(dynamic_pointer_cast<ExpressionBlock>(expression));
}
}
string Logger::toString(shared_ptr<ExpressionBinary> expression) {
switch (expression->getOperation()) {
case ExpressionBinaryOperation::EQUAL:
return "{= " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::NOT_EQUAL:
return "{!= " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::LESS:
return "{< " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::LESS_EQUAL:
return "{<= " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::GREATER:
return "{> " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::GREATER_EQUAL:
return "{<= " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::ADD:
return "{+ " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::SUB:
return "{- " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::MUL:
return "{* " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::DIV:
return "{/ " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
case ExpressionBinaryOperation::MOD:
return "{% " + toString(expression->getLeft()) + " " + toString(expression->getRight()) + "}";
}
}
string Logger::toString(shared_ptr<ExpressionIfElse> expression) {
string text;
text += format("IF({}):\n", toString(expression->getCondition()));
text += toString(expression->getThenBlock());
if (expression->getElseBlock() != nullptr) {
text += "\nELSE:\n";
text += toString(expression->getElseBlock());
}
text += "\n;";
return text;
}
string Logger::toString(shared_ptr<ExpressionVariable> expression) {
return format("VAR({})", expression->getName());
}
string Logger::toString(shared_ptr<ExpressionGrouping> expression) {
return format("({})", toString(expression->getExpression()));
}
string Logger::toString(shared_ptr<ExpressionLiteral> expression) {
switch (expression->getValueType()) {
case ValueType::NONE:
return "NONE";
case ValueType::BOOL:
return expression->getBoolValue() ? "true" : "false";
case ValueType::SINT32:
return to_string(expression->getSint32Value());
case ValueType::REAL32:
return to_string(expression->getReal32Value());
}
}
string Logger::toString(shared_ptr<ExpressionCall> expression) {
string argsString;
for (int i = 0; i < expression->getArgumentExpressions().size(); i++) {
argsString += toString(expression->getArgumentExpressions().at(i));
if (i < expression->getArgumentExpressions().size() - 1)
argsString += ", ";
}
return format("CALL({}|{})", expression->getName(), argsString);
}
string Logger::toString(shared_ptr<ExpressionBlock> expression) {
string text;
text += toString(expression->getStatementBlock());
if (expression->getResultStatementExpression() != nullptr)
text += toString(expression->getResultStatementExpression());
return text;
}
void Logger::print(vector<shared_ptr<Token>> tokens) {
for (int i=0; i<tokens.size(); i++) {
cout << i << "|" << toString(tokens.at(i));
if (i < tokens.size() - 1)
cout << " ";
}
cout << endl;
}
void Logger::print(vector<shared_ptr<Statement>> statements) {
for (shared_ptr<Statement> &statement : statements) {
cout << toString(statement) << endl << endl;
}
}
void Logger::print(shared_ptr<Error> error) {
string message;
switch (error->getKind()) {
case ErrorKind::LEXER_ERROR:
message = format("Unexpected token \"{}\" at line: {}, column: {}", error->getLexme(), error->getLine() + 1, error->getColumn() + 1);
break;
case ErrorKind::PARSER_ERROR:
shared_ptr<Token> token = error->getActualToken();
optional<TokenKind> expectedTokenKind = error->getExpectedTokenKind();
optional<string> errorMessage = error->getMessage();
if (expectedTokenKind) {
message = format(
"Expected token {} but instead found \"{}\" at line: {}, column: {}",
toString(*expectedTokenKind), token->getLexme(), token->getLine() + 1, token->getColumn() + 1
);
} else {
message = format(
"Unexpected token \"{}\" found at line: {}, column: {}",
token->getLexme(), token->getLine() + 1, token->getColumn() + 1
);
}
if (errorMessage)
message += format(". {}", *errorMessage);
break;
}
cout << message << endl;
}

65
src/Logger.h Normal file
View File

@@ -0,0 +1,65 @@
#ifndef LOGGER_H
#define LOGGER_H
#include <vector>
class Token;
enum class TokenKind;
class Statement;
class StatementMetaExternFunction;
class StatementVariable;
class StatementFunction;
class StatementBlock;
class StatementAssignment;
class StatementReturn;
class StatementRepeat;
class StatementExpression;
class Expression;
class ExpressionBinary;
class ExpressionIfElse;
class ExpressionVariable;
class ExpressionGrouping;
class ExpressionLiteral;
class ExpressionCall;
class ExpressionBlock;
enum class ValueType;
class Error;
using namespace std;
class Logger {
private:
static string toString(shared_ptr<Token> token);
static string toString(TokenKind tokenKind);
static string toString(shared_ptr<Statement> statement);
static string toString(shared_ptr<StatementMetaExternFunction> statement);
static string toString(shared_ptr<StatementVariable> statement);
static string toString(shared_ptr<StatementFunction> statement);
static string toString(shared_ptr<StatementBlock> statement);
static string toString(shared_ptr<StatementAssignment> statement);
static string toString(shared_ptr<StatementReturn> statement);
static string toString(shared_ptr<StatementRepeat> statement);
static string toString(shared_ptr<StatementExpression> statement);
static string toString(shared_ptr<Expression> expression);
static string toString(shared_ptr<ExpressionBinary> expression);
static string toString(shared_ptr<ExpressionIfElse> expression);
static string toString(shared_ptr<ExpressionVariable> expression);
static string toString(shared_ptr<ExpressionGrouping> expression);
static string toString(shared_ptr<ExpressionLiteral> expression);
static string toString(shared_ptr<ExpressionCall> expression);
static string toString(shared_ptr<ExpressionBlock> expression);
static string toString(ValueType valueType);
public:
static void print(vector<shared_ptr<Token>> tokens);
static void print(vector<shared_ptr<Statement>> statements);
static void print(shared_ptr<Error> error);
};
#endif

View File

@@ -11,11 +11,3 @@ ExpressionKind Expression::getKind() {
ValueType Expression::getValueType() {
return valueType;
}
bool Expression::isValid() {
return kind != ExpressionKind::INVALID;
}
string Expression::toString(int indent) {
return "EXPRESSION";
}

View File

@@ -15,8 +15,7 @@ enum class ExpressionKind {
IF_ELSE,
VAR,
CALL,
BLOCK,
INVALID
BLOCK
};
class Expression {
@@ -28,10 +27,9 @@ protected:
public:
Expression(ExpressionKind kind, ValueType valueType);
virtual ~Expression() { }
ExpressionKind getKind();
ValueType getValueType();
bool isValid();
virtual string toString(int indent);
};
#endif

View File

@@ -71,30 +71,3 @@ shared_ptr<Expression> ExpressionBinary::getLeft() {
shared_ptr<Expression> ExpressionBinary::getRight() {
return right;
}
string ExpressionBinary::toString(int indent) {
switch (operation) {
case ExpressionBinaryOperation::EQUAL:
return "{= " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::NOT_EQUAL:
return "{!= " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::LESS:
return "{< " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::LESS_EQUAL:
return "{<= " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::GREATER:
return "{> " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::GREATER_EQUAL:
return "{<= " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::ADD:
return "{+ " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::SUB:
return "{- " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::MUL:
return "{* " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::DIV:
return "{/ " + left->toString(0) + " " + right->toString(0) + "}";
case ExpressionBinaryOperation::MOD:
return "{% " + left->toString(0) + " " + right->toString(0) + "}";
}
}

View File

@@ -26,5 +26,4 @@ public:
ExpressionBinaryOperation getOperation();
shared_ptr<Expression> getLeft();
shared_ptr<Expression> getRight();
string toString(int indent) override;
};

View File

@@ -11,7 +11,7 @@ Expression(ExpressionKind::BLOCK, ValueType::NONE) {
valueType = resultStatementExpression->getExpression()->getValueType();
statements.pop_back();
} else {
resultStatementExpression = make_shared<StatementExpression>(ExpressionLiteral::NONE);
resultStatementExpression = make_shared<StatementExpression>(make_shared<ExpressionLiteral>());
}
statementBlock = make_shared<StatementBlock>(statements);
}
@@ -23,7 +23,3 @@ shared_ptr<StatementBlock> ExpressionBlock::getStatementBlock() {
shared_ptr<StatementExpression> ExpressionBlock::getResultStatementExpression() {
return resultStatementExpression;
}
string ExpressionBlock::toString(int indent) {
return "";
}

View File

@@ -13,5 +13,4 @@ public:
ExpressionBlock(vector<shared_ptr<Statement>> statements);
shared_ptr<StatementBlock> getStatementBlock();
shared_ptr<StatementExpression> getResultStatementExpression();
string toString(int indent) override;
};

View File

@@ -10,17 +10,3 @@ string ExpressionCall::getName() {
vector<shared_ptr<Expression>> ExpressionCall::getArgumentExpressions() {
return argumentExpressions;
}
string ExpressionCall::toString(int indent) {
string value;
value += "CALL(" + name + "):";
for (shared_ptr<Expression> &argumentExpression : argumentExpressions) {
value += "\n";
for (int ind=0; ind<indent+1; ind++)
value += " ";
value += argumentExpression->toString(indent+1) + ",";
}
return value;
}

View File

@@ -9,5 +9,4 @@ public:
ExpressionCall(string name, vector<shared_ptr<Expression>> argumentExpressions);
string getName();
vector<shared_ptr<Expression>> getArgumentExpressions();
string toString(int indent) override;
};

View File

@@ -6,7 +6,3 @@ Expression(ExpressionKind::GROUPING, expression->getValueType()), expression(exp
shared_ptr<Expression> ExpressionGrouping::getExpression() {
return expression;
}
string ExpressionGrouping::toString(int indent) {
return "( " + expression->toString(0) + " )";
}

View File

@@ -7,5 +7,4 @@ private:
public:
ExpressionGrouping(shared_ptr<Expression> expression);
shared_ptr<Expression> getExpression();
string toString(int indent) override;
};

View File

@@ -20,21 +20,3 @@ shared_ptr<ExpressionBlock> ExpressionIfElse::getThenBlock() {
shared_ptr<ExpressionBlock> ExpressionIfElse::getElseBlock() {
return elseBlock;
}
string ExpressionIfElse::toString(int indent) {
string value;
value += "IF(" + condition->toString(0) + "):\n";
value += thenBlock->toString(indent+1);
if (elseBlock != nullptr) {
for (int ind=0; ind<indent; ind++)
value += " ";
value += "ELSE:\n";
value += elseBlock->toString(indent+1);
}
for (int ind=0; ind<indent; ind++)
value += " ";
value += ";";
return value;
}

View File

@@ -13,5 +13,4 @@ public:
shared_ptr<Expression> getCondition();
shared_ptr<ExpressionBlock> getThenBlock();
shared_ptr<ExpressionBlock> getElseBlock();
string toString(int indent) override;
};

View File

@@ -1,13 +0,0 @@
#include "ExpressionInvalid.h"
ExpressionInvalid::ExpressionInvalid(shared_ptr<Token> token):
Expression(ExpressionKind::INVALID, ValueType::NONE), token(token) {
}
shared_ptr<Token> ExpressionInvalid::getToken() {
return token;
}
string ExpressionInvalid::toString(int indent) {
return "Invalid token " + token->toString() + " at " + to_string(token->getLine()) + ":" + to_string(token->getColumn()) + "\n";
}

View File

@@ -1,11 +0,0 @@
#include "Parser/Expression/Expression.h"
class ExpressionInvalid: public Expression {
private:
shared_ptr<Token> token;
public:
ExpressionInvalid(shared_ptr<Token> token);
shared_ptr<Token> getToken();
string toString(int indent) override;
};

View File

@@ -1,7 +1,5 @@
#include "ExpressionLiteral.h"
shared_ptr<ExpressionLiteral> ExpressionLiteral::NONE;
ExpressionLiteral::ExpressionLiteral():
Expression(ExpressionKind::LITERAL, ValueType::NONE) { }
@@ -54,16 +52,3 @@ int32_t ExpressionLiteral::getSint32Value() {
float ExpressionLiteral::getReal32Value() {
return real32Value;
}
string ExpressionLiteral::toString(int indent) {
switch (valueType) {
case ValueType::NONE:
return "NONE";
case ValueType::BOOL:
return boolValue ? "true" : "false";
case ValueType::SINT32:
return to_string(sint32Value);
case ValueType::REAL32:
return to_string(real32Value);
}
}

View File

@@ -6,14 +6,11 @@ private:
int32_t sint32Value;
float real32Value;
ExpressionLiteral();
public:
static shared_ptr<ExpressionLiteral> NONE;
ExpressionLiteral(shared_ptr<Token> token);
ExpressionLiteral();
bool getBoolValue();
int32_t getSint32Value();
float getReal32Value();
string toString(int indent) override;
};

View File

@@ -6,7 +6,3 @@ Expression(ExpressionKind::VAR, ValueType::NONE), name(name) { }
string ExpressionVariable::getName() {
return name;
}
string ExpressionVariable::toString(int indent) {
return "VAR(" + name + ")";
}

View File

@@ -7,5 +7,4 @@ private:
public:
ExpressionVariable(string name);
string getName();
string toString(int indent) override;
};

View File

@@ -1,5 +1,8 @@
#include "Parser.h"
#include "Error.h"
#include "Logger.h"
#include "Parser/Expression/ExpressionGrouping.h"
#include "Parser/Expression/ExpressionLiteral.h"
#include "Parser/Expression/ExpressionVariable.h"
@@ -7,7 +10,6 @@
#include "Parser/Expression/ExpressionIfElse.h"
#include "Parser/Expression/ExpressionBinary.h"
#include "Parser/Expression/ExpressionBlock.h"
#include "Parser/Expression/ExpressionInvalid.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementVariable.h"
@@ -17,7 +19,6 @@
#include "Parser/Statement/StatementMetaExternFunction.h"
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementRepeat.h"
#include "Parser/Statement/StatementInvalid.h"
Parser::Parser(vector<shared_ptr<Token>> tokens): tokens(tokens) {
}
@@ -27,20 +28,21 @@ vector<shared_ptr<Statement>> Parser::getStatements() {
while (!tryMatchingTokenKinds({TokenKind::END}, true, false)) {
shared_ptr<Statement> statement = nextStatement();
// Abort parsing if we got an error
if (!statement->isValid()) {
cerr << statement->toString(0);
exit(1);
}
statements.push_back(statement);
if (statement != nullptr) {
statements.push_back(statement);
// Expect new line after statement
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
cerr << "Expected new line" << endl;
exit(1);
// Expect new line after statement
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
markError(TokenKind::NEW_LINE, {});
}
}
if (!errors.empty()) {
for (shared_ptr<Error> &error : errors)
Logger::print(error);
exit(1);
}
return statements;
}
@@ -48,47 +50,51 @@ vector<shared_ptr<Statement>> Parser::getStatements() {
// Statement
//
shared_ptr<Statement> Parser::nextStatement() {
shared_ptr<Statement> statement;
shared_ptr<Statement> statement;
int errorsCount = errors.size();
statement = matchStatementFunction();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementVariable();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementMetaExternFunction();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
return matchStatementInvalid("Unexpected token");
markError({}, {});
return nullptr;
}
shared_ptr<Statement> Parser::nextInBlockStatement() {
shared_ptr<Statement> statement;
int errorsCount = errors.size();
statement = matchStatementVariable();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementAssignment();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementReturn();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementRepeat();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementExpression();
if (statement != nullptr)
if (statement != nullptr || errors.size() > errorsCount)
return statement;
return matchStatementInvalid("Unexpected token");
markError({}, {});
return nullptr;
}
shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
@@ -107,13 +113,17 @@ shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false))
return matchStatementInvalid("Expected function argument");
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false)) {
markError({}, "Expected function argument");
return nullptr;
}
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Token> typeToken = tokens.at(currentIndex++);
optional<ValueType> argumentType = valueTypeForToken(typeToken);
if (!argumentType)
return matchStatementInvalid("Invalid argument type");
if (!argumentType) {
markError(TokenKind::TYPE, {});
return nullptr;
}
arguments.push_back(pair<string, ValueType>(identifierToken->getLexme(), *argumentType));
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
@@ -125,8 +135,10 @@ shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
shared_ptr<Token> typeToken = tokens.at(currentIndex);
optional<ValueType> type = valueTypeForToken(typeToken);
if (!type)
return matchStatementInvalid("Expected return type");
if (!type) {
markError(TokenKind::TYPE, {});
return nullptr;
}
returnType = *type;
currentIndex++; // type
@@ -149,18 +161,22 @@ shared_ptr<Statement> Parser::matchStatementVariable() {
valueType = ValueType::SINT32;
else if (valueTypeToken->getLexme().compare("real32") == 0)
valueType = ValueType::REAL32;
else
return matchStatementInvalid("Invalid type");
else {
markError(TokenKind::TYPE, {});
return nullptr;
}
currentIndex++; // type
// Expect left arrow
if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true))
return matchStatementInvalid("Expected left arrow");
if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true)) {
markError(TokenKind::LEFT_ARROW, {});
return nullptr;
}
shared_ptr<Expression> expression = nextExpression();
if (expression == nullptr || !expression->isValid())
return matchStatementInvalid("Invalid expression");
if (expression == nullptr)
return nullptr;
return make_shared<StatementVariable>(identifierToken->getLexme(), valueType, expression);
}
@@ -182,13 +198,17 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false))
return matchStatementInvalid("Expected function argument");
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false)) {
markError({}, "Expected function argument");
return nullptr;
}
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Token> typeToken = tokens.at(currentIndex++);
optional<ValueType> argumentType = valueTypeForToken(typeToken);
if (!argumentType)
return matchStatementInvalid("Invalid argument type");
if (!argumentType) {
markError(TokenKind::TYPE, {});
return nullptr;
}
arguments.push_back(pair<string, ValueType>(identifierToken->getLexme(), *argumentType));
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
@@ -200,24 +220,30 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
shared_ptr<Token> typeToken = tokens.at(currentIndex);
optional<ValueType> type = valueTypeForToken(typeToken);
if (!type)
return matchStatementInvalid("Expected return type");
if (!type) {
markError(TokenKind::TYPE, {});
return nullptr;
}
returnType = *type;
currentIndex++; // type
}
// consume new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line after function declaration");
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
markError(TokenKind::NEW_LINE, {});
return nullptr;
}
// block
statementBlock = matchStatementBlock({TokenKind::SEMICOLON});
if (statementBlock == nullptr || !statementBlock->isValid())
return statementBlock ?: matchStatementInvalid();
if (statementBlock == nullptr)
return nullptr;
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true))
return matchStatementInvalid("Expected a \";\" after a function declaration");
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) {
markError(TokenKind::SEMICOLON, {});
return nullptr;
}
return make_shared<StatementFunction>(name, arguments, returnType, dynamic_pointer_cast<StatementBlock>(statementBlock));
}
@@ -227,16 +253,17 @@ shared_ptr<Statement> Parser::matchStatementBlock(vector<TokenKind> terminalToke
while (!tryMatchingTokenKinds(terminalTokenKinds, false, false)) {
shared_ptr<Statement> statement = nextInBlockStatement();
if (statement == nullptr || !statement->isValid())
return statement ?: matchStatementInvalid("Expected statement");
statements.push_back(statement);
if (statement != nullptr)
statements.push_back(statement);
if (tryMatchingTokenKinds(terminalTokenKinds, false, false))
break;
// except new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
return matchStatementInvalid("Expected new line");
if (statement != nullptr && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
markError(TokenKind::NEW_LINE, {});
return nullptr;
}
}
return make_shared<StatementBlock>(statements);
@@ -250,8 +277,8 @@ shared_ptr<Statement> Parser::matchStatementAssignment() {
currentIndex++; // arrow
shared_ptr<Expression> expression = nextExpression();
if (expression == nullptr || !expression->isValid())
return matchStatementInvalid("Expected expression");
if (expression == nullptr)
return nullptr;
return make_shared<StatementAssignment>(identifierToken->getLexme(), expression);
}
@@ -261,8 +288,8 @@ shared_ptr<Statement> Parser::matchStatementReturn() {
return nullptr;
shared_ptr<Expression> expression = nextExpression();
if (expression != nullptr && !expression->isValid())
return matchStatementInvalid("Expected expression");
if (expression == nullptr)
return nullptr;
return make_shared<StatementReturn>(expression);
}
@@ -280,38 +307,38 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// initial
initStatement = matchStatementVariable() ?: matchStatementAssignment();
if (initStatement != nullptr && !initStatement->isValid())
initStatement = nullptr;
if (!tryMatchingTokenKinds({TokenKind::COLON}, false, true)) {
// got initial, expect comma
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
return matchStatementInvalid("Expected comma after initial statement");
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {});
return nullptr;
}
// optional new line
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
// pre condition
preConditionExpression = nextExpression();
if (preConditionExpression != nullptr && !preConditionExpression->isValid())
return matchStatementInvalid("Expected pre-condition expression");
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
// got pre-condition, expect comma
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true))
return matchStatementInvalid("Expected comma after pre-condition statement");
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {});
return nullptr;
}
// optional new line
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
// post condition
postConditionExpression = nextExpression();
if (postConditionExpression == nullptr || !postConditionExpression->isValid())
return matchStatementInvalid("Expected post-condition expression");
// expect colon
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true))
return matchStatementInvalid("Expected \":\"");
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
markError(TokenKind::COLON, {});
return nullptr;
}
}
}
@@ -323,8 +350,8 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
else
bodyBlockStatement = matchStatementBlock({TokenKind::NEW_LINE});
if (bodyBlockStatement == nullptr || !bodyBlockStatement->isValid())
return bodyBlockStatement ?: matchStatementInvalid("Expected block statement");
if (bodyBlockStatement == nullptr)
return nullptr;
tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true);
@@ -336,46 +363,39 @@ shared_ptr<Statement> Parser::matchStatementExpression() {
if (expression == nullptr)
return nullptr;
else if (!expression->isValid())
return make_shared<StatementInvalid>(tokens.at(currentIndex), expression->toString(0));
// Consume new line
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
return make_shared<StatementExpression>(expression);
}
shared_ptr<StatementInvalid> Parser::matchStatementInvalid(string message) {
return make_shared<StatementInvalid>(tokens.at(currentIndex), message);
}
//
// Expression
//
shared_ptr<Expression> Parser::nextExpression() {
shared_ptr<Expression> expression;
int errorsCount = errors.size();
expression = matchEquality();
if (expression != nullptr)
if (expression != nullptr || errors.size() > errorsCount)
return expression;
expression = matchExpressionIfElse();
if (expression != nullptr)
if (expression != nullptr || errors.size() > errorsCount)
return expression;
expression = matchExpressionVariable();
if (expression != nullptr)
if (expression != nullptr || errors.size() > errorsCount)
return expression;
markError({}, {});
return nullptr;
}
shared_ptr<Expression> Parser::matchEquality() {
shared_ptr<Expression> expression = matchComparison();
if (expression == nullptr || !expression->isValid())
return expression;
if (expression == nullptr)
return nullptr;
while (tryMatchingTokenKinds({Token::tokensEquality}, false, false))
if (tryMatchingTokenKinds({Token::tokensEquality}, false, false))
expression = matchExpressionBinary(expression);
return expression;
@@ -383,10 +403,10 @@ shared_ptr<Expression> Parser::matchEquality() {
shared_ptr<Expression> Parser::matchComparison() {
shared_ptr<Expression> expression = matchTerm();
if (expression == nullptr || !expression->isValid())
return expression;
if (expression == nullptr)
return nullptr;
while (tryMatchingTokenKinds({Token::tokensComparison}, false, false))
if (tryMatchingTokenKinds({Token::tokensComparison}, false, false))
expression = matchExpressionBinary(expression);
return expression;
@@ -394,10 +414,10 @@ shared_ptr<Expression> Parser::matchComparison() {
shared_ptr<Expression> Parser::matchTerm() {
shared_ptr<Expression> expression = matchFactor();
if (expression == nullptr || !expression->isValid())
return expression;
if (expression == nullptr)
return nullptr;
while (tryMatchingTokenKinds({Token::tokensTerm}, false, false))
if (tryMatchingTokenKinds({Token::tokensTerm}, false, false))
expression = matchExpressionBinary(expression);
return expression;
@@ -405,10 +425,10 @@ shared_ptr<Expression> Parser::matchTerm() {
shared_ptr<Expression> Parser::matchFactor() {
shared_ptr<Expression> expression = matchPrimary();
if (expression == nullptr || !expression->isValid())
return expression;
if (expression == nullptr)
return nullptr;
while (tokens.at(currentIndex)->isOfKind(Token::tokensFactor))
if (tokens.at(currentIndex)->isOfKind(Token::tokensFactor))
expression = matchExpressionBinary(expression);
return expression;
@@ -441,12 +461,12 @@ shared_ptr<Expression> Parser::matchExpressionGrouping() {
if (tryMatchingTokenKinds({TokenKind::LEFT_PAREN}, true, true)) {
shared_ptr<Expression> expression = matchTerm();
// has grouped expression failed?
if (expression == nullptr || !expression->isValid()) {
return expression ?: matchExpressionInvalid("Expected expression");
if (expression == nullptr) {
return nullptr;
} else if (tryMatchingTokenKinds({TokenKind::RIGHT_PAREN}, true, true)) {
return make_shared<ExpressionGrouping>(expression);
} else {
return matchExpressionInvalid("Unexpected token");
markError(TokenKind::RIGHT_PAREN, {});
}
}
@@ -484,14 +504,16 @@ shared_ptr<Expression> Parser::matchExpressionCall() {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // optional new line
shared_ptr<Expression> argumentExpression = nextExpression();
if (argumentExpression == nullptr || !argumentExpression->isValid())
return argumentExpression;
if (argumentExpression == nullptr)
return nullptr;
argumentExpressions.push_back(argumentExpression);
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // optional new line
if (!tryMatchingTokenKinds({TokenKind::RIGHT_PAREN}, true, true))
return matchExpressionInvalid("Expected \")\"");
if (!tryMatchingTokenKinds({TokenKind::RIGHT_PAREN}, true, true)) {
markError(TokenKind::RIGHT_PAREN, {});
return nullptr;
}
return make_shared<ExpressionCall>(identifierToken->getLexme(), argumentExpressions);
}
@@ -506,30 +528,29 @@ shared_ptr<Expression> Parser::matchExpressionIfElse() {
// condition expression
condition = nextExpression();
if (condition == nullptr || !condition->isValid())
return condition ?: matchExpressionInvalid("Expected condition expression");
if (condition == nullptr)
return nullptr;
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true))
return matchExpressionInvalid("Expected \":\"");
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
markError(TokenKind::COLON, {});
return nullptr;
}
// then
bool isMultiLine = false;
if (tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
isMultiLine = true;
bool isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
// then block
if (isMultiLine)
thenBlock = matchExpressionBlock({TokenKind::ELSE, TokenKind::SEMICOLON});
else
thenBlock = matchExpressionBlock({TokenKind::ELSE, TokenKind::NEW_LINE});
if (thenBlock == nullptr || !thenBlock->isValid())
return thenBlock ?: matchExpressionInvalid("Expected then block");
if (thenBlock == nullptr)
return nullptr;
// else
if (tryMatchingTokenKinds({TokenKind::ELSE}, true, true)) {
if (tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
isMultiLine = true;
isMultiLine = (tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true));
// else block
if (isMultiLine)
@@ -537,8 +558,8 @@ shared_ptr<Expression> Parser::matchExpressionIfElse() {
else
elseBlock = matchExpressionBlock({TokenKind::NEW_LINE});
if (elseBlock == nullptr || !elseBlock->isValid())
return elseBlock ?: matchExpressionInvalid("Expected else block");
if (elseBlock == nullptr)
return nullptr;
}
tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true);
@@ -560,9 +581,7 @@ shared_ptr<Expression> Parser::matchExpressionBinary(shared_ptr<Expression> left
}
if (right == nullptr) {
return matchExpressionInvalid("Expected right-side expression");
} else if (!right->isValid()) {
return right;
return nullptr;
} else {
return make_shared<ExpressionBinary>(token, left, right);
}
@@ -575,18 +594,23 @@ shared_ptr<Expression> Parser::matchExpressionBlock(vector<TokenKind> terminalTo
while (!tryMatchingTokenKinds(terminalTokenKinds, false, false)) {
shared_ptr<Statement> statement = nextInBlockStatement();
if (statement == nullptr || !statement->isValid())
return matchExpressionInvalid("Expected statement");
statements.push_back(statement);
if (statement != nullptr)
statements.push_back(statement);
if (tryMatchingTokenKinds(terminalTokenKinds, false, false))
break;
// except new line
if (statement != nullptr && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
markError(TokenKind::NEW_LINE, {});
return nullptr;
}
}
return make_shared<ExpressionBlock>(statements);
}
shared_ptr<ExpressionInvalid> Parser::matchExpressionInvalid(string message) {
return make_shared<ExpressionInvalid>(tokens.at(currentIndex));
}
bool Parser::tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance) {
int requiredCount = shouldMatchAll ? kinds.size() : 1;
if (currentIndex + requiredCount > tokens.size())
@@ -628,3 +652,19 @@ optional<ValueType> Parser::valueTypeForToken(shared_ptr<Token> token) {
return {};
}
void Parser::markError(optional<TokenKind> expectedTokenKind, optional<string> message) {
shared_ptr<Token> actualToken = tokens.at(currentIndex);
// Try reaching the next safe token
vector<TokenKind> safeKinds = {TokenKind::END};
if (!actualToken->isOfKind({TokenKind::NEW_LINE}))
safeKinds.push_back(TokenKind::NEW_LINE);
if (!actualToken->isOfKind({TokenKind::SEMICOLON}))
safeKinds.push_back(TokenKind::SEMICOLON);
while (!tryMatchingTokenKinds(safeKinds, false, true))
currentIndex++;
errors.push_back(make_shared<Error>(actualToken, expectedTokenKind, message));
}

View File

@@ -2,14 +2,14 @@
#define PARSER_H
#include <vector>
#include "Types.h"
#include "Lexer/Token.h"
class Token;
enum class TokenKind;
class Error;
class Expression;
class ExpressionInvalid;
class Statement;
class StatementInvalid;
using namespace std;
@@ -17,6 +17,7 @@ class Parser {
private:
vector<shared_ptr<Token>> tokens;
int currentIndex = 0;
vector<shared_ptr<Error>> errors;
shared_ptr<Statement> nextStatement();
shared_ptr<Statement> nextInBlockStatement();
@@ -30,7 +31,6 @@ private:
shared_ptr<Statement> matchStatementReturn();
shared_ptr<Statement> matchStatementRepeat();
shared_ptr<Statement> matchStatementExpression();
shared_ptr<StatementInvalid> matchStatementInvalid(string message = "");
shared_ptr<Expression> nextExpression();
shared_ptr<Expression> matchEquality(); // =, !=
@@ -46,11 +46,12 @@ private:
shared_ptr<Expression> matchExpressionIfElse();
shared_ptr<Expression> matchExpressionBinary(shared_ptr<Expression> left);
shared_ptr<Expression> matchExpressionBlock(vector<TokenKind> terminalTokenKinds);
shared_ptr<ExpressionInvalid> matchExpressionInvalid(string message);
bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance);
optional<ValueType> valueTypeForToken(shared_ptr<Token> token);
void markError(optional<TokenKind> expectedTokenKind, optional<string> message);
public:
Parser(vector<shared_ptr<Token>> tokens);
vector<shared_ptr<Statement>> getStatements();

View File

@@ -6,11 +6,3 @@ kind(kind) { }
StatementKind Statement::getKind() {
return kind;
}
bool Statement::isValid() {
return kind != StatementKind::INVALID;
}
string Statement::toString(int indent) {
return "STATEMENT";
}

View File

@@ -15,8 +15,7 @@ enum class StatementKind {
VARIABLE,
ASSIGNMENT,
REPEAT,
META_EXTERN_FUNCTION,
INVALID
META_EXTERN_FUNCTION
};
class Statement {
@@ -25,9 +24,8 @@ private:
public:
Statement(StatementKind kind);
virtual ~Statement() { }
StatementKind getKind();
bool isValid();
virtual string toString(int indent);
};
#endif

View File

@@ -8,16 +8,3 @@ Statement(StatementKind::BLOCK), statements(statements) { }
vector<shared_ptr<Statement>> StatementBlock::getStatements() {
return statements;
}
string StatementBlock::toString(int indent) {
string value;
for (int i=0; i<statements.size(); i++) {
//for (int ind=0; ind<indent; ind++)
// value += " ";
value += statements.at(i)->toString(indent);
}
for (int ind=0; ind<indent; ind++)
value += " ";
value += "#\n";
return value;
}

View File

@@ -9,5 +9,4 @@ private:
public:
StatementBlock(vector<shared_ptr<Statement>> statements);
vector<shared_ptr<Statement>> getStatements();
string toString(int indent) override;
};

View File

@@ -8,12 +8,3 @@ Statement(StatementKind::EXPRESSION), expression(expression) { }
shared_ptr<Expression> StatementExpression::getExpression() {
return expression;
}
string StatementExpression::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += expression->toString(indent);
value += "\n";
return value;
}

View File

@@ -9,5 +9,4 @@ private:
public:
StatementExpression(shared_ptr<Expression> expression);
shared_ptr<Expression> getExpression();
string toString(int indent) override;
};

View File

@@ -43,17 +43,3 @@ ValueType StatementFunction::getReturnValueType() {
shared_ptr<StatementBlock> StatementFunction::getStatementBlock() {
return statementBlock;
}
string StatementFunction::toString(int indent) {
string value = "";
for (int ind=0; ind<indent; ind++)
value += " ";
value += "FUNCTION(";
value += valueTypeToString(returnValueType);
value += ", " + name + "):\n";
value += statementBlock->toString(indent+1);
for (int ind=0; ind<indent; ind++)
value += " ";
value += ";";
return value;
}

View File

@@ -15,5 +15,4 @@ public:
vector<pair<string, ValueType>> getArguments();
ValueType getReturnValueType();
shared_ptr<StatementBlock> getStatementBlock();
string toString(int indent) override;
};

View File

@@ -1,14 +0,0 @@
#include "Parser/Statement/StatementInvalid.h"
#include "Lexer/Token.h"
StatementInvalid::StatementInvalid(shared_ptr<Token> token, string message):
Statement(StatementKind::INVALID), token(token), message(message) { }
string StatementInvalid::toString(int indent) {
return "Error for token " + token->toString() + " at " + to_string(token->getLine()) + ":" + to_string(token->getColumn()) + ": " + message + "\n";
}
string StatementInvalid::getMessage() {
return message;
}

View File

@@ -1,14 +0,0 @@
#include "Parser/Statement/Statement.h"
class Token;
class StatementInvalid: public Statement {
private:
shared_ptr<Token> token;
string message;
public:
StatementInvalid(shared_ptr<Token> token, string message);
string toString(int indent) override;
string getMessage();
};

View File

@@ -27,14 +27,3 @@ vector<pair<string, ValueType>> StatementMetaExternFunction::getArguments() {
ValueType StatementMetaExternFunction::getReturnValueType() {
return returnValueType;
}
string StatementMetaExternFunction::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += "EXTERN_FUN(";
value += name + ", ";
value += valueTypeToString(returnValueType);
value += ")\n";
return value;
}

View File

@@ -11,5 +11,4 @@ public:
string getName();
vector<pair<string, ValueType>> getArguments();
ValueType getReturnValueType();
string toString(int indent) override;
};

View File

@@ -21,19 +21,3 @@ shared_ptr<Expression> StatementRepeat::getPostConditionExpression() {
shared_ptr<StatementBlock> StatementRepeat::getBodyBlockStatement() {
return bodyBlockStatement;
}
string StatementRepeat::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += "REP(";
if (initStatement != nullptr)
value += initStatement->toString(0), ", ";
if (preConditionExpression != nullptr)
value += preConditionExpression->toString(0) + ", ";
if (postConditionExpression != nullptr)
value += postConditionExpression->toString(0);
value += "):\n";
value += bodyBlockStatement->toString(indent+1);
return value;
}

View File

@@ -16,5 +16,4 @@ public:
shared_ptr<Expression> getPreConditionExpression();
shared_ptr<Expression> getPostConditionExpression();
shared_ptr<StatementBlock> getBodyBlockStatement();
string toString(int indent) override;
};

View File

@@ -8,18 +8,3 @@ Statement(StatementKind::RETURN), expression(expression) { }
shared_ptr<Expression> StatementReturn::getExpression() {
return expression;
}
string StatementReturn::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += "RETURN";
if (expression != nullptr) {
value += ":\n";
for (int ind=0; ind<indent+1; ind++)
value += " ";
value += expression->toString(indent+1);
}
value += "\n";
return value;
}

View File

@@ -9,5 +9,4 @@ private:
public:
StatementReturn(shared_ptr<Expression> expression);
shared_ptr<Expression> getExpression();
string toString(int indent) override;
};

View File

@@ -29,17 +29,3 @@ ValueType StatementVariable::getValueType() {
shared_ptr<Expression> StatementVariable::getExpression() {
return expression;
}
string StatementVariable::toString(int indent) {
string value;
for (int ind=0; ind<indent; ind++)
value += " ";
value += name + "(";
value += valueTypeToString(valueType);
value += "):\n";
for (int ind=0; ind<indent+1; ind++)
value += " ";
value += expression->toString(indent+1);
value += "\n";
return value;
}

View File

@@ -13,5 +13,4 @@ public:
string getName();
ValueType getValueType();
shared_ptr<Expression> getExpression();
string toString(int indent) override;
};

View File

@@ -13,6 +13,7 @@
#include "Compiler/ModuleBuilder.h"
#include "Compiler/CodeGenerator.h"
#include "Logger.h"
using namespace std;
@@ -56,22 +57,15 @@ int main(int argc, char **argv) {
Lexer lexer(source);
vector<shared_ptr<Token>> tokens = lexer.getTokens();
if (isVerbose) {
for (int i=0; i<tokens.size(); i++) {
cout << i << "|" << tokens.at(i)->toString();
if (i < tokens.size() - 1)
cout << ", ";
}
cout << endl << endl;
Logger::print(tokens);
cout << endl;
}
Parser parser(tokens);
vector<shared_ptr<Statement>> statements = parser.getStatements();
if (isVerbose) {
for (shared_ptr<Statement> &statement : statements) {
cout << statement->toString(0);
cout << endl;
}
cout << endl << endl;
Logger::print(statements);
cout << endl;
}
ModuleBuilder moduleBuilder(moduleName, inputFilePath, statements);

View File

@@ -1,7 +0,0 @@
//dummy sint32 <- 55
stuff fun: num1 sint32, num2 sint32 -> sint32
rep:
i <- i + 1
;
ret 42
;