2
.gitignore
vendored
2
.gitignore
vendored
@@ -3,5 +3,5 @@
|
||||
brb
|
||||
.vscode/settings.json
|
||||
*.dSYM
|
||||
#*.brc
|
||||
*.brc
|
||||
build/
|
||||
35
src/Error.cpp
Normal file
35
src/Error.cpp
Normal 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
43
src/Error.h
Normal 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
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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
437
src/Logger.cpp
Normal 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
65
src/Logger.h
Normal 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
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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) + "}";
|
||||
}
|
||||
}
|
||||
@@ -26,5 +26,4 @@ public:
|
||||
ExpressionBinaryOperation getOperation();
|
||||
shared_ptr<Expression> getLeft();
|
||||
shared_ptr<Expression> getRight();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -13,5 +13,4 @@ public:
|
||||
ExpressionBlock(vector<shared_ptr<Statement>> statements);
|
||||
shared_ptr<StatementBlock> getStatementBlock();
|
||||
shared_ptr<StatementExpression> getResultStatementExpression();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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) + " )";
|
||||
}
|
||||
|
||||
@@ -7,5 +7,4 @@ private:
|
||||
public:
|
||||
ExpressionGrouping(shared_ptr<Expression> expression);
|
||||
shared_ptr<Expression> getExpression();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -13,5 +13,4 @@ public:
|
||||
shared_ptr<Expression> getCondition();
|
||||
shared_ptr<ExpressionBlock> getThenBlock();
|
||||
shared_ptr<ExpressionBlock> getElseBlock();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
@@ -6,7 +6,3 @@ Expression(ExpressionKind::VAR, ValueType::NONE), name(name) { }
|
||||
string ExpressionVariable::getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
string ExpressionVariable::toString(int indent) {
|
||||
return "VAR(" + name + ")";
|
||||
}
|
||||
@@ -7,5 +7,4 @@ private:
|
||||
public:
|
||||
ExpressionVariable(string name);
|
||||
string getName();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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";
|
||||
}
|
||||
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -9,5 +9,4 @@ private:
|
||||
public:
|
||||
StatementBlock(vector<shared_ptr<Statement>> statements);
|
||||
vector<shared_ptr<Statement>> getStatements();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -9,5 +9,4 @@ private:
|
||||
public:
|
||||
StatementExpression(shared_ptr<Expression> expression);
|
||||
shared_ptr<Expression> getExpression();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -15,5 +15,4 @@ public:
|
||||
vector<pair<string, ValueType>> getArguments();
|
||||
ValueType getReturnValueType();
|
||||
shared_ptr<StatementBlock> getStatementBlock();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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();
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -11,5 +11,4 @@ public:
|
||||
string getName();
|
||||
vector<pair<string, ValueType>> getArguments();
|
||||
ValueType getReturnValueType();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -16,5 +16,4 @@ public:
|
||||
shared_ptr<Expression> getPreConditionExpression();
|
||||
shared_ptr<Expression> getPostConditionExpression();
|
||||
shared_ptr<StatementBlock> getBodyBlockStatement();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -9,5 +9,4 @@ private:
|
||||
public:
|
||||
StatementReturn(shared_ptr<Expression> expression);
|
||||
shared_ptr<Expression> getExpression();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
@@ -13,5 +13,4 @@ public:
|
||||
string getName();
|
||||
ValueType getValueType();
|
||||
shared_ptr<Expression> getExpression();
|
||||
string toString(int indent) override;
|
||||
};
|
||||
16
src/main.cpp
16
src/main.cpp
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user