Merge branch 'main' into 26-update-readme

This commit is contained in:
Rafał Grodziński
2025-08-01 12:45:51 +09:00
35 changed files with 1426 additions and 285 deletions

6
.gitignore vendored
View File

@@ -1,3 +1,8 @@
# ingnore files without extension
*
!*.*
!*/
.DS_Store
.vscode/settings.json
@@ -7,3 +12,4 @@ build/
# brb build artifiacts
*.o
*.asm

2
.vscode/launch.json vendored
View File

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

9
.vscode/tasks.json vendored
View File

@@ -3,12 +3,17 @@
"tasks": [
{
"label": "Build Bits Runner Builder (Debug)",
"type": "cmake",
"command": "build",
"type": "shell",
"command": "cmake -B build && cmake --build build --config Debug",
"group": {
"kind": "build",
"isDefault": true
}
},
{
"label": "Clean",
"type": "shell",
"command": "rm -rf build *.o *.asm; find ./ -perm +100 -type f -maxdepth 1 -delete"
}
]
}

View File

@@ -1,6 +1,6 @@
@extern putchar fun: character sint32 -> sint32
@extern putchar fun: character u32 -> u32
fib fun: number sint32 -> sint32
fib fun: number u32 -> u32
ret if number < 2:
number
else
@@ -8,13 +8,13 @@ fib fun: number sint32 -> sint32
;
;
printNum fun: number sint32
biggest sint32 <- 10
printNum fun: number u32
biggest u32 <- 10
rep biggest <= number: biggest <- biggest * 10
biggest <- biggest / 10
rep biggest > 0:
digit sint32 <- number / biggest
digit u32 <- number / biggest
putchar(digit + '0')
number <- number % biggest
biggest <- biggest / 10
@@ -22,9 +22,9 @@ printNum fun: number sint32
;
// Print first 20 fibonaci numbers
main fun -> sint32
rep i sint32 <- 0, i < 20:
res sint32 <- fib(i)
main fun -> u32
rep i u32 <- 0, i < 20:
res u32 <- fib(i)
printNum(res)
putchar('\n')
i <- i + 1

View File

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

View File

@@ -1,4 +1,6 @@
@extern putchar fun: character sint32 -> sint32
//@extern putchar fun: character sint32 -> sint32
// ./build/brb samples/test.brc -S -x86-asm-syntax=intel
/*
User type
@@ -18,8 +20,42 @@ i u32 <- 0, rep text[i] != 0:
// text data<u8> <- "Hello world!"
main fun -> sint32
text data<sint32> <- "Hello string!\n"
/*addStuff asm<"+r, r">: num1 u32, num2 u32 -> u32
add $1, $0
;*/
/*normAdd fun: num1 sint32, num2 sint32 -> sint32
ret num1 + num2
;*/
/*rawAdd raw<"=r,r,r">: num1 sint32, num2 sint32 -> sint32
add $1, $2
mov $0, $1
;*/
/*rawAdd raw: num1 sint32, num2 sint32 -> sint32
add $1, $2
mov $0, $1
;*/
/*printChar raw
.global REGISTER
.text
.REGISTER:
.byte "Hello", 0xa0
.long RegisterTable
//push 0x21
;*/
main fun -> u32
num1 u8 <- 42
num2 s8 <- 3 - +15
num3 u32 <- 1234123
num4 s32 <- -345345
num5 r32 <- -42.58
num5 + num3
ret 0
;

View File

@@ -11,9 +11,11 @@
#include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionIfElse.h"
#include "Parser/Expression/ExpressionBinary.h"
#include "Parser/Expression/ExpressionUnary.h"
#include "Parser/Expression/ExpressionBlock.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementRawFunction.h"
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
@@ -31,8 +33,11 @@ moduleName(moduleName), sourceFileName(sourceFileName), statements(statements) {
typeVoid = llvm::Type::getVoidTy(*context);
typeBool = llvm::Type::getInt1Ty(*context);
typeSint32 = llvm::Type::getInt32Ty(*context);
typeReal32 = llvm::Type::getFloatTy(*context);
typeU8 = llvm::Type::getInt8Ty(*context);
typeU32 = llvm::Type::getInt32Ty(*context);
typeS8 = llvm::Type::getInt8Ty(*context);
typeS32 = llvm::Type::getInt32Ty(*context);
typeR32 = llvm::Type::getFloatTy(*context);
}
shared_ptr<llvm::Module> ModuleBuilder::getModule() {
@@ -40,6 +45,12 @@ shared_ptr<llvm::Module> ModuleBuilder::getModule() {
for (shared_ptr<Statement> &statement : statements)
buildStatement(statement);
// verify module
string errorMessage;
llvm::raw_string_ostream llvmErrorMessage(errorMessage);
if (llvm::verifyModule(*module, &llvmErrorMessage))
markError(0, 0, errorMessage);
if (!errors.empty()) {
for (shared_ptr<Error> &error : errors)
Logger::print(error);
@@ -52,7 +63,10 @@ shared_ptr<llvm::Module> ModuleBuilder::getModule() {
void ModuleBuilder::buildStatement(shared_ptr<Statement> statement) {
switch (statement->getKind()) {
case StatementKind::FUNCTION:
buildFunctionDeclaration(dynamic_pointer_cast<StatementFunction>(statement));
buildFunction(dynamic_pointer_cast<StatementFunction>(statement));
break;
case StatementKind::RAW_FUNCTION:
buildRawFunction(dynamic_pointer_cast<StatementRawFunction>(statement));
break;
case StatementKind::VARIABLE:
buildVarDeclaration(dynamic_pointer_cast<StatementVariable>(statement));
@@ -80,15 +94,21 @@ void ModuleBuilder::buildStatement(shared_ptr<Statement> statement) {
}
}
void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> statement) {
// get argument types
vector<llvm::Type *> types;
void ModuleBuilder::buildFunction(shared_ptr<StatementFunction> statement) {
// function types
llvm::Type *returnType = typeForValueType(statement->getReturnValueType());
if (returnType == nullptr)
return;
vector<llvm::Type *> argTypes;
for (pair<string, shared_ptr<ValueType>> &arg : statement->getArguments()) {
types.push_back(typeForValueType(arg.second));
llvm::Type *argType = typeForValueType(arg.second);
if (argType == nullptr)
return;
argTypes.push_back(argType);
}
// build function declaration
llvm::FunctionType *funType = llvm::FunctionType::get(typeForValueType(statement->getReturnValueType()), types, false);
llvm::FunctionType *funType = llvm::FunctionType::get(returnType, argTypes, false);
llvm::Function *fun = llvm::Function::Create(funType, llvm::GlobalValue::ExternalLinkage, statement->getName(), module.get());
if (!setFun(statement->getName(), fun))
return;
@@ -103,7 +123,7 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> state
int i=0;
for (auto &arg : fun->args()) {
string name = statement->getArguments()[i].first;
llvm::Type *type = types[i];
llvm::Type *type = argTypes[i];
arg.setName(name);
llvm::AllocaInst *alloca = builder->CreateAlloca(type, nullptr, name);
@@ -126,6 +146,20 @@ void ModuleBuilder::buildFunctionDeclaration(shared_ptr<StatementFunction> state
markError(0, 0, errorMessage);
}
void ModuleBuilder::buildRawFunction(shared_ptr<StatementRawFunction> statement) {
// function types
llvm::Type *returnType = typeForValueType(statement->getReturnValueType());
vector<llvm::Type *> argTypes;
for (pair<string, shared_ptr<ValueType>> &arg : statement->getArguments())
argTypes.push_back(typeForValueType(arg.second));
// build function declaration & body
llvm::FunctionType *funType = llvm::FunctionType::get(returnType, argTypes, false);
llvm::InlineAsm *rawFun = llvm::InlineAsm::get(funType, statement->getRawSource(), statement->getConstraints(), true, false, llvm::InlineAsm::AsmDialect::AD_Intel);
if (!setRawFun(statement->getName(), rawFun))
return;
}
void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement) {
if (statement->getValueType()->getKind() == ValueTypeKind::DATA) {
vector<llvm::Value *> values = valuesForExpression(statement->getExpression());
@@ -145,6 +179,8 @@ void ModuleBuilder::buildVarDeclaration(shared_ptr<StatementVariable> statement)
}
} else {
llvm::Value *value = valueForExpression(statement->getExpression());
if (value == nullptr)
return;
llvm::AllocaInst *alloca = builder->CreateAlloca(typeForValueType(statement->getValueType(), 0), nullptr, statement->getName());
if (!setAlloca(statement->getName(), alloca))
@@ -244,7 +280,10 @@ void ModuleBuilder::buildMetaExternFunction(shared_ptr<StatementMetaExternFuncti
}
// build function declaration
llvm::FunctionType *funType = llvm::FunctionType::get(typeForValueType(statement->getReturnValueType()), types, false);
llvm::Type *returnType = typeForValueType(statement->getReturnValueType());
if (returnType == nullptr)
return;
llvm::FunctionType *funType = llvm::FunctionType::get(returnType, types, false);
llvm::Function *fun = llvm::Function::Create(funType, llvm::GlobalValue::ExternalLinkage, statement->getName(), module.get());
if (!setFun(statement->getName(), fun))
return;
@@ -270,6 +309,8 @@ llvm::Value *ModuleBuilder::valueForExpression(shared_ptr<Expression> expression
return valueForExpression(dynamic_pointer_cast<ExpressionGrouping>(expression)->getExpression());
case ExpressionKind::BINARY:
return valueForBinary(dynamic_pointer_cast<ExpressionBinary>(expression));
case ExpressionKind::UNARY:
return valueForUnary(dynamic_pointer_cast<ExpressionUnary>(expression));
case ExpressionKind::IF_ELSE:
return valueForIfElse(dynamic_pointer_cast<ExpressionIfElse>(expression));
case ExpressionKind::VAR:
@@ -301,10 +342,16 @@ llvm::Value *ModuleBuilder::valueForLiteral(shared_ptr<ExpressionLiteral> expres
return llvm::UndefValue::get(typeVoid);
case ValueTypeKind::BOOL:
return llvm::ConstantInt::get(typeBool, expression->getBoolValue(), true);
case ValueTypeKind::SINT32:
return llvm::ConstantInt::get(typeSint32, expression->getSint32Value(), true);
case ValueTypeKind::REAL32:
return llvm::ConstantInt::get(typeReal32, expression->getReal32Value(), true);
case ValueTypeKind::U8:
return llvm::ConstantInt::get(typeU8, expression->getU8Value(), true);
case ValueTypeKind::U32:
return llvm::ConstantInt::get(typeU32, expression->getU32Value(), true);
case ValueTypeKind::S8:
return llvm::ConstantInt::get(typeS8, expression->getS8Value(), true);
case ValueTypeKind::S32:
return llvm::ConstantInt::get(typeS32, expression->getS32Value(), true);
case ValueTypeKind::R32:
return llvm::ConstantFP::get(typeR32, expression->getR32Value());
}
}
@@ -331,9 +378,11 @@ llvm::Value *ModuleBuilder::valueForBinary(shared_ptr<ExpressionBinary> expressi
if (type == typeBool) {
return valueForBinaryBool(expression->getOperation(), leftValue, rightValue);
} else if (type == typeSint32 || type == typeVoid) {
return valueForBinaryInteger(expression->getOperation(), leftValue, rightValue);
} else if (type == typeReal32) {
} else if (type == typeU8 || type == typeU32) {
return valueForBinaryUnsignedInteger(expression->getOperation(), leftValue, rightValue);
} else if (type == typeS8 || type == typeS32) {
return valueForBinarySignedInteger(expression->getOperation(), leftValue, rightValue);
} else if (type == typeR32) {
return valueForBinaryReal(expression->getOperation(), leftValue, rightValue);
}
@@ -348,35 +397,62 @@ llvm::Value *ModuleBuilder::valueForBinaryBool(ExpressionBinaryOperation operati
case ExpressionBinaryOperation::NOT_EQUAL:
return builder->CreateICmpNE(leftValue, rightValue);
default:
markError(0, 0, "Unexpecgted operation for boolean operands");
markError(0, 0, "Unexpected operation for boolean operands");
return nullptr;
}
}
llvm::Value *ModuleBuilder::valueForBinaryInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
llvm::Value *ModuleBuilder::valueForBinaryUnsignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
switch (operation) {
case ExpressionBinaryOperation::EQUAL:
return builder->CreateICmpEQ(leftValue, rightValue);
case ExpressionBinaryOperation::NOT_EQUAL:
return builder->CreateICmpNE(leftValue, rightValue);
case ExpressionBinaryOperation::LESS:
return builder->CreateICmpSLT(leftValue, rightValue);
case ExpressionBinaryOperation::LESS_EQUAL:
return builder->CreateICmpSLE(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER:
return builder->CreateICmpSGT(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER_EQUAL:
return builder->CreateICmpSGE(leftValue, rightValue);
case ExpressionBinaryOperation::ADD:
return builder->CreateNSWAdd(leftValue, rightValue);
case ExpressionBinaryOperation::SUB:
return builder->CreateNSWSub(leftValue, rightValue);
case ExpressionBinaryOperation::MUL:
return builder->CreateNSWMul(leftValue, rightValue);
case ExpressionBinaryOperation::DIV:
return builder->CreateSDiv(leftValue, rightValue);
case ExpressionBinaryOperation::MOD:
return builder->CreateSRem(leftValue, rightValue);
case ExpressionBinaryOperation::EQUAL:
return builder->CreateICmpEQ(leftValue, rightValue);
case ExpressionBinaryOperation::NOT_EQUAL:
return builder->CreateICmpNE(leftValue, rightValue);
case ExpressionBinaryOperation::LESS:
return builder->CreateICmpSLT(leftValue, rightValue);
case ExpressionBinaryOperation::LESS_EQUAL:
return builder->CreateICmpSLE(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER:
return builder->CreateICmpSGT(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER_EQUAL:
return builder->CreateICmpSGE(leftValue, rightValue);
case ExpressionBinaryOperation::ADD:
return builder->CreateNUWAdd(leftValue, rightValue);
case ExpressionBinaryOperation::SUB:
return builder->CreateNUWSub(leftValue, rightValue);
case ExpressionBinaryOperation::MUL:
return builder->CreateNUWMul(leftValue, rightValue);
case ExpressionBinaryOperation::DIV:
return builder->CreateUDiv(leftValue, rightValue);
case ExpressionBinaryOperation::MOD:
return builder->CreateURem(leftValue, rightValue);
}
}
llvm::Value *ModuleBuilder::valueForBinarySignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue) {
switch (operation) {
case ExpressionBinaryOperation::EQUAL:
return builder->CreateICmpEQ(leftValue, rightValue);
case ExpressionBinaryOperation::NOT_EQUAL:
return builder->CreateICmpNE(leftValue, rightValue);
case ExpressionBinaryOperation::LESS:
return builder->CreateICmpSLT(leftValue, rightValue);
case ExpressionBinaryOperation::LESS_EQUAL:
return builder->CreateICmpSLE(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER:
return builder->CreateICmpSGT(leftValue, rightValue);
case ExpressionBinaryOperation::GREATER_EQUAL:
return builder->CreateICmpSGE(leftValue, rightValue);
case ExpressionBinaryOperation::ADD:
return builder->CreateNSWAdd(leftValue, rightValue);
case ExpressionBinaryOperation::SUB:
return builder->CreateNSWSub(leftValue, rightValue);
case ExpressionBinaryOperation::MUL:
return builder->CreateNSWMul(leftValue, rightValue);
case ExpressionBinaryOperation::DIV:
return builder->CreateSDiv(leftValue, rightValue);
case ExpressionBinaryOperation::MOD:
return builder->CreateSRem(leftValue, rightValue);
}
}
@@ -407,6 +483,26 @@ llvm::Value *ModuleBuilder::valueForBinaryReal(ExpressionBinaryOperation operati
}
}
llvm::Value *ModuleBuilder::valueForUnary(shared_ptr<ExpressionUnary> expression) {
llvm::Value *value = valueForExpression(expression->getExpression());
llvm::Type *type = value->getType();
// do nothing for plus
if (expression->getOperation() == ExpressionUnaryOperation::PLUS)
return value;
if (type == typeU8 || type == typeU32) {
return builder->CreateNeg(value);
} else if (type == typeS8 || type == typeS32) {
return builder->CreateNSWNeg(value);
} else if (type == typeR32) {
return builder->CreateFNeg(value);
}
markError(0, 0, "Unexpected operation");
return nullptr;
}
llvm::Value *ModuleBuilder::valueForIfElse(shared_ptr<ExpressionIfElse> expression) {
shared_ptr<Expression> conditionExpression = expression->getCondition();
@@ -481,15 +577,28 @@ llvm::Value *ModuleBuilder::valueForVar(shared_ptr<ExpressionVariable> expressio
llvm::Value *ModuleBuilder::valueForCall(shared_ptr<ExpressionCall> expression) {
llvm::Function *fun = getFun(expression->getName());
if (fun == nullptr)
return nullptr;
llvm::FunctionType *funType = fun->getFunctionType();
vector<llvm::Value*> argValues;
for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) {
llvm::Value *argValue = valueForExpression(argumentExpression);
argValues.push_back(argValue);
if (fun != nullptr) {
llvm::FunctionType *funType = fun->getFunctionType();
vector<llvm::Value*> argValues;
for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) {
llvm::Value *argValue = valueForExpression(argumentExpression);
argValues.push_back(argValue);
}
return builder->CreateCall(funType, fun, llvm::ArrayRef(argValues));
}
return builder->CreateCall(funType, fun, llvm::ArrayRef(argValues));
llvm::InlineAsm *rawFun = getRawFun(expression->getName());
if (rawFun != nullptr) {
vector<llvm::Value *>argValues;
for (shared_ptr<Expression> &argumentExpression : expression->getArgumentExpressions()) {
llvm::Value *argValue = valueForExpression(argumentExpression);
argValues.push_back(argValue);
}
return builder->CreateCall(rawFun, llvm::ArrayRef(argValues));
}
markError(0, 0, format("Function \"{}\" not defined in scope", expression->getName()));
return nullptr;
}
bool ModuleBuilder::setAlloca(string name, llvm::AllocaInst *alloca) {
@@ -518,7 +627,7 @@ llvm::AllocaInst* ModuleBuilder::getAlloca(string name) {
bool ModuleBuilder::setFun(string name, llvm::Function *fun) {
if (scopes.top().funMap[name] != nullptr) {
markError(0, 0, format("Function \"{}\" already defined", name));
markError(0, 0, format("Function \"{}\" already defined in scope", name));
return false;
}
@@ -536,27 +645,59 @@ llvm::Function* ModuleBuilder::getFun(string name) {
scopes.pop();
}
markError(0, 0, format("Function \"{}\" not defined in scope", name));
return nullptr;
}
bool ModuleBuilder::setRawFun(string name, llvm::InlineAsm *rawFun) {
if (scopes.top().rawFunMap[name] != nullptr) {
markError(0, 0, format("Raw function \"{}\" already defined in scope", name));
return false;
}
scopes.top().rawFunMap[name] = rawFun;
return true;
}
llvm::InlineAsm *ModuleBuilder::getRawFun(string name) {
stack<Scope> scopes = this->scopes;
while (!scopes.empty()) {
llvm::InlineAsm *rawFun = scopes.top().rawFunMap[name];
if (rawFun != nullptr)
return rawFun;
scopes.pop();
}
return nullptr;
}
llvm::Type *ModuleBuilder::typeForValueType(shared_ptr<ValueType> valueType, int count) {
if (valueType == nullptr) {
markError(0, 0, "Missing type");
return nullptr;
}
switch (valueType->getKind()) {
case ValueTypeKind::NONE:
return typeVoid;
case ValueTypeKind::BOOL:
return typeBool;
case ValueTypeKind::SINT32:
return typeSint32;
case ValueTypeKind::REAL32:
return typeReal32;
case ValueTypeKind::U8:
return typeU8;
case ValueTypeKind::U32:
return typeU32;
case ValueTypeKind::S8:
return typeS8;
case ValueTypeKind::S32:
return typeS32;
case ValueTypeKind::R32:
return typeR32;
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

@@ -10,6 +10,7 @@
#include <llvm/IR/Constants.h>
#include <llvm/Support/raw_ostream.h>
#include <llvm/IR/Verifier.h>
#include <llvm/IR/InlineAsm.h>
class Error;
class ValueType;
@@ -22,10 +23,12 @@ class ExpressionVariable;
class ExpressionCall;
class ExpressionIfElse;
class ExpressionBinary;
class ExpressionUnary;
enum class ExpressionBinaryOperation;
class Statement;
class StatementFunction;
class StatementRawFunction;
class StatementVariable;
class StatementAssignment;
class StatementReturn;
@@ -39,6 +42,7 @@ using namespace std;
typedef struct {
map<string, llvm::AllocaInst*> allocaMap;
map<string, llvm::Function*> funMap;
map<string, llvm::InlineAsm*> rawFunMap;
} Scope;
class ModuleBuilder {
@@ -53,14 +57,18 @@ private:
llvm::Type *typeVoid;
llvm::Type *typeBool;
llvm::IntegerType *typeSint32;
llvm::Type *typeReal32;
llvm::IntegerType *typeU8;
llvm::IntegerType *typeU32;
llvm::IntegerType *typeS8;
llvm::IntegerType *typeS32;
llvm::Type *typeR32;
vector<shared_ptr<Statement>> statements;
stack<Scope> scopes;
void buildStatement(shared_ptr<Statement> statement);
void buildFunctionDeclaration(shared_ptr<StatementFunction> statement);
void buildFunction(shared_ptr<StatementFunction> statement);
void buildRawFunction(shared_ptr<StatementRawFunction> statement);
void buildVarDeclaration(shared_ptr<StatementVariable> statement);
void buildAssignment(shared_ptr<StatementAssignment> statement);
void buildBlock(shared_ptr<StatementBlock> statement);
@@ -76,8 +84,10 @@ private:
llvm::Value *valueForGrouping(shared_ptr<ExpressionGrouping> expression);
llvm::Value *valueForBinary(shared_ptr<ExpressionBinary> expression);
llvm::Value *valueForBinaryBool(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
llvm::Value *valueForBinaryInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
llvm::Value *valueForBinaryUnsignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
llvm::Value *valueForBinarySignedInteger(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
llvm::Value *valueForBinaryReal(ExpressionBinaryOperation operation, llvm::Value *leftValue, llvm::Value *rightValue);
llvm::Value *valueForUnary(shared_ptr<ExpressionUnary> expression);
llvm::Value *valueForIfElse(shared_ptr<ExpressionIfElse> expression);
llvm::Value *valueForVar(shared_ptr<ExpressionVariable> expression);
llvm::Value *valueForCall(shared_ptr<ExpressionCall> expression);
@@ -88,6 +98,9 @@ private:
bool setFun(string name, llvm::Function *fun);
llvm::Function *getFun(string name);
bool setRawFun(string name, llvm::InlineAsm *rawFun);
llvm::InlineAsm *getRawFun(string name);
llvm::Type *typeForValueType(shared_ptr<ValueType> valueType, int count = 0);
void markError(int line, int column, string message);

View File

@@ -12,6 +12,8 @@ vector<shared_ptr<Token>> Lexer::getTokens() {
currentIndex = 0;
currentLine = 0;
currentColumn = 0;
foundRawSourceStart = false;
isParsingRawSource = false;
tokens.clear();
errors.clear();
@@ -117,6 +119,11 @@ shared_ptr<Token> Lexer::nextToken() {
return nextToken(); // gets rid of remaining white spaces without repeating the code
}
// raw source
token = matchRawSourceLine();
if (token != nullptr)
return token;
// structural
token = match(TokenKind::LEFT_PAREN, "(", false);
if (token != nullptr)
@@ -212,6 +219,12 @@ shared_ptr<Token> Lexer::nextToken() {
token = match(TokenKind::FUNCTION, "fun", true);
if (token != nullptr)
return token;
token = match(TokenKind::RAW_FUNCTION, "raw", true);
if (token != nullptr) {
foundRawSourceStart = true;
return token;
}
token = match(TokenKind::RETURN, "ret", true);
if (token != nullptr)
@@ -271,8 +284,10 @@ shared_ptr<Token> Lexer::nextToken() {
// new line
token = match(TokenKind::NEW_LINE, "\n", false);
if (token != nullptr)
if (token != nullptr) {
tryStartingRawSourceParsing();
return token;
}
// eof
token = matchEnd();
@@ -430,21 +445,6 @@ shared_ptr<Token> Lexer::matchString() {
return token;
}
shared_ptr<Token> Lexer::matchIdentifier() {
int nextIndex = currentIndex;
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::IDENTIFIER, lexme, currentLine, currentColumn);
advanceWithToken(token);
return token;
}
shared_ptr<Token> Lexer::matchType() {
int nextIndex = currentIndex;
@@ -463,6 +463,52 @@ shared_ptr<Token> Lexer::matchType() {
return token;
}
shared_ptr<Token> Lexer::matchIdentifier() {
int nextIndex = currentIndex;
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::IDENTIFIER, lexme, currentLine, currentColumn);
advanceWithToken(token);
return token;
}
void Lexer::tryStartingRawSourceParsing() {
if (!foundRawSourceStart)
return;
if (!tokens.at(tokens.size() - 1)->isOfKind({TokenKind::COLON, TokenKind::COMMA, TokenKind::RIGHT_ARROW})) {
foundRawSourceStart = false;
isParsingRawSource = true;
}
}
shared_ptr<Token> Lexer::matchRawSourceLine() {
int nextIndex = currentIndex;
if (!isParsingRawSource)
return nullptr;
if (source.at(nextIndex) == ';') {
isParsingRawSource = false;
return nullptr;
}
while (source.at(nextIndex) != '\n')
nextIndex++;
string lexme = source.substr(currentIndex, nextIndex - currentIndex);
shared_ptr<Token> token = make_shared<Token>(TokenKind::RAW_SOURCE_LINE, lexme, currentLine, currentColumn);
advanceWithToken(token);
currentIndex++; // skip newline
return token;
}
shared_ptr<Token> Lexer::matchEnd() {
if (currentIndex >= source.length())
return make_shared<Token>(TokenKind::END, "", currentLine, currentColumn);
@@ -530,11 +576,15 @@ bool Lexer::isSeparator(int index) {
}
void Lexer::advanceWithToken(shared_ptr<Token> token) {
if (token->getKind() == TokenKind::NEW_LINE) {
currentLine++;
currentColumn = 0;
} else {
currentColumn += token->getLexme().length();
switch (token->getKind()) {
case TokenKind::NEW_LINE:
case TokenKind::RAW_SOURCE_LINE:
currentLine++;
currentColumn = 0;
break;
default:
currentColumn += token->getLexme().length();
break;
}
currentIndex += token->getLexme().length();
}

View File

@@ -17,6 +17,8 @@ private:
int currentColumn;
vector<shared_ptr<Token>> tokens;
vector<shared_ptr<Error>> errors;
bool foundRawSourceStart;
bool isParsingRawSource;
shared_ptr<Token> nextToken();
shared_ptr<Token> match(TokenKind kind, string lexme, bool needsSeparator);
@@ -28,6 +30,8 @@ private:
shared_ptr<Token> matchString();
shared_ptr<Token> matchType();
shared_ptr<Token> matchIdentifier();
void tryStartingRawSourceParsing();
shared_ptr<Token> matchRawSourceLine();
shared_ptr<Token> matchEnd();
bool isWhiteSpace(int index);

View File

@@ -4,21 +4,30 @@ vector<TokenKind> Token::tokensEquality = {
TokenKind::EQUAL,
TokenKind::NOT_EQUAL
};
vector<TokenKind> Token::tokensComparison = {
TokenKind::LESS,
TokenKind::LESS_EQUAL,
TokenKind::GREATER,
TokenKind::GREATER_EQUAL
};
vector<TokenKind> Token::tokensTerm = {
TokenKind::PLUS,
TokenKind::MINUS
};
vector<TokenKind> Token::tokensFactor = {
TokenKind::STAR,
TokenKind::SLASH,
TokenKind::PERCENT
};
vector<TokenKind> Token::tokensUnary = {
TokenKind::PLUS,
TokenKind::MINUS
};
vector<TokenKind> Token::tokensBinary = {
TokenKind::EQUAL,
TokenKind::NOT_EQUAL,
@@ -35,6 +44,7 @@ vector<TokenKind> Token::tokensBinary = {
TokenKind::SLASH,
TokenKind::PERCENT
};
vector<TokenKind> Token::tokensLiteral = {
TokenKind::BOOL,
TokenKind::INTEGER_DEC,

View File

@@ -30,6 +30,8 @@ enum class TokenKind {
RIGHT_ARROW,
FUNCTION,
RAW_FUNCTION,
RAW_SOURCE_LINE,
RETURN,
REPEAT,
IF,
@@ -63,6 +65,7 @@ public:
static vector<TokenKind> tokensComparison;
static vector<TokenKind> tokensTerm;
static vector<TokenKind> tokensFactor;
static vector<TokenKind> tokensUnary;
static vector<TokenKind> tokensBinary;
static vector<TokenKind> tokensLiteral;

View File

@@ -11,6 +11,7 @@
#include "Parser/Statement/StatementMetaExternFunction.h"
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementRawFunction.h"
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
@@ -19,6 +20,7 @@
#include "Parser/Expression/Expression.h"
#include "Parser/Expression/ExpressionBinary.h"
#include "Parser/Expression/ExpressionUnary.h"
#include "Parser/Expression/ExpressionIfElse.h"
#include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionGrouping.h"
@@ -97,6 +99,10 @@ string Logger::toString(shared_ptr<Token> token) {
return "ELSE";
case TokenKind::FUNCTION:
return "FUN";
case TokenKind::RAW_FUNCTION:
return "RAW";
case TokenKind::RAW_SOURCE_LINE:
return format("RAW_SOURCE_LINE({})", token->getLexme());
case TokenKind::RETURN:
return "RET";
case TokenKind::REPEAT:
@@ -179,6 +185,8 @@ string Logger::toString(TokenKind tokenKind) {
return "ELSE";
case TokenKind::FUNCTION:
return "FUN";
case TokenKind::RAW_FUNCTION:
return "RAW";
case TokenKind::RETURN:
return "RET";
case TokenKind::REPEAT:
@@ -195,15 +203,24 @@ string Logger::toString(TokenKind tokenKind) {
}
string Logger::toString(shared_ptr<ValueType> valueType) {
if (valueType == nullptr)
return "{INVALID}";
switch (valueType->getKind()) {
case ValueTypeKind::NONE:
return "NONE";
case ValueTypeKind::BOOL:
return "BOOL";
case ValueTypeKind::SINT32:
return "SINT32";
case ValueTypeKind::REAL32:
return "REAL32";
case ValueTypeKind::U8:
return "U8";
case ValueTypeKind::U32:
return "U32";
case ValueTypeKind::S8:
return "S8";
case ValueTypeKind::S32:
return "S32";
case ValueTypeKind::R32:
return "R32";
case ValueTypeKind::DATA:
return "[]";
}
@@ -217,6 +234,8 @@ string Logger::toString(shared_ptr<Statement> statement) {
return toString(dynamic_pointer_cast<StatementVariable>(statement));
case StatementKind::FUNCTION:
return toString(dynamic_pointer_cast<StatementFunction>(statement));
case StatementKind::RAW_FUNCTION:
return toString(dynamic_pointer_cast<StatementRawFunction>(statement));
case StatementKind::BLOCK:
return toString(dynamic_pointer_cast<StatementBlock>(statement));
case StatementKind::ASSIGNMENT:
@@ -262,6 +281,21 @@ string Logger::toString(shared_ptr<StatementFunction> statement) {
return text;
}
string Logger::toString(shared_ptr<StatementRawFunction> 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("RAW(\"{}\"|{}|{}):\n", statement->getName(), argsString, toString(statement->getReturnValueType()));
text += statement->getRawSource();
return text;
}
string Logger::toString(shared_ptr<StatementBlock> statement) {
string text;
@@ -314,7 +348,9 @@ string Logger::toString(shared_ptr<StatementExpression> statement) {
string Logger::toString(shared_ptr<Expression> expression) {
switch (expression->getKind()) {
case ExpressionKind::BINARY:
return toString(dynamic_pointer_cast<ExpressionBinary>(expression));
return toString(dynamic_pointer_cast<ExpressionBinary>(expression));
case ExpressionKind::UNARY:
return toString(dynamic_pointer_cast<ExpressionUnary>(expression));
case ExpressionKind::IF_ELSE:
return toString(dynamic_pointer_cast<ExpressionIfElse>(expression));
case ExpressionKind::VAR:
@@ -361,6 +397,17 @@ string Logger::toString(shared_ptr<ExpressionBinary> expression) {
}
}
string Logger::toString(shared_ptr<ExpressionUnary> expression) {
switch (expression->getOperation()) {
case ExpressionUnaryOperation::PLUS:
return "+" + toString(expression->getExpression());
case ExpressionUnaryOperation::MINUS:
return "-" + toString(expression->getExpression());
case ExpressionUnaryOperation::INVALID:
return "{INVALID}";
}
}
string Logger::toString(shared_ptr<ExpressionIfElse> expression) {
string text;
@@ -396,10 +443,16 @@ string Logger::toString(shared_ptr<ExpressionLiteral> expression) {
return "NONE";
case ValueTypeKind::BOOL:
return expression->getBoolValue() ? "true" : "false";
case ValueTypeKind::SINT32:
return to_string(expression->getSint32Value());
case ValueTypeKind::REAL32:
return to_string(expression->getReal32Value());
case ValueTypeKind::U8:
return to_string(expression->getU8Value());
case ValueTypeKind::U32:
return to_string(expression->getU32Value());
case ValueTypeKind::S8:
return to_string(expression->getS8Value());
case ValueTypeKind::S32:
return to_string(expression->getS32Value());
case ValueTypeKind::R32:
return to_string(expression->getR32Value());
default:
return "?";
}
@@ -458,7 +511,7 @@ void Logger::print(shared_ptr<Error> error) {
switch (error->getKind()) {
case ErrorKind::LEXER_ERROR: {
string lexme = error->getLexme() ? *(error->getLexme()) : "";
message = format("Unexpected token \"{}\" at line: {}, column: {}", lexme, error->getLine() + 1, error->getColumn() + 1);
message = format("At line {}, column {}: Unexpected token \"{}\"", error->getLine() + 1, error->getColumn() + 1, lexme);
break;
}
case ErrorKind::PARSER_ERROR: {
@@ -468,13 +521,13 @@ void Logger::print(shared_ptr<Error> error) {
if (expectedTokenKind) {
message = format(
"Expected token {} but instead found \"{}\" at line: {}, column: {}",
toString(*expectedTokenKind), token->getLexme(), token->getLine() + 1, token->getColumn() + 1
"At line {}, column {}: Expected token {} but found {} instead",
token->getLine() + 1, token->getColumn() + 1, toString(*expectedTokenKind), toString(token)
);
} else {
message = format(
"Unexpected token \"{}\" found at line: {}, column: {}",
token->getLexme(), token->getLine() + 1, token->getColumn() + 1
"At line {}, column {}: Unexpected token \"{}\" found",
token->getLine() + 1, token->getColumn() + 1, toString(token)
);
}
if (errorMessage)
@@ -483,7 +536,7 @@ void Logger::print(shared_ptr<Error> error) {
}
case ErrorKind::BUILDER_ERROR: {
string errorMessage = error->getMessage() ? *(error->getMessage()) : "";
message = format("Error at line {}, column {}: {}", error->getLine(), error->getColumn(), errorMessage);
message = format("At line {}, column {}: {}", error->getLine(), error->getColumn(), errorMessage);
break;
}
}

View File

@@ -11,6 +11,7 @@ class Statement;
class StatementMetaExternFunction;
class StatementVariable;
class StatementFunction;
class StatementRawFunction;
class StatementBlock;
class StatementAssignment;
class StatementReturn;
@@ -19,6 +20,7 @@ class StatementExpression;
class Expression;
class ExpressionBinary;
class ExpressionUnary;
class ExpressionIfElse;
class ExpressionVariable;
class ExpressionGrouping;
@@ -41,6 +43,7 @@ private:
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<StatementRawFunction> statement);
static string toString(shared_ptr<StatementBlock> statement);
static string toString(shared_ptr<StatementAssignment> statement);
static string toString(shared_ptr<StatementReturn> statement);
@@ -49,6 +52,7 @@ private:
static string toString(shared_ptr<Expression> expression);
static string toString(shared_ptr<ExpressionBinary> expression);
static string toString(shared_ptr<ExpressionUnary> expression);
static string toString(shared_ptr<ExpressionIfElse> expression);
static string toString(shared_ptr<ExpressionVariable> expression);
static string toString(shared_ptr<ExpressionGrouping> expression);

View File

@@ -12,6 +12,7 @@ enum class ExpressionKind {
LITERAL,
ARRAY_LITERAL,
GROUPING,
UNARY,
BINARY,
IF_ELSE,
VAR,

View File

@@ -1,4 +1,7 @@
#include "Parser/Expression/Expression.h"
#ifndef EXPRESSION_BINARY_H
#define EXPRESSION_BINARY_H
#include "Expression.h"
enum class ExpressionBinaryOperation {
EQUAL,
@@ -26,4 +29,6 @@ public:
ExpressionBinaryOperation getOperation();
shared_ptr<Expression> getLeft();
shared_ptr<Expression> getRight();
};
};
#endif

View File

@@ -15,14 +15,14 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
case TokenKind::INTEGER_DEC: {
string numString = token->getLexme();
erase(numString, '_');
expression->sint32Value = stoi(numString, nullptr, 10);
expression->s32Value = stoi(numString, nullptr, 10);
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break;
}
case TokenKind::INTEGER_HEX: {
string numString = token->getLexme();
erase(numString, '_');
expression->sint32Value = stoi(numString, nullptr, 16);
expression->u32Value = stoul(numString, nullptr, 16);
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break;
}
@@ -30,7 +30,7 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
string numString = token->getLexme();
erase(numString, '_');
numString = numString.substr(2, numString.size()-1);
expression->sint32Value = stoi(numString, nullptr, 2);
expression->u32Value = stoul(numString, nullptr, 2);
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break;
}
@@ -41,13 +41,14 @@ shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(share
return nullptr;
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
expression->sint32Value = *charValue;
expression->u32Value = *charValue;
return expression;
}
case TokenKind::REAL:
expression->real32Value = stof(token->getLexme());
case TokenKind::REAL: {
expression->r32Value = stof(token->getLexme());
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
break;
}
default:
return nullptr;
}
@@ -62,10 +63,22 @@ bool ExpressionLiteral::getBoolValue() {
return boolValue;
}
int32_t ExpressionLiteral::getSint32Value() {
return sint32Value;
uint8_t ExpressionLiteral::getU8Value() {
return u8Value;
}
float ExpressionLiteral::getReal32Value() {
return real32Value;
uint32_t ExpressionLiteral::getU32Value() {
return u32Value;
}
int8_t ExpressionLiteral::getS8Value() {
return s8Value;
}
int32_t ExpressionLiteral::getS32Value() {
return s32Value;
}
float ExpressionLiteral::getR32Value() {
return r32Value;
}

View File

@@ -6,16 +6,22 @@
class ExpressionLiteral: public Expression {
private:
bool boolValue;
int32_t sint32Value;
float real32Value;
uint8_t u8Value;
uint32_t u32Value;
int8_t s8Value;
int32_t s32Value;
float r32Value;
public:
static shared_ptr<ExpressionLiteral> expressionLiteralForToken(shared_ptr<Token> token);
ExpressionLiteral();
bool getBoolValue();
int32_t getSint32Value();
float getReal32Value();
uint8_t getU8Value();
uint32_t getU32Value();
int8_t getS8Value();
int32_t getS32Value();
float getR32Value();
};
#endif

View File

@@ -0,0 +1,29 @@
#include "ExpressionUnary.h"
#include "Lexer/Token.h"
ExpressionUnary::ExpressionUnary(shared_ptr<Token> token, shared_ptr<Expression> expression):
Expression(ExpressionKind::UNARY, nullptr), expression(expression) {
switch (token->getKind()) {
case TokenKind::PLUS:
operation = ExpressionUnaryOperation::PLUS;
valueType = expression->getValueType();
break;
case TokenKind::MINUS:
operation = ExpressionUnaryOperation::MINUS;
valueType = expression->getValueType();
break;
default:
operation = ExpressionUnaryOperation::INVALID;
valueType = nullptr;
break;
}
}
ExpressionUnaryOperation ExpressionUnary::getOperation() {
return operation;
}
shared_ptr<Expression> ExpressionUnary::getExpression() {
return expression;
}

View File

@@ -0,0 +1,23 @@
#ifndef EXPRESSION_UNARY_H
#define EXPRESSION_UNARY_H
#include "Expression.h"
enum class ExpressionUnaryOperation {
PLUS,
MINUS,
INVALID
};
class ExpressionUnary: public Expression {
private:
ExpressionUnaryOperation operation;
shared_ptr<Expression> expression;
public:
ExpressionUnary(shared_ptr<Token> token, shared_ptr<Expression> expression);
ExpressionUnaryOperation getOperation();
shared_ptr<Expression> getExpression();
};
#endif

View File

@@ -0,0 +1,44 @@
#include "Parsee.h"
Parsee Parsee::tokenParsee(TokenKind tokenKind, bool isRequired, bool shouldReturn) {
Parsee parsee;
parsee.kind = ParseeKind::TOKEN;
parsee.tokenKind = tokenKind;
parsee.isRequired = isRequired;
parsee.shouldReturn = shouldReturn;
return parsee;
}
Parsee Parsee::valueTypeParsee(bool isRequired) {
Parsee parsee;
parsee.kind = ParseeKind::VALUE_TYPE;
parsee.isRequired = isRequired;
parsee.shouldReturn = true;
return parsee;
}
Parsee Parsee::expressionParsee(bool isRequired) {
Parsee parsee;
parsee.kind = ParseeKind::EXPRESSION;
parsee.isRequired = isRequired;
parsee.shouldReturn = true;
return parsee;
}
Parsee::Parsee() { }
ParseeKind Parsee::getKind() {
return kind;
}
TokenKind Parsee::getTokenKind() {
return tokenKind;
}
bool Parsee::getIsRequired() {
return isRequired;
}
bool Parsee::getShouldReturn() {
return shouldReturn;
}

View File

@@ -0,0 +1,33 @@
#ifndef PARSEE_H
#define PARSEE_H
#include <memory>
enum class TokenKind;
enum class ParseeKind {
TOKEN,
VALUE_TYPE,
EXPRESSION
};
class Parsee {
private:
ParseeKind kind;
TokenKind tokenKind;
bool isRequired;
bool shouldReturn;
Parsee();
public:
static Parsee tokenParsee(TokenKind tokenKind, bool isRequired, bool shouldReturn);
static Parsee valueTypeParsee(bool isRequired);
static Parsee expressionParsee(bool isRequired);
ParseeKind getKind();
TokenKind getTokenKind();
bool getIsRequired();
bool getShouldReturn();
};
#endif

View File

@@ -0,0 +1,20 @@
#include "ParseeGroup.h"
#include "Parsee.h"
ParseeGroup::ParseeGroup(vector<Parsee> parsees, optional<ParseeGroup> repeatedGroup):
parsees(parsees) {
if (repeatedGroup) {
this->repeatedGroup = *repeatedGroup;
} else {
this->repeatedGroup = {};
}
}
vector<Parsee> ParseeGroup::getParsees() {
return parsees;
}
optional<reference_wrapper<ParseeGroup>> ParseeGroup::getRepeatedGroup() {
return repeatedGroup;
}

View File

@@ -0,0 +1,22 @@
#ifndef PARSEE_GROUP_H
#define PARSEE_GROUP_H
#include <vector>
#include <optional>
class Parsee;
using namespace std;
class ParseeGroup {
private:
vector<Parsee> parsees;
optional<reference_wrapper<ParseeGroup>> repeatedGroup;
public:
ParseeGroup(vector<Parsee> parsees, optional<ParseeGroup> repeatedGroup);
vector<Parsee> getParsees();
optional<reference_wrapper<ParseeGroup>> getRepeatedGroup();
};
#endif

View File

@@ -0,0 +1,51 @@
#include "ParseeResult.h"
#include "Lexer/Token.h"
#include "Parser/ValueType.h"
ParseeResult ParseeResult::tokenResult(shared_ptr<Token> token) {
ParseeResult parseeResult;
parseeResult.kind = ParseeResultKind::TOKEN;
parseeResult.token = token;
parseeResult.tokensCount = 1;
return parseeResult;
}
ParseeResult ParseeResult::valueTypeResult(shared_ptr<ValueType> valueType, int tokensCount) {
ParseeResult parseeResult;
parseeResult.kind = ParseeResultKind::VALUE_TYPE;
parseeResult.valueType = valueType;
parseeResult.tokensCount = tokensCount;
return parseeResult;
}
ParseeResult ParseeResult::expressionResult(shared_ptr<Expression> expression, int tokensCount) {
ParseeResult result;
result.kind = ParseeResultKind::EXPRESSION;
result.expression = expression;
result.tokensCount = tokensCount;
return result;
}
ParseeResult::ParseeResult() { }
ParseeResultKind ParseeResult::getKind() {
return kind;
}
shared_ptr<Token> ParseeResult::getToken() {
return token;
}
shared_ptr<ValueType> ParseeResult::getValueType() {
return valueType;
}
shared_ptr<Expression> ParseeResult::getExpression() {
return expression;
}
int ParseeResult::getTokensCount() {
return tokensCount;
}

View File

@@ -0,0 +1,39 @@
#ifndef PARSEE_RESULT_H
#define PARSEE_RESULT_H
#include <memory>
class Token;
class ValueType;
class Expression;
using namespace std;
enum class ParseeResultKind {
TOKEN,
VALUE_TYPE,
EXPRESSION
};
class ParseeResult {
private:
ParseeResultKind kind;
shared_ptr<Token> token;
shared_ptr<ValueType> valueType;
shared_ptr<Expression> expression;
int tokensCount;
ParseeResult();
public:
static ParseeResult tokenResult(shared_ptr<Token> token);
static ParseeResult valueTypeResult(shared_ptr<ValueType> valueType, int tokensCount);
static ParseeResult expressionResult(shared_ptr<Expression> expression, int tokensCount);
ParseeResultKind getKind();
shared_ptr<Token> getToken();
shared_ptr<ValueType> getValueType();
shared_ptr<Expression> getExpression();
int getTokensCount();
};
#endif

View File

@@ -0,0 +1,30 @@
#include "ParseeResultsGroup.h"
#include "ParseeResult.h"
ParseeResultsGroup ParseeResultsGroup::success(vector<ParseeResult> results) {
ParseeResultsGroup resultsGroup;
resultsGroup.kind = ParseeResultsGroupKind::SUCCESS;
resultsGroup.results = results;
return resultsGroup;
}
ParseeResultsGroup ParseeResultsGroup::noMatch() {
ParseeResultsGroup resultsGroup;
resultsGroup.kind = ParseeResultsGroupKind::NO_MATCH;
return resultsGroup;
}
ParseeResultsGroup ParseeResultsGroup::failure() {
ParseeResultsGroup resultsGroup;
resultsGroup.kind = ParseeResultsGroupKind::FAILURE;
return resultsGroup;
}
ParseeResultsGroupKind ParseeResultsGroup::getKind() {
return kind;
}
vector<ParseeResult> ParseeResultsGroup::getResults() {
return results;
}

View File

@@ -0,0 +1,30 @@
#ifndef PARSEE_RESULTS_GROUP_H
#define PARSEE_RESULTS_GROUP_H
#include <vector>
class ParseeResult;
using namespace std;
enum class ParseeResultsGroupKind {
SUCCESS,
NO_MATCH,
FAILURE
};
class ParseeResultsGroup {
private:
ParseeResultsGroupKind kind;
vector<ParseeResult> results;
public:
static ParseeResultsGroup success(vector<ParseeResult> results);
static ParseeResultsGroup noMatch();
static ParseeResultsGroup failure();
ParseeResultsGroupKind getKind();
vector<ParseeResult> getResults();
};
#endif

View File

@@ -12,10 +12,12 @@
#include "Parser/Expression/ExpressionVariable.h"
#include "Parser/Expression/ExpressionCall.h"
#include "Parser/Expression/ExpressionIfElse.h"
#include "Parser/Expression/ExpressionUnary.h"
#include "Parser/Expression/ExpressionBinary.h"
#include "Parser/Expression/ExpressionBlock.h"
#include "Parser/Statement/StatementFunction.h"
#include "Parser/Statement/StatementRawFunction.h"
#include "Parser/Statement/StatementVariable.h"
#include "Parser/Statement/StatementAssignment.h"
#include "Parser/Statement/StatementReturn.h"
@@ -24,6 +26,11 @@
#include "Parser/Statement/StatementBlock.h"
#include "Parser/Statement/StatementRepeat.h"
#include "Parsee/Parsee.h"
#include "Parsee/ParseeGroup.h"
#include "Parsee/ParseeResult.h"
#include "Parsee/ParseeResultsGroup.h"
Parser::Parser(vector<shared_ptr<Token>> tokens) :
tokens(tokens) { }
@@ -61,6 +68,10 @@ shared_ptr<Statement> Parser::nextStatement() {
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementRawFunction();
if (statement != nullptr || errors.size() > errorsCount)
return statement;
statement = matchStatementVariable();
if (statement != nullptr || errors.size() > errorsCount)
return statement;
@@ -102,112 +113,207 @@ shared_ptr<Statement> Parser::nextInBlockStatement() {
}
shared_ptr<Statement> Parser::matchStatementMetaExternFunction() {
if (!tryMatchingTokenKinds({TokenKind::M_EXTERN, TokenKind::IDENTIFIER, TokenKind::FUNCTION}, true, false))
return nullptr;
ParseeResultsGroup resultsGroup;
string name;
string identifier;
vector<pair<string, shared_ptr<ValueType>>> arguments;
shared_ptr<ValueType> returnType = ValueType::NONE;
currentIndex++; // skip meta
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
currentIndex++; // skip fun
// identifier
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::M_EXTERN, true, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::tokenParsee(TokenKind::FUNCTION, true, false)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
identifier = resultsGroup.getResults().at(0).getToken()->getLexme();
break;
case ParseeResultsGroupKind::NO_MATCH:
case ParseeResultsGroupKind::FAILURE:
return nullptr;
}
// arguments
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false)) {
markError({}, "Expected function argument");
return nullptr;
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COLON, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COMMA, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
{}
)
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
for (int i=0; i<resultsGroup.getResults().size(); i+=2) {
pair<string, shared_ptr<ValueType>> arg;
arg.first = resultsGroup.getResults().at(i).getToken()->getLexme();
arg.second = resultsGroup.getResults().at(i+1).getValueType();
arguments.push_back(arg);
}
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
//shared_ptr<Token> argumentTypeToken = tokens.at(currentIndex++);
shared_ptr<ValueType> argumentType = matchValueType();
if (argumentType == nullptr) {
markError(TokenKind::TYPE, {});
return nullptr;
}
arguments.push_back(pair<string, shared_ptr<ValueType>>(identifierToken->getLexme(), argumentType));
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
}
// Return type
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
//shared_ptr<Token> returnTypeToken = tokens.at(currentIndex);
returnType = matchValueType();
if (returnType == nullptr) {
markError(TokenKind::TYPE, {});
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
return nullptr;
}
}
return make_shared<StatementMetaExternFunction>(identifierToken->getLexme(), arguments, returnType);
// return type
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::RIGHT_ARROW, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::valueTypeParsee(true)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
returnType = resultsGroup.getResults().at(0).getValueType();
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
return nullptr;
}
return make_shared<StatementMetaExternFunction>(identifier, arguments, returnType);
}
shared_ptr<Statement> Parser::matchStatementVariable() {
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false))
ParseeResultsGroup resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true),
Parsee::tokenParsee(TokenKind::LEFT_ARROW, true, false),
Parsee::expressionParsee(true)
},
{}
)
);
if (resultsGroup.getKind() != ParseeResultsGroupKind::SUCCESS)
return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<ValueType> valueType = matchValueType();
string identifier = resultsGroup.getResults().at(0).getToken()->getLexme();
shared_ptr<ValueType> valueType = resultsGroup.getResults().at(1).getValueType();
shared_ptr<Expression> expression = resultsGroup.getResults().at(2).getExpression();
// Expect left arrow
if (!tryMatchingTokenKinds({TokenKind::LEFT_ARROW}, true, true)) {
markError(TokenKind::LEFT_ARROW, {});
return nullptr;
}
shared_ptr<Expression> expression = nextExpression();
if (expression == nullptr)
return nullptr;
return make_shared<StatementVariable>(identifierToken->getLexme(), valueType, expression);
return make_shared<StatementVariable>(identifier, valueType, expression);
}
shared_ptr<Statement> Parser::matchStatementFunction() {
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::FUNCTION}, true, false))
return nullptr;
bool hasError = false;
ParseeResultsGroup resultsGroup;
string name;
vector<pair<string, shared_ptr<ValueType>>> arguments;
shared_ptr<ValueType> returnType = ValueType::NONE;
shared_ptr<Statement> statementBlock;
// name
name = tokens.at(currentIndex++)->getLexme();
currentIndex++; // skip fun
// identifier
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::tokenParsee(TokenKind::FUNCTION, true, false)
},
{}
)
);
// arguments
if (tryMatchingTokenKinds({TokenKind::COLON}, true, true)) {
do {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER, TokenKind::TYPE}, true, false)) {
markError({}, "Expected function argument");
return nullptr;
}
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
shared_ptr<ValueType> argumentType = matchValueType();
if (argumentType == nullptr) {
markError(TokenKind::TYPE, {});
return nullptr;
}
arguments.push_back(pair<string, shared_ptr<ValueType>>(identifierToken->getLexme(), argumentType));
} while (tryMatchingTokenKinds({TokenKind::COMMA}, true, true));
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
name = resultsGroup.getResults().at(0).getToken()->getLexme();
break;
case ParseeResultsGroupKind::NO_MATCH:
return nullptr;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
// return type
if (tryMatchingTokenKinds({TokenKind::RIGHT_ARROW}, true, true)) {
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true); // skip new line
// arguments
if (!hasError) {
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COLON, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COMMA, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
{}
)
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
for (int i=0; i<resultsGroup.getResults().size(); i+=2) {
pair<string, shared_ptr<ValueType>> arg;
arg.first = resultsGroup.getResults().at(i).getToken()->getLexme();
arg.second = resultsGroup.getResults().at(i+1).getValueType();
arguments.push_back(arg);
}
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
}
returnType = matchValueType();
if (returnType == nullptr) {
markError(TokenKind::TYPE, {});
return nullptr;
// return type
if (!hasError) {
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::RIGHT_ARROW, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::valueTypeParsee(true)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
returnType = resultsGroup.getResults().at(0).getValueType();
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
}
@@ -218,10 +324,11 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
}
// block
statementBlock = matchStatementBlock({TokenKind::SEMICOLON});
statementBlock = matchStatementBlock({TokenKind::SEMICOLON, TokenKind::END});
if (statementBlock == nullptr)
return nullptr;
// closing semicolon
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) {
markError(TokenKind::SEMICOLON, {});
return nullptr;
@@ -230,6 +337,155 @@ shared_ptr<Statement> Parser::matchStatementFunction() {
return make_shared<StatementFunction>(name, arguments, returnType, dynamic_pointer_cast<StatementBlock>(statementBlock));
}
shared_ptr<Statement> Parser::matchStatementRawFunction() {
bool hasError = false;
ParseeResultsGroup resultsGroup;
string name;
string constraints;
vector<pair<string, shared_ptr<ValueType>>> arguments;
shared_ptr<ValueType> returnType = ValueType::NONE;
string rawSource;
// identifier
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::tokenParsee(TokenKind::RAW_FUNCTION, true, false)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
name = resultsGroup.getResults().at(0).getToken()->getLexme();
break;
case ParseeResultsGroupKind::NO_MATCH:
return nullptr;
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
// constraints
if (!hasError) {
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::LESS, true, false),
Parsee::tokenParsee(TokenKind::STRING, true, true),
Parsee::tokenParsee(TokenKind::GREATER, true, false)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
constraints = resultsGroup.getResults().at(0).getToken()->getLexme();
// remove enclosing quotes
if (constraints.length() >= 2)
constraints = constraints.substr(1, constraints.length() - 2);
break;
case ParseeResultsGroupKind::NO_MATCH:
return nullptr;
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
}
// arguments
if (!hasError) {
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COLON, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::COMMA, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
Parsee::valueTypeParsee(true)
},
{}
)
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
for (int i=0; i<resultsGroup.getResults().size(); i+=2) {
pair<string, shared_ptr<ValueType>> arg;
arg.first = resultsGroup.getResults().at(i).getToken()->getLexme();
arg.second = resultsGroup.getResults().at(i+1).getValueType();
arguments.push_back(arg);
}
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
}
// return type
if (!hasError) {
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::RIGHT_ARROW, true, false),
Parsee::tokenParsee(TokenKind::NEW_LINE, false, false),
Parsee::valueTypeParsee(true)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
returnType = resultsGroup.getResults().at(0).getValueType();
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
hasError = true;
break;
}
}
// consume new line
if (!tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true)) {
markError(TokenKind::NEW_LINE, {});
return nullptr;
}
// source
while (tryMatchingTokenKinds({TokenKind::RAW_SOURCE_LINE}, true, false)) {
if (!rawSource.empty())
rawSource += "\n";
rawSource += tokens.at(currentIndex++)->getLexme();
// Consume optional new line (for example because of a comment)
tryMatchingTokenKinds({TokenKind::NEW_LINE}, true, true);
}
if(!tryMatchingTokenKinds({TokenKind::SEMICOLON}, false, true)) {
markError(TokenKind::SEMICOLON, {});
return nullptr;
}
return make_shared<StatementRawFunction>(name, constraints, arguments, returnType, rawSource);
}
shared_ptr<Statement> Parser::matchStatementBlock(vector<TokenKind> terminalTokenKinds) {
vector<shared_ptr<Statement>> statements;
@@ -251,44 +507,90 @@ shared_ptr<Statement> Parser::matchStatementBlock(vector<TokenKind> terminalToke
shared_ptr<Statement> Parser::matchStatementAssignment() {
int startIndex = currentIndex;
ParseeResultsGroup resultsGroup;
if (!tryMatchingTokenKinds({TokenKind::IDENTIFIER}, true, false))
return nullptr;
shared_ptr<Token> identifierToken = tokens.at(currentIndex++);
string identifier;
shared_ptr<Expression> indexExpression;
shared_ptr<Expression> expression;
if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
indexExpression = nextExpression();
if (indexExpression == nullptr)
return nullptr;
// identifier
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::IDENTIFIER, true, true),
},
{}
)
);
if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
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();
if (expression == nullptr)
if (resultsGroup.getKind() != ParseeResultsGroupKind::SUCCESS)
return nullptr;
return make_shared<StatementAssignment>(identifierToken->getLexme(), indexExpression, expression);
identifier = resultsGroup.getResults().at(0).getToken()->getLexme();
// index expression
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::LEFT_SQUARE_BRACKET, true, false),
Parsee::expressionParsee(true),
Parsee::tokenParsee(TokenKind::RIGHT_SQUARE_BRACKET, true, false),
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
indexExpression = resultsGroup.getResults().at(0).getExpression();
break;
case ParseeResultsGroupKind::NO_MATCH:
break;
case ParseeResultsGroupKind::FAILURE:
return nullptr;
}
// expression
resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::LEFT_ARROW, true, false),
Parsee::expressionParsee(true)
},
{}
)
);
switch (resultsGroup.getKind()) {
case ParseeResultsGroupKind::SUCCESS:
expression = resultsGroup.getResults().at(0).getExpression();
break;
case ParseeResultsGroupKind::NO_MATCH:
currentIndex = startIndex;
return nullptr;
case ParseeResultsGroupKind::FAILURE:
return nullptr;
}
return make_shared<StatementAssignment>(identifier, indexExpression, expression);
}
shared_ptr<Statement> Parser::matchStatementReturn() {
if (!tryMatchingTokenKinds({TokenKind::RETURN}, true, true))
ParseeResultsGroup resultsGroup = parseeResultsGroupForParseeGroup(
ParseeGroup(
{
Parsee::tokenParsee(TokenKind::RETURN, true, false),
Parsee::expressionParsee(false)
},
{}
)
);
if (resultsGroup.getKind() != ParseeResultsGroupKind::SUCCESS)
return nullptr;
shared_ptr<Expression> expression = nextExpression();
if (expression == nullptr)
return nullptr;
shared_ptr<Expression> expression = !resultsGroup.getResults().empty() ? resultsGroup.getResults().at(0).getExpression() : nullptr;
return make_shared<StatementReturn>(expression);
}
@@ -385,7 +687,6 @@ shared_ptr<Expression> Parser::nextExpression() {
if (expression != nullptr || errors.size() > errorsCount)
return expression;
markError({}, {});
return nullptr;
}
@@ -423,7 +724,7 @@ shared_ptr<Expression> Parser::matchTerm() {
}
shared_ptr<Expression> Parser::matchFactor() {
shared_ptr<Expression> expression = matchPrimary();
shared_ptr<Expression> expression = matchUnary();
if (expression == nullptr)
return nullptr;
@@ -433,6 +734,19 @@ shared_ptr<Expression> Parser::matchFactor() {
return expression;
}
shared_ptr<Expression> Parser::matchUnary() {
shared_ptr<Token> token = tokens.at(currentIndex);
if (tryMatchingTokenKinds(Token::tokensUnary, false, true)) {
shared_ptr<Expression> expression = matchPrimary();
if (expression == nullptr)
return nullptr;
return make_shared<ExpressionUnary>(token, expression);
}
return matchPrimary();
}
shared_ptr<Expression> Parser::matchPrimary() {
shared_ptr<Expression> expression;
int errorsCount = errors.size();
@@ -442,8 +756,8 @@ shared_ptr<Expression> Parser::matchPrimary() {
return expression;
expression = matchExpressionArrayLiteral();
if (expression != nullptr || errors.size() > errorsCount)
return expression;
if (expression != nullptr || errors.size() > errorsCount)
return expression;
expression = matchExpressionLiteral();
if (expression != nullptr || errors.size() > errorsCount)
@@ -621,6 +935,7 @@ shared_ptr<Expression> Parser::matchExpressionBinary(shared_ptr<Expression> left
}
if (right == nullptr) {
markError({}, "Expected expression");
return nullptr;
} else {
return make_shared<ExpressionBinary>(token, left, right);
@@ -651,44 +966,130 @@ shared_ptr<Expression> Parser::matchExpressionBlock(vector<TokenKind> terminalTo
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;
ParseeResultsGroup Parser::parseeResultsGroupForParseeGroup(ParseeGroup group) {
int errorsCount = errors.size();
int startIndex = currentIndex;
vector<ParseeResult> results;
bool mustFulfill = false;
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();
for (Parsee &parsee : group.getParsees()) {
optional<ParseeResult> result;
switch (parsee.getKind()) {
case ParseeKind::TOKEN:
result = tokenParseeResult(currentIndex, parsee.getTokenKind());
break;
case ParseeKind::VALUE_TYPE:
result = valueTypeParseeResult(currentIndex);
break;
case ParseeKind::EXPRESSION:
result = expressionParseeResult(currentIndex);
break;
}
// generated an error?
if (errors.size() > errorsCount)
return ParseeResultsGroup::failure();
if (!tryMatchingTokenKinds({TokenKind::GREATER}, true, true)) {
markError(TokenKind::GREATER, {});
return nullptr;
// if doesn't match on optional group
if (!result && parsee.getIsRequired() && !mustFulfill) {
currentIndex = startIndex;
//return vector<ParseeResult>();
return ParseeResultsGroup::noMatch();
}
// return matching token?
if (result && parsee.getShouldReturn())
results.push_back(*result);
// decide if we're decoding the expected sequence
if (!parsee.getIsRequired() && currentIndex > startIndex)
mustFulfill = true;
// invalid sequence detected?
if (!result && parsee.getIsRequired() && mustFulfill) {
markError(parsee.getTokenKind(), {});
//return {};
return ParseeResultsGroup::failure();
}
// got to the next token if we got a match
if (result)
currentIndex += (*result).getTokensCount();
}
return ValueType::valueTypeForToken(typeToken, subType, valueArg);
if (group.getRepeatedGroup()) {
ParseeResultsGroup subResultsGroup;
do {
subResultsGroup = parseeResultsGroupForParseeGroup(*group.getRepeatedGroup());
if (subResultsGroup.getKind() == ParseeResultsGroupKind::FAILURE)
return ParseeResultsGroup::failure();
for (ParseeResult &subResult : subResultsGroup.getResults())
results.push_back(subResult);
} while (subResultsGroup.getKind() == ParseeResultsGroupKind::SUCCESS);
}
return ParseeResultsGroup::success(results);
}
optional<ParseeResult> Parser::tokenParseeResult(int index, TokenKind tokenKind) {
shared_ptr<Token> token = tokens.at(index);
if (token->isOfKind({tokenKind}))
return ParseeResult::tokenResult(token);
return {};
}
optional<ParseeResult> Parser::valueTypeParseeResult(int index) {
int startIndex = index;
if (!tokens.at(index)->isOfKind({TokenKind::TYPE}))
return {};
shared_ptr<Token> typeToken = tokens.at(index++);
shared_ptr<ValueType> subType;
int typeArg = 0;
if (tokens.at(index)->isOfKind({TokenKind::LESS})) {
index++;
optional<ParseeResult> subResult = valueTypeParseeResult(index);
if (!subResult)
return {};
subType = (*subResult).getValueType();
index += (*subResult).getTokensCount();
if (tokens.at(index)->isOfKind({TokenKind::COMMA})) {
index++;
if (!tokens.at(index)->isOfKind({TokenKind::INTEGER_DEC, TokenKind::INTEGER_HEX, TokenKind::INTEGER_BIN, TokenKind::INTEGER_CHAR}))
return {};
int storedIndex = currentIndex;
currentIndex = index;
shared_ptr<Expression> expressionValue = matchExpressionLiteral();
typeArg = dynamic_pointer_cast<ExpressionLiteral>(expressionValue)->getU32Value();
currentIndex = storedIndex;
index++;
}
if (!tokens.at(index)->isOfKind({TokenKind::GREATER}))
return {};
index++;
}
shared_ptr<ValueType> valueType = ValueType::valueTypeForToken(typeToken, subType, typeArg);
return ParseeResult::valueTypeResult(valueType, index - startIndex);
}
optional<ParseeResult> Parser::expressionParseeResult(int index) {
int startIndex = currentIndex;
int errorsCount = errors.size();
shared_ptr<Expression> expression = nextExpression();
if (errors.size() > errorsCount)
return {};
int tokensCount = currentIndex - startIndex;
currentIndex = startIndex;
return ParseeResult::expressionResult(expression, tokensCount);
}
bool Parser::tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance) {

View File

@@ -12,6 +12,10 @@ class ValueType;
class Expression;
class Statement;
class ParseeGroup;
class ParseeResult;
class ParseeResultsGroup;
using namespace std;
class Parser {
@@ -26,6 +30,7 @@ private:
shared_ptr<Statement> matchStatementMetaExternFunction();
shared_ptr<Statement> matchStatementVariable();
shared_ptr<Statement> matchStatementFunction();
shared_ptr<Statement> matchStatementRawFunction();
shared_ptr<Statement> matchStatementBlock(vector<TokenKind> terminalTokenKinds);
shared_ptr<Statement> matchStatementAssignment();
@@ -38,7 +43,8 @@ private:
shared_ptr<Expression> matchComparison(); // <, <=, >, >=
shared_ptr<Expression> matchTerm(); // +, -
shared_ptr<Expression> matchFactor(); // *, /, %
shared_ptr<Expression> matchPrimary(); // integer, ()
shared_ptr<Expression> matchUnary(); // +, -
shared_ptr<Expression> matchPrimary(); // literal, ()
shared_ptr<Expression> matchExpressionGrouping();
shared_ptr<Expression> matchExpressionLiteral();
@@ -49,8 +55,10 @@ private:
shared_ptr<Expression> matchExpressionBinary(shared_ptr<Expression> left);
shared_ptr<Expression> matchExpressionBlock(vector<TokenKind> terminalTokenKinds);
shared_ptr<ValueType> matchValueType();
ParseeResultsGroup parseeResultsGroupForParseeGroup(ParseeGroup group);
optional<ParseeResult> tokenParseeResult(int index, TokenKind tokenKind);
optional<ParseeResult> valueTypeParseeResult(int index);
optional<ParseeResult> expressionParseeResult(int index);
bool tryMatchingTokenKinds(vector<TokenKind> kinds, bool shouldMatchAll, bool shouldAdvance);
void markError(optional<TokenKind> expectedTokenKind, optional<string> message);

View File

@@ -10,6 +10,7 @@ enum class StatementKind {
BLOCK,
RETURN,
FUNCTION,
RAW_FUNCTION,
VARIABLE,
ASSIGNMENT,
REPEAT,

View File

@@ -0,0 +1,24 @@
#include "StatementRawFunction.h"
StatementRawFunction::StatementRawFunction(string name, string constraints, vector<pair<string, shared_ptr<ValueType>>> arguments, shared_ptr<ValueType> returnValueType, string rawSource):
Statement(StatementKind::RAW_FUNCTION), name(name), constraints(constraints), arguments(arguments), returnValueType(returnValueType), rawSource(rawSource) { }
string StatementRawFunction::getName() {
return name;
}
string StatementRawFunction::getConstraints() {
return constraints;
}
vector<pair<string, shared_ptr<ValueType>>> StatementRawFunction::getArguments() {
return arguments;
}
shared_ptr<ValueType> StatementRawFunction::getReturnValueType() {
return returnValueType;
}
string StatementRawFunction::getRawSource() {
return rawSource;
}

View File

@@ -0,0 +1,20 @@
#include "Parser/Statement/Statement.h"
class ValueType;
class StatementRawFunction: public Statement {
private:
string name;
string constraints;
vector<pair<string, shared_ptr<ValueType>>> arguments;
shared_ptr<ValueType> returnValueType;
string rawSource;
public:
StatementRawFunction(string name, string constraints, vector<pair<string, shared_ptr<ValueType>>> arguments, shared_ptr<ValueType> returnValueType, string rawSource);
string getName();
string getConstraints();
vector<pair<string, shared_ptr<ValueType>>> getArguments();
shared_ptr<ValueType> getReturnValueType();
string getRawSource();
};

View File

@@ -4,8 +4,11 @@
shared_ptr<ValueType> ValueType::NONE = make_shared<ValueType>(ValueTypeKind::NONE, nullptr, 0);
shared_ptr<ValueType> ValueType::BOOL = make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
shared_ptr<ValueType> ValueType::SINT32 = make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
shared_ptr<ValueType> ValueType::REAL32 = make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
shared_ptr<ValueType> ValueType::U8 = make_shared<ValueType>(ValueTypeKind::U8, nullptr, 0);
shared_ptr<ValueType> ValueType::U32 = make_shared<ValueType>(ValueTypeKind::U32, nullptr, 0);
shared_ptr<ValueType> ValueType::S8 = make_shared<ValueType>(ValueTypeKind::S8, nullptr, 0);
shared_ptr<ValueType> ValueType::S32 = make_shared<ValueType>(ValueTypeKind::S32, nullptr, 0);
shared_ptr<ValueType> ValueType::R32 = make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
ValueType::ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg):
kind(kind), subType(subType), valueArg(valueArg) { }
@@ -16,10 +19,16 @@ shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shar
string lexme = token->getLexme();
if (lexme.compare("bool") == 0)
return make_shared<ValueType>(ValueTypeKind::BOOL, subType, valueArg);
else if (lexme.compare("sint32") == 0)
return make_shared<ValueType>(ValueTypeKind::SINT32, subType, valueArg);
else if (lexme.compare("real32") == 0)
return make_shared<ValueType>(ValueTypeKind::REAL32, subType, valueArg);
else if (lexme.compare("u8") == 0)
return make_shared<ValueType>(ValueTypeKind::U8, subType, valueArg);
else if (lexme.compare("u32") == 0)
return make_shared<ValueType>(ValueTypeKind::U32, subType, valueArg);
else if (lexme.compare("s8") == 0)
return make_shared<ValueType>(ValueTypeKind::S8, subType, valueArg);
else if (lexme.compare("s32") == 0)
return make_shared<ValueType>(ValueTypeKind::S32, subType, valueArg);
else if (lexme.compare("r32") == 0)
return make_shared<ValueType>(ValueTypeKind::R32, subType, valueArg);
else if (lexme.compare("data") == 0)
return make_shared<ValueType>(ValueTypeKind::DATA, subType, valueArg);
else
@@ -28,12 +37,13 @@ shared_ptr<ValueType> ValueType::valueTypeForToken(shared_ptr<Token> token, shar
case TokenKind::BOOL:
return make_shared<ValueType>(ValueTypeKind::BOOL, nullptr, 0);
case TokenKind::INTEGER_DEC:
return make_shared<ValueType>(ValueTypeKind::S32, nullptr, 0);
case TokenKind::INTEGER_HEX:
case TokenKind::INTEGER_BIN:
case TokenKind::INTEGER_CHAR:
return make_shared<ValueType>(ValueTypeKind::SINT32, nullptr, 0);
return make_shared<ValueType>(ValueTypeKind::U32, nullptr, 0);
case TokenKind::REAL:
return make_shared<ValueType>(ValueTypeKind::REAL32, nullptr, 0);
return make_shared<ValueType>(ValueTypeKind::R32, nullptr, 0);
default:
return nullptr;
}

View File

@@ -10,8 +10,11 @@ using namespace std;
enum class ValueTypeKind {
NONE,
BOOL,
SINT32,
REAL32,
U8,
U32,
S8,
S32,
R32,
DATA
};
@@ -24,8 +27,11 @@ private:
public:
static shared_ptr<ValueType> NONE;
static shared_ptr<ValueType> BOOL;
static shared_ptr<ValueType> SINT32;
static shared_ptr<ValueType> REAL32;
static shared_ptr<ValueType> U8;
static shared_ptr<ValueType> U32;
static shared_ptr<ValueType> S8;
static shared_ptr<ValueType> S32;
static shared_ptr<ValueType> R32;
static shared_ptr<ValueType> valueTypeForToken(shared_ptr<Token> token, shared_ptr<ValueType> subType, int valueArg);
ValueType(ValueTypeKind kind, shared_ptr<ValueType> subType, int valueArg);