Merge pull request #25 from rafalgrodzinski/22-support-arrays

Support arrays
This commit is contained in:
Rafał
2025-07-10 14:39:26 +09:00
committed by GitHub
27 changed files with 564 additions and 141 deletions

7
.gitignore vendored
View File

@@ -1,6 +1,9 @@
.DS_Store .DS_Store
*.o
brb
.vscode/settings.json .vscode/settings.json
# project build artifacts
*.dSYM *.dSYM
build/ build/
# brb build artifiacts
*.o

2
.vscode/launch.json vendored
View File

@@ -6,7 +6,7 @@
"type": "lldb-dap", "type": "lldb-dap",
"request": "launch", "request": "launch",
"program": "${command:cmake.launchTargetPath}", "program": "${command:cmake.launchTargetPath}",
"args": ["-v", "${workspaceFolder}/test.brc"], "args": ["-v", "${workspaceFolder}/samples/hello.brc"],
"cwd": "${workspaceFolder}", "cwd": "${workspaceFolder}",
"internalConsoleOptions": "openOnSessionStart", "internalConsoleOptions": "openOnSessionStart",
} }

12
samples/hello.brc Normal file
View File

@@ -0,0 +1,12 @@
@extern putchar fun: character sint32 -> sint32
main fun -> sint32
text data<sint32> <- "Hello, world!\n"
rep i sint32 <- 0, text[i] != 0:
putchar(text[i])
i <- i + 1
;
ret 0
;

25
samples/test.brc Normal file
View File

@@ -0,0 +1,25 @@
@extern putchar fun: character sint32 -> sint32
/*
User type
name data<u8, 32>
age u32
successRatio r32
isActive bool
;
*/
/*
i u32 <- 0, rep text[i] != 0:
putchar(text[i])
i++
;
*/
// text data<u8> <- "Hello world!"
main fun -> sint32
text data<sint32> <- "Hello string!\n"
ret 0
;

View File

@@ -6,6 +6,7 @@
#include "Parser/Expression/ExpressionGrouping.h" #include "Parser/Expression/ExpressionGrouping.h"
#include "Parser/Expression/ExpressionLiteral.h" #include "Parser/Expression/ExpressionLiteral.h"
#include "Parser/Expression/ExpressionArrayLiteral.h"
#include "Parser/Expression/ExpressionVariable.h" #include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionCall.h" #include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionIfElse.h" #include "Parser/Expression/ExpressionIfElse.h"
@@ -126,13 +127,31 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> state
} }
void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement) { void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement) {
if (statement->getValueType()->getKind() == ValueTypeKind::DATA) {
vector<llvm::Value *> values = valuesForExpression(statement->getExpression());
llvm::ArrayType *type = (llvm::ArrayType *)typeForValueType(statement->getValueType(), values.size());
llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, statement->getName());
if (!setAlloca(statement->getName(), alloca))
return;
for (int i=0; i < type->getNumElements(); i++) {
llvm::Value *index[] = {
builder->getInt32(0),
builder->getInt32(i)
};
llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}_{}", statement->getName(), i));
builder->CreateStore(values[i], elementPtr);
}
} else {
llvm::Value *value = valueForExpression(statement->getExpression()); llvm::Value *value = valueForExpression(statement->getExpression());
llvm::AllocaInst *alloca = builder->CreateAlloca(typeForValueType(statement->getValueType()), nullptr, statement->getName()); llvm::AllocaInst *alloca = builder->CreateAlloca(typeForValueType(statement->getValueType(), 0), nullptr, statement->getName());
if (!setAlloca(statement->getName(), alloca)) if (!setAlloca(statement->getName(), alloca))
return; return;
builder->CreateStore(value, alloca); builder->CreateStore(value, alloca);
} }
}
void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) { void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) {
llvm::AllocaInst *alloca = getAlloca(statement->getName()); llvm::AllocaInst *alloca = getAlloca(statement->getName());
@@ -140,8 +159,21 @@ void ModuleBuilder::buildAssignment(shared_ptr<StatementAssignment> statement) {
return; return;
llvm::Value *value = valueForExpression(statement->getExpression()); llvm::Value *value = valueForExpression(statement->getExpression());
if (statement->getIndexExpression()) {
llvm::Value *indexValue = valueForExpression(statement->getIndexExpression());
llvm::Value *index[] = {
builder->getInt32(0),
indexValue
};
llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType();
llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", statement->getName()));
builder->CreateStore(value, elementPtr);
} else {
builder->CreateStore(value, alloca); builder->CreateStore(value, alloca);
} }
}
void ModuleBuilder::buildBlock(shared_ptr<StatementBlock> statement) { void ModuleBuilder::buildBlock(shared_ptr<StatementBlock> statement) {
for (shared_ptr<Statement> &innerStatement : statement->getStatements()) for (shared_ptr<Statement> &innerStatement : statement->getStatements())
@@ -250,6 +282,16 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr<Expression> expression
} }
} }
vector<llvm::Value*> ModuleBuilder::valuesForExpression(shared_ptr<Expression> expression) {
switch (expression->getKind()) {
case ExpressionKind::ARRAY_LITERAL:
return valuesForArrayLiteral(dynamic_pointer_cast<ExpressionArrayLiteral>(expression));
default:
markError(0, 0, "Unexpected expression");
return vector<llvm::Value*>();
}
}
llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expression) { llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expression) {
if (expression->getValueType() == nullptr) if (expression->getValueType() == nullptr)
return llvm::UndefValue::get(typeVoid); return llvm::UndefValue::get(typeVoid);
@@ -266,6 +308,14 @@ llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expres
} }
} }
vector<llvm::Value*> ModuleBuilder::valuesForArrayLiteral(shared_ptr<ExpressionArrayLiteral> expression) {
vector<llvm::Value*> values;
for (shared_ptr<Expression> &expression : expression->getExpressions()) {
values.push_back(valueForExpression(expression));
}
return values;
}
llvm::Value *ModuleBuilder::valueForGrouping(shared_ptr<ExpressionGrouping> expression) { llvm::Value *ModuleBuilder::valueForGrouping(shared_ptr<ExpressionGrouping> expression) {
return valueForExpression(expression->getExpression()); return valueForExpression(expression->getExpression());
} }
@@ -274,6 +324,9 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr<ExpressionBinary> expressi
llvm::Value *leftValue = valueForExpression(expression->getLeft()); llvm::Value *leftValue = valueForExpression(expression->getLeft());
llvm::Value *rightValue = valueForExpression(expression->getRight()); llvm::Value *rightValue = valueForExpression(expression->getRight());
if (leftValue == nullptr || rightValue == nullptr)
return nullptr;
llvm::Type *type = leftValue->getType(); llvm::Type *type = leftValue->getType();
if (type == typeBool) { if (type == typeBool) {
@@ -411,8 +464,20 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVariable> expressio
if (alloca == nullptr) if (alloca == nullptr)
return nullptr; return nullptr;
if (expression->getIndexExpression()) {
llvm::Value *indexValue = valueForExpression(expression->getIndexExpression());
llvm::Value *index[] = {
builder->getInt32(0),
indexValue
};
llvm::ArrayType *type = (llvm::ArrayType *)alloca->getAllocatedType();
llvm::Value *elementPtr = builder->CreateGEP(type, alloca, index, format("{}[]", expression->getName()));
return builder->CreateLoad(type->getArrayElementType(), elementPtr);
} else {
return builder->CreateLoad(alloca->getAllocatedType(), alloca, expression->getName()); return builder->CreateLoad(alloca->getAllocatedType(), alloca, expression->getName());
} }
}
llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) { llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) {
llvm::Function *fun = getFun(expression->getName()); llvm::Function *fun = getFun(expression->getName());
@@ -475,7 +540,7 @@ llvm::Function* ModuleBuilder::getFun(string name) {
return nullptr; return nullptr;
} }
llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType) { llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int count) {
switch (valueType->getKind()) { switch (valueType->getKind()) {
case ValueTypeKind::NONE: case ValueTypeKind::NONE:
return typeVoid; return typeVoid;
@@ -485,6 +550,14 @@ llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType) {
return typeSint32; return typeSint32;
case ValueTypeKind::REAL32: case ValueTypeKind::REAL32:
return typeReal32; return typeReal32;
case ValueTypeKind::DATA: {
if (valueType->getSubType() == nullptr)
return nullptr;
if (valueType->getValueArg() > 0)
count = valueType->getValueArg();
return llvm::ArrayType::get(typeForValueType(valueType->getSubType(), count), count);
return nullptr;
}
} }
} }

View File

@@ -17,6 +17,7 @@ class ValueType;
class Expression; class Expression;
class ExpressionGrouping; class ExpressionGrouping;
class ExpressionLiteral; class ExpressionLiteral;
class ExpressionArrayLiteral;
class ExpressionVariable; class ExpressionVariable;
class ExpressionCall; class ExpressionCall;
class ExpressionIfElse; class ExpressionIfElse;
@@ -69,7 +70,9 @@ private:
void buildExpression(shared_ptr<StatementExpression> statement); void buildExpression(shared_ptr<StatementExpression> statement);
llvm::Value *valueForExpression(shared_ptr<Expression> expression); llvm::Value *valueForExpression(shared_ptr<Expression> expression);
vector<llvm::Value*> valuesForExpression(shared_ptr<Expression> expression);
llvm::Value *valueForLiteral(shared_ptr<ExpressionLiteral> expression); llvm::Value *valueForLiteral(shared_ptr<ExpressionLiteral> expression);
vector<llvm::Value*> valuesForArrayLiteral(shared_ptr<ExpressionArrayLiteral> expression);
llvm::Value *valueForGrouping(shared_ptr<ExpressionGrouping> expression); llvm::Value *valueForGrouping(shared_ptr<ExpressionGrouping> expression);
llvm::Value *valueForBinary(shared_ptr<ExpressionBinary> expression); llvm::Value *valueForBinary(shared_ptr<ExpressionBinary> expression);
llvm::Value *valueForBinaryBool(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue); llvm::Value *valueForBinaryBool(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
@@ -85,7 +88,7 @@ private:
bool setFun(string name, llvm::Function *fun); bool setFun(string name, llvm::Function *fun);
llvm::Function *getFun(string name); llvm::Function *getFun(string name);
llvm::Type *typeForValueType(shared_ptr<ValueType> valueType); llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0);
void markError(int line, int column, string message); void markError(int line, int column, string message);

View File

@@ -13,9 +13,9 @@ vector<shared_ptr<Token>> Lexer::getTokens() {
currentLine = 0; currentLine = 0;
currentColumn = 0; currentColumn = 0;
tokens.clear();
errors.clear(); errors.clear();
vector<shared_ptr<Token>> tokens;
shared_ptr<Token> token; shared_ptr<Token> token;
do { do {
token = nextToken(); token = nextToken();
@@ -126,6 +126,14 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr) if (token != nullptr)
return token; return token;
token = match(TokenKind::LEFT_SQUARE_BRACKET, "[", false);
if (token != nullptr)
return token;
token = match(TokenKind::RIGHT_SQUARE_BRACKET, "]", false);
if (token != nullptr)
return token;
token = match(TokenKind::COMMA, ",", false); token = match(TokenKind::COMMA, ",", false);
if (token != nullptr) if (token != nullptr)
return token; return token;
@@ -242,16 +250,12 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr) if (token != nullptr)
return token; return token;
token = matchString();
if (token != nullptr)
return token;
// type // type
token = match(TokenKind::TYPE, "bool", true); token = matchType();
if (token != nullptr)
return token;
token = match(TokenKind::TYPE, "sint32", true);
if (token != nullptr)
return token;
token = match(TokenKind::TYPE, "real32", true);
if (token != nullptr) if (token != nullptr)
return token; return token;
@@ -405,6 +409,27 @@ shared_ptr<Token> Lexer::matchReal() {
return token; return token;
} }
shared_ptr<Token> Lexer::matchString() {
int nextIndex = currentIndex;
if (currentIndex >= source.size() || source.at(nextIndex) != '\"')
return nullptr;
bool isClosing = false;
do {
nextIndex++;
isClosing = source.at(nextIndex) == '\"' && source.at(nextIndex - 1) != '\\';
} while (nextIndex < source.length() && !isClosing);
if (!isClosing)
return nullptr;
string lexme = source.substr(currentIndex, nextIndex - currentIndex + 1);
shared_ptr<Token> token = make_shared<Token>(TokenKind::STRING, lexme, currentLine, currentColumn);
advanceWithToken(token);
return token;
}
shared_ptr<Token> Lexer::matchIdentifier() { shared_ptr<Token> Lexer::matchIdentifier() {
int nextIndex = currentIndex; int nextIndex = currentIndex;
@@ -420,6 +445,24 @@ shared_ptr<Token> Lexer::matchIdentifier() {
return token; return token;
} }
shared_ptr<Token> Lexer::matchType() {
int nextIndex = currentIndex;
if (tokens.empty() || !tokens.back()->isOfKind({TokenKind::IDENTIFIER, TokenKind::LESS, TokenKind::RIGHT_ARROW}))
return nullptr;
while (nextIndex < source.length() && isIdentifier(nextIndex))
nextIndex++;
if (nextIndex == currentIndex || !isSeparator(nextIndex))
return nullptr;
string lexme = source.substr(currentIndex, nextIndex - currentIndex);
shared_ptr<Token> token = make_shared<Token>(TokenKind::TYPE, lexme, currentLine, currentColumn);
advanceWithToken(token);
return token;
}
shared_ptr<Token> Lexer::matchEnd() { shared_ptr<Token> Lexer::matchEnd() {
if (currentIndex >= source.length()) if (currentIndex >= source.length())
return make_shared<Token>(TokenKind::END, "", currentLine, currentColumn); return make_shared<Token>(TokenKind::END, "", currentLine, currentColumn);
@@ -472,6 +515,8 @@ bool Lexer::isSeparator(int index) {
case '>': case '>':
case '(': case '(':
case ')': case ')':
case '[':
case ']':
case ',': case ',':
case ':': case ':':
case ';': case ';':

View File

@@ -15,6 +15,7 @@ private:
int currentIndex; int currentIndex;
int currentLine; int currentLine;
int currentColumn; int currentColumn;
vector<shared_ptr<Token>> tokens;
vector<shared_ptr<Error>> errors; vector<shared_ptr<Error>> errors;
shared_ptr<Token> nextToken(); shared_ptr<Token> nextToken();
@@ -24,6 +25,8 @@ private:
shared_ptr<Token> matchIntegerBin(); shared_ptr<Token> matchIntegerBin();
shared_ptr<Token> matchIntegerChar(); shared_ptr<Token> matchIntegerChar();
shared_ptr<Token> matchReal(); shared_ptr<Token> matchReal();
shared_ptr<Token> matchString();
shared_ptr<Token> matchType();
shared_ptr<Token> matchIdentifier(); shared_ptr<Token> matchIdentifier();
shared_ptr<Token> matchEnd(); shared_ptr<Token> matchEnd();

View File

@@ -41,7 +41,8 @@ vector<TokenKind> Token::tokensLiteral = {
TokenKind::INTEGER_HEX, TokenKind::INTEGER_HEX,
TokenKind::INTEGER_BIN, TokenKind::INTEGER_BIN,
TokenKind::INTEGER_CHAR, TokenKind::INTEGER_CHAR,
TokenKind::REAL TokenKind::REAL,
TokenKind::STRING
}; };
Token::Token(TokenKind kind, string lexme, int line, int column): Token::Token(TokenKind kind, string lexme, int line, int column):

View File

@@ -21,6 +21,8 @@ enum class TokenKind {
LEFT_PAREN, LEFT_PAREN,
RIGHT_PAREN, RIGHT_PAREN,
LEFT_SQUARE_BRACKET,
RIGHT_SQUARE_BRACKET,
COMMA, COMMA,
COLON, COLON,
SEMICOLON, SEMICOLON,
@@ -39,6 +41,7 @@ enum class TokenKind {
INTEGER_BIN, INTEGER_BIN,
INTEGER_CHAR, INTEGER_CHAR,
REAL, REAL,
STRING,
IDENTIFIER, IDENTIFIER,
TYPE, TYPE,

View File

@@ -23,6 +23,7 @@
#include "Parser/Expression/ExpressionVariable.h" #include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionGrouping.h" #include "Parser/Expression/ExpressionGrouping.h"
#include "Parser/Expression/ExpressionLiteral.h" #include "Parser/Expression/ExpressionLiteral.h"
#include "Parser/Expression/ExpressionArrayLiteral.h"
#include "Parser/Expression/ExpressionCall.h" #include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionBlock.h" #include "Parser/Expression/ExpressionBlock.h"
@@ -56,6 +57,10 @@ string Logger::toString(shared_ptr<Token> token) {
return "("; return "(";
case TokenKind::RIGHT_PAREN: case TokenKind::RIGHT_PAREN:
return ")"; return ")";
case TokenKind::LEFT_SQUARE_BRACKET:
return "[";
case TokenKind::RIGHT_SQUARE_BRACKET:
return "]";
case TokenKind::COMMA: case TokenKind::COMMA:
return ","; return ",";
case TokenKind::COLON: case TokenKind::COLON:
@@ -79,6 +84,8 @@ string Logger::toString(shared_ptr<Token> token) {
return "INT_CHAR(" + token->getLexme() + ")"; return "INT_CHAR(" + token->getLexme() + ")";
case TokenKind::REAL: case TokenKind::REAL:
return "REAL(" + token->getLexme() + ")"; return "REAL(" + token->getLexme() + ")";
case TokenKind::STRING:
return "STRING(" + token->getLexme() + ")";
case TokenKind::IDENTIFIER: case TokenKind::IDENTIFIER:
return "ID(" + token->getLexme() + ")"; return "ID(" + token->getLexme() + ")";
case TokenKind::TYPE: case TokenKind::TYPE:
@@ -135,6 +142,10 @@ string Logger::toString(TokenKind tokenKind) {
return "("; return "(";
case TokenKind::RIGHT_PAREN: case TokenKind::RIGHT_PAREN:
return ")"; return ")";
case TokenKind::LEFT_SQUARE_BRACKET:
return "[";
case TokenKind::RIGHT_SQUARE_BRACKET:
return "]";
case TokenKind::COMMA: case TokenKind::COMMA:
return ","; return ",";
case TokenKind::COLON: case TokenKind::COLON:
@@ -155,6 +166,8 @@ string Logger::toString(TokenKind tokenKind) {
return "LITERAL(INTEGER)"; return "LITERAL(INTEGER)";
case TokenKind::REAL: case TokenKind::REAL:
return "LITERAL(REAL)"; return "LITERAL(REAL)";
case TokenKind::STRING:
return "LITERAL(STRING)";
case TokenKind::IDENTIFIER: case TokenKind::IDENTIFIER:
return "LITERAL(ID)"; return "LITERAL(ID)";
case TokenKind::TYPE: case TokenKind::TYPE:
@@ -191,6 +204,8 @@ string Logger::toString(shared_ptr<ValueType> valueType) {
return "SINT32"; return "SINT32";
case ValueTypeKind::REAL32: case ValueTypeKind::REAL32:
return "REAL32"; return "REAL32";
case ValueTypeKind::DATA:
return "[]";
} }
} }
@@ -308,6 +323,8 @@ string Logger::toString(shared_ptr<Expression> expression) {
return toString(dynamic_pointer_cast<ExpressionGrouping>(expression)); return toString(dynamic_pointer_cast<ExpressionGrouping>(expression));
case ExpressionKind::LITERAL: case ExpressionKind::LITERAL:
return toString(dynamic_pointer_cast<ExpressionLiteral>(expression)); return toString(dynamic_pointer_cast<ExpressionLiteral>(expression));
case ExpressionKind::ARRAY_LITERAL:
return toString(dynamic_pointer_cast<ExpressionArrayLiteral>(expression));
case ExpressionKind::CALL: case ExpressionKind::CALL:
return toString(dynamic_pointer_cast<ExpressionCall>(expression)); return toString(dynamic_pointer_cast<ExpressionCall>(expression));
case ExpressionKind::BLOCK: case ExpressionKind::BLOCK:
@@ -359,7 +376,11 @@ string Logger::toString(shared_ptr<ExpressionIfElse> expression) {
} }
string Logger::toString(shared_ptr<ExpressionVariable> expression) { string Logger::toString(shared_ptr<ExpressionVariable> expression) {
return format("VAR({})", expression->getName()); string text = format("VAR({}", expression->getName());
if (expression->getIndexExpression() != nullptr)
text += format("|{}", toString(expression->getIndexExpression()));
text += ")";
return text;
} }
string Logger::toString(shared_ptr<ExpressionGrouping> expression) { string Logger::toString(shared_ptr<ExpressionGrouping> expression) {
@@ -379,9 +400,23 @@ string Logger::toString(shared_ptr<ExpressionLiteral> expression) {
return to_string(expression->getSint32Value()); return to_string(expression->getSint32Value());
case ValueTypeKind::REAL32: case ValueTypeKind::REAL32:
return to_string(expression->getReal32Value()); return to_string(expression->getReal32Value());
default:
return "?";
} }
} }
string Logger::toString(shared_ptr<ExpressionArrayLiteral> expression) {
string text;
text += "[";
for (int i=0; i<expression->getExpressions().size(); i++) {
text += toString(expression->getExpressions().at(i));
if (i < expression->getExpressions().size() - 1)
text += ", ";
}
text += "]";
return text;
}
string Logger::toString(shared_ptr<ExpressionCall> expression) { string Logger::toString(shared_ptr<ExpressionCall> expression) {
string argsString; string argsString;
for (int i = 0; i < expression->getArgumentExpressions().size(); i++) { for (int i = 0; i < expression->getArgumentExpressions().size(); i++) {

View File

@@ -23,6 +23,7 @@ class ExpressionIfElse;
class ExpressionVariable; class ExpressionVariable;
class ExpressionGrouping; class ExpressionGrouping;
class ExpressionLiteral; class ExpressionLiteral;
class ExpressionArrayLiteral;
class ExpressionCall; class ExpressionCall;
class ExpressionBlock; class ExpressionBlock;
@@ -52,6 +53,7 @@ private:
static string toString(shared_ptr<ExpressionVariable> expression); static string toString(shared_ptr<ExpressionVariable> expression);
static string toString(shared_ptr<ExpressionGrouping> expression); static string toString(shared_ptr<ExpressionGrouping> expression);
static string toString(shared_ptr<ExpressionLiteral> expression); static string toString(shared_ptr<ExpressionLiteral> expression);
static string toString(shared_ptr<ExpressionArrayLiteral> expression);
static string toString(shared_ptr<ExpressionCall> expression); static string toString(shared_ptr<ExpressionCall> expression);
static string toString(shared_ptr<ExpressionBlock> expression); static string toString(shared_ptr<ExpressionBlock> expression);

View File

@@ -10,6 +10,7 @@ using namespace std;
enum class ExpressionKind { enum class ExpressionKind {
LITERAL, LITERAL,
ARRAY_LITERAL,
GROUPING, GROUPING,
BINARY, BINARY,
IF_ELSE, IF_ELSE,

View File

@@ -0,0 +1,47 @@
#include "ExpressionArrayLiteral.h"
#include "Lexer/Token.h"
#include "Parser/Expression/ExpressionLiteral.h"
shared_ptr<ExpressionArrayLiteral> ExpressionArrayLiteral::expressionArrayLiteralForExpressions(vector<shared_ptr<Expression>> expressions) {
shared_ptr<ExpressionArrayLiteral> expression = make_shared<ExpressionArrayLiteral>();
expression->expressions = expressions;
return expression;
}
shared_ptr<ExpressionArrayLiteral> ExpressionArrayLiteral::expressionArrayLiteralForTokenString(shared_ptr<Token> tokenString) {
if (tokenString->getKind() != TokenKind::STRING)
return nullptr;
shared_ptr<ExpressionArrayLiteral> expression = make_shared<ExpressionArrayLiteral>();
vector<shared_ptr<Expression>> expressions;
string stringValue = tokenString->getLexme();
for (int i=1; i<stringValue.length()-1; i++) {
string lexme = stringValue.substr(i, 1);
if (stringValue[i] == '\\') {
lexme = stringValue.substr(i, 2);
i++;
}
shared_ptr<Token> token = make_shared<Token>(TokenKind::INTEGER_CHAR, lexme, tokenString->getLine(), tokenString->getColumn() + i);
shared_ptr<ExpressionLiteral> expression = ExpressionLiteral::expressionLiteralForToken(token);
expressions.push_back(expression);
// add terminal 0 if missing
if (i == stringValue.length() - 2 && lexme.compare("\\0") != 0) {
shared_ptr<Token> token = make_shared<Token>(TokenKind::INTEGER_CHAR, "\\0", tokenString->getLine(), tokenString->getColumn() + i + lexme.length());
shared_ptr<ExpressionLiteral> expression = ExpressionLiteral::expressionLiteralForToken(token);
expressions.push_back(expression);
}
}
expression->expressions = expressions;
return expression;
}
ExpressionArrayLiteral::ExpressionArrayLiteral():
Expression(ExpressionKind::ARRAY_LITERAL, nullptr) { }
vector<shared_ptr<Expression>> ExpressionArrayLiteral::getExpressions() {
return expressions;
}

View File

@@ -0,0 +1,18 @@
#ifndef EXPRESSION_ARRAY_LITERAL_H
#define EXPRESSION_ARRAY_LITERAL_H
#include "Expression.h"
class ExpressionArrayLiteral: public Expression {
private:
vector<shared_ptr<Expression>> expressions;
public:
static shared_ptr<ExpressionArrayLiteral> expressionArrayLiteralForExpressions(vector<shared_ptr<Expression>> expressions);
static shared_ptr<ExpressionArrayLiteral> expressionArrayLiteralForTokenString(shared_ptr<Token> tokenString);
ExpressionArrayLiteral();
vector<shared_ptr<Expression>> getExpressions();
};
#endif

View File

@@ -1,79 +1,63 @@
#include "ExpressionLiteral.h" #include "ExpressionLiteral.h"
#include "Utils.h"
#include "Lexer/Token.h" #include "Lexer/Token.h"
#include "Parser/ValueType.h" #include "Parser/ValueType.h"
ExpressionLiteral::ExpressionLiteral(): shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(shared_ptr<Token> token) {
Expression(ExpressionKind::LITERAL, nullptr) { } shared_ptr<ExpressionLiteral> expression = make_shared<ExpressionLiteral>();
ExpressionLiteral::ExpressionLiteral(shared_ptr<Token> token):
Expression(ExpressionKind::LITERAL, nullptr) {
switch (token->getKind()) { switch (token->getKind()) {
case TokenKind::BOOL: case TokenKind::BOOL:
boolValue = token->getLexme().compare("true") == 0; expression->boolValue = token->getLexme().compare("true") == 0;
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break; break;
case TokenKind::INTEGER_DEC: { case TokenKind::INTEGER_DEC: {
string numString = token->getLexme(); string numString = token->getLexme();
erase(numString, '_'); erase(numString, '_');
sint32Value = stoi(numString, nullptr, 10); expression->sint32Value = stoi(numString, nullptr, 10);
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break; break;
} }
case TokenKind::INTEGER_HEX: { case TokenKind::INTEGER_HEX: {
string numString = token->getLexme(); string numString = token->getLexme();
erase(numString, '_'); erase(numString, '_');
sint32Value = stoi(numString, nullptr, 16); expression->sint32Value = stoi(numString, nullptr, 16);
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break; break;
} }
case TokenKind::INTEGER_BIN: { case TokenKind::INTEGER_BIN: {
string numString = token->getLexme(); string numString = token->getLexme();
erase(numString, '_'); erase(numString, '_');
numString = numString.substr(2, numString.size()-1); numString = numString.substr(2, numString.size()-1);
sint32Value = stoi(numString, nullptr, 2); expression->sint32Value = stoi(numString, nullptr, 2);
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break; break;
} }
case TokenKind::INTEGER_CHAR: { case TokenKind::INTEGER_CHAR: {
string charString = token->getLexme(); string charString = token->getLexme();
optional<int> charValue = Utils::charStringToInt(charString);
if (!charValue)
return nullptr;
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
if (charString.length() == 3) { expression->sint32Value = *charValue;
sint32Value = charString[1]; return expression;
} else if (charString.length() == 4 && charString[1] == '\\') {
switch (charString[2]) {
case 'b':
sint32Value = '\b';
break;
case 'n':
sint32Value = '\n';
break;
case 't':
sint32Value = '\t';
break;
case '\\':
sint32Value = '\\';
break;
case '\'':
sint32Value = '\'';
break;
case '\"':
sint32Value = '\"';
break;
}
}
break;
} }
case TokenKind::REAL: case TokenKind::REAL:
real32Value = stof(token->getLexme()); expression->real32Value = stof(token->getLexme());
valueType = ValueType::valueTypeForToken(token); expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break; break;
default: default:
exit(1); return nullptr;
} }
return expression;
} }
ExpressionLiteral::ExpressionLiteral():
Expression(ExpressionKind::LITERAL, nullptr) { }
bool ExpressionLiteral::getBoolValue() { bool ExpressionLiteral::getBoolValue() {
return boolValue; return boolValue;
} }

View File

@@ -1,4 +1,7 @@
#include "Parser/Expression/Expression.h" #ifndef EXPRESSION_LITERAL_H
#define EXPRESSION_LITERAL_H
#include "Expression.h"
class ExpressionLiteral: public Expression { class ExpressionLiteral: public Expression {
private: private:
@@ -7,9 +10,12 @@ private:
float real32Value; float real32Value;
public: public:
ExpressionLiteral(shared_ptr<Token> token); static shared_ptr<ExpressionLiteral> expressionLiteralForToken(shared_ptr<Token> token);
ExpressionLiteral(); ExpressionLiteral();
bool getBoolValue(); bool getBoolValue();
int32_t getSint32Value(); int32_t getSint32Value();
float getReal32Value(); float getReal32Value();
}; };
#endif

View File

@@ -1,8 +1,12 @@
#include "ExpressionVariable.h" #include "ExpressionVariable.h"
ExpressionVariable::ExpressionVariable(string name): ExpressionVariable::ExpressionVariable(string name, shared_ptr<Expression> indexExpression):
Expression(ExpressionKind::VAR, nullptr), name(name) { } Expression(ExpressionKind::VAR, nullptr), name(name), indexExpression(indexExpression) { }
string ExpressionVariable::getName() { string ExpressionVariable::getName() {
return name; return name;
} }
shared_ptr<Expression> ExpressionVariable::getIndexExpression() {
return indexExpression;
}

View File

@@ -3,8 +3,10 @@
class ExpressionVariable: public Expression { class ExpressionVariable: public Expression {
private: private:
string name; string name;
shared_ptr<Expression> indexExpression;
public: public:
ExpressionVariable(string name); ExpressionVariable(string name, shared_ptr<Expression> indexExpression);
string getName(); string getName();
shared_ptr<Expression> getIndexExpression();
}; };

View File

@@ -8,6 +8,7 @@
#include "Parser/Expression/ExpressionGrouping.h" #include "Parser/Expression/ExpressionGrouping.h"
#include "Parser/Expression/ExpressionLiteral.h" #include "Parser/Expression/ExpressionLiteral.h"
#include "Parser/Expression/ExpressionArrayLiteral.h"
#include "Parser/Expression/ExpressionVariable.h" #include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionCall.h" #include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionIfElse.h" #include "Parser/Expression/ExpressionIfElse.h"
@@ -121,8 +122,8 @@ shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
return nullptr; return nullptr;
} }
shared_ptr<Token> identifierToken = tokens.at(currentIndex++); shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Token> argumentTypeToken = tokens.at(currentIndex++); //shared_ptr<Token> argumentTypeToken = tokens.at(currentIndex++);
shared_ptr<ValueType> argumentType = ValueType::valueTypeForToken(argumentTypeToken); shared_ptr<ValueType> argumentType = matchValueType();
if (argumentType == nullptr) { if (argumentType == nullptr) {
markError(TokenKind::TYPE, {}); markError(TokenKind::TYPE, {});
return nullptr; return nullptr;
@@ -136,14 +137,12 @@ shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) { if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
shared_ptr<Token> returnTypeToken = tokens.at(currentIndex); //shared_ptr<Token> returnTypeToken = tokens.at(currentIndex);
returnType = ValueType::valueTypeForToken(returnTypeToken); returnType = matchValueType();
if (returnType == nullptr) { if (returnType == nullptr) {
markError(TokenKind::TYPE, {}); markError(TokenKind::TYPE, {});
return nullptr; return nullptr;
} }
currentIndex++; // type
} }
return make_shared<StatementMetaExternFunction>(identifierToken->getLexme(), arguments, returnType); return make_shared<StatementMetaExternFunction>(identifierToken->getLexme(), arguments, returnType);
@@ -154,21 +153,7 @@ shared_ptr<Statement> Parser::matchStatementVariable() {
return nullptr; return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex++); shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Token> valueTypeToken = tokens.at(currentIndex); shared_ptr<ValueType> valueType = matchValueType();
shared_ptr<ValueType> valueType;
if (valueTypeToken->getLexme().compare("bool") == 0)
valueType = ValueType::BOOL;
else if (valueTypeToken->getLexme().compare("sint32") == 0)
valueType = ValueType::SINT32;
else if (valueTypeToken->getLexme().compare("real32") == 0)
valueType = ValueType::REAL32;
else {
markError(TokenKind::TYPE, {});
return nullptr;
}
currentIndex++; // type
// Expect left arrow // Expect left arrow
if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true)) {
@@ -205,8 +190,7 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
return nullptr; return nullptr;
} }
shared_ptr<Token> identifierToken = tokens.at(currentIndex++); shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Token> argumentTypeToken = tokens.at(currentIndex++); shared_ptr<ValueType> argumentType = matchValueType();
shared_ptr<ValueType> argumentType = ValueType::valueTypeForToken(argumentTypeToken);
if (argumentType == nullptr) { if (argumentType == nullptr) {
markError(TokenKind::TYPE, {}); markError(TokenKind::TYPE, {});
return nullptr; return nullptr;
@@ -220,14 +204,11 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) { if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
shared_ptr<Token> returnTypeToken = tokens.at(currentIndex); returnType = matchValueType();
returnType = ValueType::valueTypeForToken(returnTypeToken);
if (returnType == nullptr) { if (returnType == nullptr) {
markError(TokenKind::TYPE, {}); markError(TokenKind::TYPE, {});
return nullptr; return nullptr;
} }
currentIndex++; // type
} }
// consume new line // consume new line
@@ -261,27 +242,43 @@ shared_ptr<Statement> Parser::matchStatementBlock(vector<TokenKind> terminalToke
break; break;
// except new line // except new line
if (statement != nullptr && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) { if (statement != nullptr && !tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true))
markError(TokenKind::NEW_LINE, {}); markError(TokenKind::NEW_LINE, {});
return nullptr;
}
} }
return make_shared<StatementBlock>(statements); return make_shared<StatementBlock>(statements);
} }
shared_ptr<Statement> Parser::matchStatementAssignment() { shared_ptr<Statement> Parser::matchStatementAssignment() {
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::LEFT_ARROW}, true, false)) int startIndex = currentIndex;
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, false))
return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<Expression> indexExpression;
if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
indexExpression = nextExpression();
if (indexExpression == nullptr)
return nullptr; return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex++); if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
currentIndex++; // arrow markError(TokenKind::RIGHT_SQUARE_BRACKET, {});
return nullptr;
}
}
// assignment requires left arrow, otherwise abort
if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true)) {
currentIndex = startIndex;
return nullptr;
}
shared_ptr<Expression> expression = nextExpression(); shared_ptr<Expression> expression = nextExpression();
if (expression == nullptr) if (expression == nullptr)
return nullptr; return nullptr;
return make_shared<StatementAssignment>(identifierToken->getLexme(), expression); return make_shared<StatementAssignment>(identifierToken->getLexme(), indexExpression, expression);
} }
shared_ptr<Statement> Parser::matchStatementReturn() { shared_ptr<Statement> Parser::matchStatementReturn() {
@@ -313,7 +310,7 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// got initial, expect comma // got initial, expect comma
if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { if (initStatement != nullptr && !tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {}); markError(TokenKind::COMMA, {});
return nullptr; goto afterIf;
} }
// optional new line // optional new line
@@ -326,7 +323,7 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// got pre-condition, expect comma // got pre-condition, expect comma
if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
markError(TokenKind::COMMA, {}); markError(TokenKind::COMMA, {});
return nullptr; goto afterIf;
} }
// optional new line // optional new line
@@ -338,10 +335,11 @@ shared_ptr<Statement> Parser::matchStatementRepeat() {
// expect colon // expect colon
if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
markError(TokenKind::COLON, {}); markError(TokenKind::COLON, {});
return nullptr; goto afterIf;
} }
} }
} }
afterIf:
isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); isMultiLine = tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
@@ -437,28 +435,32 @@ shared_ptr<Expression> Parser::matchFactor() {
shared_ptr<Expression> Parser::matchPrimary() { shared_ptr<Expression> Parser::matchPrimary() {
shared_ptr<Expression> expression; shared_ptr<Expression> expression;
int errorsCount = errors.size();
expression = matchExpressionGrouping(); expression = matchExpressionGrouping();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression;
expression = matchExpressionArrayLiteral();
if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionLiteral(); expression = matchExpressionLiteral();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionCall(); expression = matchExpressionCall();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
expression = matchExpressionVariable(); expression = matchExpressionVariable();
if (expression != nullptr) if (expression != nullptr || errors.size() > errorsCount)
return expression; return expression;
return nullptr; return nullptr;
} }
shared_ptr<Expression> Parser::matchExpressionGrouping() { shared_ptr<Expression> Parser::matchExpressionGrouping() {
shared_ptr<Token> token = tokens.at(currentIndex);
if (tryMatchingTokenKinds({TokenKind::LEFT_PAREN}, true, true)) { if (tryMatchingTokenKinds({TokenKind::LEFT_PAREN}, true, true)) {
shared_ptr<Expression> expression = matchTerm(); shared_ptr<Expression> expression = matchTerm();
// has grouped expression failed? // has grouped expression failed?
@@ -478,18 +480,53 @@ shared_ptr<Expression> Parser::matchExpressionLiteral() {
shared_ptr<Token> token = tokens.at(currentIndex); shared_ptr<Token> token = tokens.at(currentIndex);
if (tryMatchingTokenKinds(Token::tokensLiteral, false, true)) if (tryMatchingTokenKinds(Token::tokensLiteral, false, true))
return make_shared<ExpressionLiteral>(token); return ExpressionLiteral::expressionLiteralForToken(token);
return nullptr;
}
shared_ptr<Expression> Parser::matchExpressionArrayLiteral() {
if (tryMatchingTokenKinds({TokenKind::STRING}, true, false)) {
return ExpressionArrayLiteral::expressionArrayLiteralForTokenString(tokens.at(currentIndex++));
} else if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
vector<shared_ptr<Expression>> expressions;
if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
do {
shared_ptr<Expression> expression = nextExpression();
if (expression != nullptr)
expressions.push_back(expression);
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
markError(TokenKind::RIGHT_SQUARE_BRACKET, {});
return nullptr;
}
}
return ExpressionArrayLiteral::expressionArrayLiteralForExpressions(expressions);
}
return nullptr; return nullptr;
} }
shared_ptr<Expression> Parser::matchExpressionVariable() { shared_ptr<Expression> Parser::matchExpressionVariable() {
shared_ptr<Token> token = tokens.at(currentIndex); if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, false))
if (tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, true))
return make_shared<ExpressionVariable>(token->getLexme());
return nullptr; return nullptr;
shared_ptr<Token> idToken = tokens.at(currentIndex++);
shared_ptr<Expression> indexExpression;
if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
indexExpression = nextExpression();
if (indexExpression == nullptr)
return nullptr;
if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
markError(TokenKind::RIGHT_SQUARE_BRACKET, {});
return nullptr;
}
}
return make_shared<ExpressionVariable>(idToken->getLexme(), indexExpression);
} }
shared_ptr<Expression> Parser::matchExpressionCall() { shared_ptr<Expression> Parser::matchExpressionCall() {
@@ -614,6 +651,46 @@ shared_ptr<Expression> Parser::matchExpressionBlock(vector<TokenKind> terminalTo
return make_shared<ExpressionBlock>(statements); return make_shared<ExpressionBlock>(statements);
} }
shared_ptr<ValueType> Parser::matchValueType() {
if (!tryMatchingTokenKinds({TokenKind::TYPE}, true, false))
return nullptr;
shared_ptr<Token> typeToken = tokens.at(currentIndex++);
shared_ptr<ValueType> subType;
int valueArg = 0;
if (tryMatchingTokenKinds({TokenKind::LESS}, true, true)) {
if (!tryMatchingTokenKinds({TokenKind::TYPE}, true, false)) {
markError(TokenKind::TYPE, {});
return nullptr;
}
subType = matchValueType();
if (subType == nullptr)
return subType;
if (tryMatchingTokenKinds({TokenKind::COMMA}, true, true)) {
if (!tryMatchingTokenKinds({TokenKind::INTEGER_DEC, TokenKind::INTEGER_HEX, TokenKind::INTEGER_BIN, TokenKind::INTEGER_CHAR}, false, false)) {
markError({}, "Expected integer literal");
return nullptr;
}
shared_ptr<Expression> expressionValue = matchExpressionLiteral();
if (expressionValue == nullptr) {
markError({}, "Expected integer literal");
return nullptr;
}
valueArg = dynamic_pointer_cast<ExpressionLiteral>(expressionValue)->getSint32Value();
}
if (!tryMatchingTokenKinds({TokenKind::GREATER}, true, true)) {
markError(TokenKind::GREATER, {});
return nullptr;
}
}
return ValueType::valueTypeForToken(typeToken, subType, valueArg);
}
bool Parser::tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance) { bool Parser::tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance) {
int requiredCount = shouldMatchAll ? kinds.size() : 1; int requiredCount = shouldMatchAll ? kinds.size() : 1;
if (currentIndex + requiredCount > tokens.size()) if (currentIndex + requiredCount > tokens.size())
@@ -655,5 +732,9 @@ void Parser::markError(optional<TokenKind> expectedTokenKind, optional<string> m
while (!tryMatchingTokenKinds(safeKinds, false, true)) while (!tryMatchingTokenKinds(safeKinds, false, true))
currentIndex++; currentIndex++;
// Last END should not be consumed
if (currentIndex > tokens.size() - 1)
currentIndex = tokens.size() - 1;
errors.push_back(Error::parserError(actualToken, expectedTokenKind, message)); errors.push_back(Error::parserError(actualToken, expectedTokenKind, message));
} }

View File

@@ -3,9 +3,11 @@
#include <vector> #include <vector>
class Error;
class Token; class Token;
enum class TokenKind; enum class TokenKind;
class Error; class ValueType;
class Expression; class Expression;
class Statement; class Statement;
@@ -40,12 +42,15 @@ private:
shared_ptr<Expression> matchExpressionGrouping(); shared_ptr<Expression> matchExpressionGrouping();
shared_ptr<Expression> matchExpressionLiteral(); shared_ptr<Expression> matchExpressionLiteral();
shared_ptr<Expression> matchExpressionArrayLiteral();
shared_ptr<Expression> matchExpressionVariable(); shared_ptr<Expression> matchExpressionVariable();
shared_ptr<Expression> matchExpressionCall(); shared_ptr<Expression> matchExpressionCall();
shared_ptr<Expression> matchExpressionIfElse(); shared_ptr<Expression> matchExpressionIfElse();
shared_ptr<Expression> matchExpressionBinary(shared_ptr<Expression> left); shared_ptr<Expression> matchExpressionBinary(shared_ptr<Expression> left);
shared_ptr<Expression> matchExpressionBlock(vector<TokenKind> terminalTokenKinds); shared_ptr<Expression> matchExpressionBlock(vector<TokenKind> terminalTokenKinds);
shared_ptr<ValueType> matchValueType();
bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance); bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance);
void markError(optional<TokenKind> expectedTokenKind, optional<string> message); void markError(optional<TokenKind> expectedTokenKind, optional<string> message);

View File

@@ -1,12 +1,16 @@
#include "StatementAssignment.h" #include "StatementAssignment.h"
StatementAssignment::StatementAssignment(string name, shared_ptr<Expression> expression): StatementAssignment::StatementAssignment(string name, shared_ptr<Expression> indexExpression, shared_ptr<Expression> expression):
Statement(StatementKind::ASSIGNMENT), name(name), expression(expression) { } Statement(StatementKind::ASSIGNMENT), name(name), indexExpression(indexExpression), expression(expression) { }
string StatementAssignment::getName() { string StatementAssignment::getName() {
return name; return name;
} }
shared_ptr<Expression> StatementAssignment::getIndexExpression() {
return indexExpression;
}
shared_ptr<Expression> StatementAssignment::getExpression() { shared_ptr<Expression> StatementAssignment::getExpression() {
return expression; return expression;
} }

View File

@@ -5,10 +5,12 @@ class Expression;
class StatementAssignment: public Statement { class StatementAssignment: public Statement {
private: private:
string name; string name;
shared_ptr<Expression> indexExpression;
shared_ptr<Expression> expression; shared_ptr<Expression> expression;
public: public:
StatementAssignment(string name, shared_ptr<Expression> expression); StatementAssignment(string name, shared_ptr<Expression> indexExpressio, shared_ptr<Expression> expression);
string getName(); string getName();
shared_ptr<Expression> getIndexExpression();
shared_ptr<Expression> getExpression(); shared_ptr<Expression> getExpression();
}; };

View File

@@ -2,36 +2,38 @@
#include "Lexer/Token.h" #include "Lexer/Token.h"
shared_ptr<ValueType> ValueType::NONE = make_shared<ValueType>(ValueTypeKind::NONE); shared_ptr<ValueType> ValueType::NONE = make_shared<ValueType>(ValueTypeKind::NONE, nullptr, 0);
shared_ptr<ValueType> ValueType::BOOL = make_shared<ValueType>(ValueTypeKind::BOOL); shared_ptr<ValueType> ValueType::BOOL = make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
shared_ptr<ValueType> ValueType::SINT32 = make_shared<ValueType>(ValueTypeKind::SINT32); shared_ptr<ValueType> ValueType::SINT32 = make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
shared_ptr<ValueType> ValueType::REAL32 = make_shared<ValueType>(ValueTypeKind::REAL32); shared_ptr<ValueType> ValueType::REAL32 = make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
ValueType::ValueType(ValueTypeKind kind): ValueType::ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg):
kind(kind) { } kind(kind), subType(subType), valueArg(valueArg) { }
shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token) { shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg) {
switch (token->getKind()) { switch (token->getKind()) {
case TokenKind::TYPE: { case TokenKind::TYPE: {
string lexme = token->getLexme(); string lexme = token->getLexme();
if (lexme.compare("bool") == 0) if (lexme.compare("bool") == 0)
return make_shared<ValueType>(ValueTypeKind::BOOL); return make_shared<ValueType>(ValueTypeKind::BOOL, subType, valueArg);
else if (lexme.compare("sint32") == 0) else if (lexme.compare("sint32") == 0)
return make_shared<ValueType>(ValueTypeKind::SINT32); return make_shared<ValueType>(ValueTypeKind::SINT32, subType, valueArg);
else if (lexme.compare("real32") == 0) else if (lexme.compare("real32") == 0)
return make_shared<ValueType>(ValueTypeKind::REAL32); return make_shared<ValueType>(ValueTypeKind::REAL32, subType, valueArg);
else if (lexme.compare("data") == 0)
return make_shared<ValueType>(ValueTypeKind::DATA, subType, valueArg);
else else
return nullptr; return nullptr;
} }
case TokenKind::BOOL: case TokenKind::BOOL:
return make_shared<ValueType>(ValueTypeKind::BOOL); return make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
case TokenKind::INTEGER_DEC: case TokenKind::INTEGER_DEC:
case TokenKind::INTEGER_HEX: case TokenKind::INTEGER_HEX:
case TokenKind::INTEGER_BIN: case TokenKind::INTEGER_BIN:
case TokenKind::INTEGER_CHAR: case TokenKind::INTEGER_CHAR:
return make_shared<ValueType>(ValueTypeKind::SINT32); return make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
case TokenKind::REAL: case TokenKind::REAL:
return make_shared<ValueType>(ValueTypeKind::REAL32); return make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
default: default:
return nullptr; return nullptr;
} }
@@ -40,3 +42,11 @@ shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token) {
ValueTypeKind ValueType::getKind() { ValueTypeKind ValueType::getKind() {
return kind; return kind;
} }
shared_ptr<ValueType> ValueType::getSubType() {
return subType;
}
int ValueType::getValueArg() {
return valueArg;
}

View File

@@ -11,22 +11,27 @@ enum class ValueTypeKind {
NONE, NONE,
BOOL, BOOL,
SINT32, SINT32,
REAL32 REAL32,
DATA
}; };
class ValueType { class ValueType {
private: private:
ValueTypeKind kind; ValueTypeKind kind;
shared_ptr<ValueType> subType;
int valueArg;
public: public:
static shared_ptr<ValueType> NONE; static shared_ptr<ValueType> NONE;
static shared_ptr<ValueType> BOOL; static shared_ptr<ValueType> BOOL;
static shared_ptr<ValueType> SINT32; static shared_ptr<ValueType> SINT32;
static shared_ptr<ValueType> REAL32; static shared_ptr<ValueType> REAL32;
static shared_ptr<ValueType> valueTypeForToken(shared_ptr<Token> token); static shared_ptr<ValueType> valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg);
ValueType(ValueTypeKind kind); ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg);
ValueTypeKind getKind(); ValueTypeKind getKind();
shared_ptr<ValueType> getSubType();
int getValueArg();
}; };
#endif #endif

36
src/Utils.cpp Normal file
View File

@@ -0,0 +1,36 @@
#include "Utils.h"
optional<int> Utils::charStringToInt(string charString) {
switch (charString.length()) {
case 1:
return charString[0];
case 3:
return charString[1];
case 4:
charString[0] = charString[1];
charString[1] = charString[2];
case 2:
if (charString[0] != '\\')
return {};
switch (charString[1]) {
case 'b':
return '\b';
case 'n':
return '\n';
case 't':
return '\t';
case '\\':
return '\\';
case '\'':
return '\'';
case '\"':
return '\"';
case '0':
return '\0';
default:
return {};
}
default:
return {};
}
}

13
src/Utils.h Normal file
View File

@@ -0,0 +1,13 @@
#ifndef UTILS_H
#define UTILS_H
#include <iostream>
using namespace std;
class Utils {
public:
static optional<int> charStringToInt(string charString);
};
#endif