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 .DS_Store
.vscode/settings.json .vscode/settings.json
# project build artifacts # project build artifacts
*.dSYM *.dSYM
build/ 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) if (token != nullptr)
return token; return token;
token = matchString();
if (token != nullptr)
return token;
// type // type
token = matchType(); token = matchType();
if (token != nullptr) if (token != nullptr)
@@ -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;

View File

@@ -25,6 +25,7 @@ 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> 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

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

View File

@@ -84,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:
@@ -164,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:

View File

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

View File

@@ -9,6 +9,9 @@ private:
public: public:
ExpressionArrayLiteral(vector<shared_ptr<Expression>> expressions); 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(); vector<shared_ptr<Expression>> getExpressions();
}; };

View File

@@ -1,8 +1,26 @@
#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"
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(): ExpressionLiteral::ExpressionLiteral():
Expression(ExpressionKind::LITERAL, nullptr) { } Expression(ExpressionKind::LITERAL, nullptr) { }

View File

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

View File

@@ -421,11 +421,11 @@ shared_ptr<Expression> Parser::matchPrimary() {
if (expression != nullptr) if (expression != nullptr)
return expression; return expression;
expression = matchExpressionLiteral(); expression = matchExpressionArrayLiteral();
if (expression != nullptr) if (expression != nullptr)
return expression; return expression;
expression = matchExpressionArrayLiteral(); expression = matchExpressionLiteral();
if (expression != nullptr) if (expression != nullptr)
return expression; return expression;
@@ -466,9 +466,9 @@ shared_ptr<Expression> Parser::matchExpressionLiteral() {
} }
shared_ptr<Expression> Parser::matchExpressionArrayLiteral() { shared_ptr<Expression> Parser::matchExpressionArrayLiteral() {
if (!tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) if (tryMatchingTokenKinds({TokenKind::STRING}, true, false)) {
return nullptr; return ExpressionArrayLiteral::expressionArrayLiteralForTokenString(tokens.at(currentIndex++));
} else if (tryMatchingTokenKinds({TokenKind::LEFT_SQUARE_BRACKET}, true, true)) {
vector<shared_ptr<Expression>> expressions; vector<shared_ptr<Expression>> expressions;
if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) { if (!tryMatchingTokenKinds({TokenKind::RIGHT_SQUARE_BRACKET}, true, true)) {
do { do {
@@ -487,6 +487,9 @@ shared_ptr<Expression> Parser::matchExpressionArrayLiteral() {
return make_shared<ExpressionArrayLiteral>(expressions); return make_shared<ExpressionArrayLiteral>(expressions);
} }
return nullptr;
}
shared_ptr<Expression> Parser::matchExpressionVariable() { shared_ptr<Expression> Parser::matchExpressionVariable() {
shared_ptr<Token> token = tokens.at(currentIndex); shared_ptr<Token> token = tokens.at(currentIndex);

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