String literals

This commit is contained in:
Rafał Grodziński
2025-07-08 22:26:24 +09:00
parent 1c19600430
commit e53a844a28
14 changed files with 162 additions and 27 deletions

9
.gitignore vendored
View File

@@ -1,12 +1,9 @@
# ignore files without extensions
*
!*.*
# brb build artifiacts
*.o
.DS_Store
.vscode/settings.json
# project build artifacts
*.dSYM
build/
# brb build artifiacts
*.o

7
samples/test.brc Normal file
View File

@@ -0,0 +1,7 @@
@extern putchar fun: character sint32 -> sint32
main fun -> sint32
text data<sint32> <- "Hello string!\n"
ret 0
;

View File

@@ -250,6 +250,10 @@ shared_ptr<Token> Lexer::nextToken() {
if (token != nullptr)
return token;
token = matchString();
if (token != nullptr)
return token;
// type
token = matchType();
if (token != nullptr)
@@ -405,6 +409,27 @@ shared_ptr<Token> Lexer::matchReal() {
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() {
int nextIndex = currentIndex;

View File

@@ -25,6 +25,7 @@ private:
shared_ptr<Token> matchIntegerBin();
shared_ptr<Token> matchIntegerChar();
shared_ptr<Token> matchReal();
shared_ptr<Token> matchString();
shared_ptr<Token> matchType();
shared_ptr<Token> matchIdentifier();
shared_ptr<Token> matchEnd();

View File

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

View File

@@ -41,6 +41,7 @@ enum class TokenKind {
INTEGER_BIN,
INTEGER_CHAR,
REAL,
STRING,
IDENTIFIER,
TYPE,

View File

@@ -84,6 +84,8 @@ string Logger::toString(shared_ptr<Token> token) {
return "INT_CHAR(" + token->getLexme() + ")";
case TokenKind::REAL:
return "REAL(" + token->getLexme() + ")";
case TokenKind::STRING:
return "STRING(" + token->getLexme() + ")";
case TokenKind::IDENTIFIER:
return "ID(" + token->getLexme() + ")";
case TokenKind::TYPE:
@@ -164,6 +166,8 @@ string Logger::toString(TokenKind tokenKind) {
return "LITERAL(INTEGER)";
case TokenKind::REAL:
return "LITERAL(REAL)";
case TokenKind::STRING:
return "LITERAL(STRING)";
case TokenKind::IDENTIFIER:
return "LITERAL(ID)";
case TokenKind::TYPE:

View File

@@ -1,8 +1,34 @@
#include "ExpressionArrayLiteral.h"
#include "Lexer/Token.h"
#include "Parser/Expression/ExpressionLiteral.h"
ExpressionArrayLiteral::ExpressionArrayLiteral(vector<shared_ptr<Expression>> expressions):
Expression(ExpressionKind::ARRAY_LITERAL, nullptr), expressions(expressions) { }
shared_ptr<ExpressionArrayLiteral> ExpressionArrayLiteral::expressionArrayLiteralForExpressions(vector<shared_ptr<Expression>> expressions) {
return make_shared<ExpressionArrayLiteral>(expressions);
}
shared_ptr<ExpressionArrayLiteral> ExpressionArrayLiteral::expressionArrayLiteralForTokenString(shared_ptr<Token> tokenString) {
if (tokenString->getKind() != TokenKind::STRING)
return nullptr;
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);
}
return make_shared<ExpressionArrayLiteral>(expressions);
}
vector<shared_ptr<Expression>> ExpressionArrayLiteral::getExpressions() {
return expressions;
}
}

View File

@@ -9,6 +9,9 @@ private:
public:
ExpressionArrayLiteral(vector<shared_ptr<Expression>> expressions);
//ExpressionArrayLiteral(shared_ptr<Token> tokenString);
static shared_ptr<ExpressionArrayLiteral> expressionArrayLiteralForExpressions(vector<shared_ptr<Expression>> expressions);
static shared_ptr<ExpressionArrayLiteral> expressionArrayLiteralForTokenString(shared_ptr<Token> tokenString);
vector<shared_ptr<Expression>> getExpressions();
};

View File

@@ -1,8 +1,26 @@
#include "ExpressionLiteral.h"
#include "Utils.h"
#include "Lexer/Token.h"
#include "Parser/ValueType.h"
shared_ptr<ExpressionLiteral> ExpressionLiteral::expressionLiteralForToken(shared_ptr<Token> token) {
switch (token->getKind()) {
case TokenKind::INTEGER_CHAR: {
string charString = token->getLexme();
optional<int> charValue = Utils::charStringToInt(charString);
if (!charValue)
return nullptr;
shared_ptr<ExpressionLiteral> expression = make_shared<ExpressionLiteral>();
expression->valueType = ValueType::valueTypeForToken(token, nullptr, 0);
expression->sint32Value = *charValue;
return expression;
}
default:
return nullptr;
}
}
ExpressionLiteral::ExpressionLiteral():
Expression(ExpressionKind::LITERAL, nullptr) { }

View File

@@ -10,6 +10,8 @@ private:
float real32Value;
public:
static shared_ptr<ExpressionLiteral> expressionLiteralForToken(shared_ptr<Token> token);
ExpressionLiteral(shared_ptr<Token> token);
ExpressionLiteral();
bool getBoolValue();

View File

@@ -421,11 +421,11 @@ shared_ptr<Expression> Parser::matchPrimary() {
if (expression != nullptr)
return expression;
expression = matchExpressionLiteral();
if (expression != nullptr)
return expression;
expression = matchExpressionArrayLiteral();
if (expression != nullptr)
return expression;
expression = matchExpressionLiteral();
if (expression != nullptr)
return expression;
@@ -466,25 +466,28 @@ shared_ptr<Expression> Parser::matchExpressionLiteral() {
}
shared_ptr<Expression> Parser::matchExpressionArrayLiteral() {
if (!tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true))
return nullptr;
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::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)) {
markError(TokenKind::RIGHT_SQUARE_BRACKET, {});
return nullptr;
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 make_shared<ExpressionArrayLiteral>(expressions);
}
return make_shared<ExpressionArrayLiteral>(expressions);
return nullptr;
}
shared_ptr<Expression> Parser::matchExpressionVariable() {

34
src/Utils.cpp Normal file
View File

@@ -0,0 +1,34 @@
#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 '\"';
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