Skip to content

Commit

Permalink
Add support for bin, oct and hex literals
Browse files Browse the repository at this point in the history
  • Loading branch information
marcauberer committed Aug 8, 2022
1 parent d6b0fd9 commit 603e302
Show file tree
Hide file tree
Showing 5 changed files with 81 additions and 25 deletions.
2 changes: 1 addition & 1 deletion .run/Spice_run.run.xml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Spice_run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O0 -ir ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="Spice_run" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="Spice_run">
<configuration default="false" name="Spice_run" type="CMakeRunConfiguration" factoryName="Application" PROGRAM_PARAMS="run -O2 -ir ../../media/test-project/os-test.spice" REDIRECT_INPUT="false" ELEVATE="false" USE_EXTERNAL_CONSOLE="false" PASS_PARENT_ENVS_2="true" PROJECT_NAME="Spice" TARGET_NAME="Spice_run" CONFIG_NAME="Debug" RUN_TARGET_PROJECT_NAME="Spice" RUN_TARGET_NAME="Spice_run">
<envs>
<env name="RUN_TESTS" value="OFF" />
</envs>
Expand Down
8 changes: 1 addition & 7 deletions media/test-project/os-test.spice
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,5 @@ f<int> main() {
}*/

f<int> main() {
int[10][10] a;
for int i = 0; i < 10; i++ {
for int j = 0; j < 10; j++ {
a[i][j] = i * j;
}
}
printf("Cell [1,3]: %d", a[1][3]);
printf("Test: %d\n", 0xfff);
}
19 changes: 10 additions & 9 deletions src/Spice.g4
Original file line number Diff line number Diff line change
Expand Up @@ -170,18 +170,19 @@ DOT: '.';
ELLIPSIS: '...';

// Regex tokens
DOUBLE_LIT: [0-9]*[.][0-9]+;
INT_LIT: NUM_LIT;
SHORT_LIT: NUM_LIT 's';
LONG_LIT: NUM_LIT 'l';
CHAR_LIT: '\'' (~['\\\r\n] | '\\' (. | EOF)) '\'';
STRING_LIT: '"' (~["\\\r\n] | '\\' (. | EOF))* '"';
INT_LIT: NONZERO_DIGIT DIGIT* | ZERO;
DOUBLE_LIT: DIGIT+ DOT DIGIT+;
SHORT_LIT: INT_LIT 's';
LONG_LIT: INT_LIT 'l';
IDENTIFIER: NONDIGIT (NONDIGIT | DIGIT)*;
IDENTIFIER: [a-zA-Z_][a-zA-Z0-9_]*;
fragment ZERO: [0];
fragment DIGIT: [0-9];
fragment NONZERO_DIGIT: [1-9];
fragment NONDIGIT: [a-zA-Z_];
fragment NUM_LIT: DEC_LIT | BIN_LIT | HEX_LIT | OCT_LIT;
fragment DEC_LIT: ([0][dD])?[0-9]+;
fragment BIN_LIT: [0][bB][01]+;
fragment HEX_LIT: [0][xXhH][0-9a-fA-F]+;
fragment OCT_LIT: [0][oO][0-7]+;
// Skipped tokens
BLOCK_COMMENT: '/*' .*? '*/' -> skip;
Expand Down
70 changes: 62 additions & 8 deletions src/parser/AstBuilderVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1197,24 +1197,21 @@ std::any AstBuilderVisitor::visitPrimitiveValue(SpiceParser::PrimitiveValueConte
primitiveValueNode->data.doubleValue = std::stod(t->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::INT_LIT) {
primitiveValueNode->type = PrimitiveValueNode::TY_INT;
primitiveValueNode->data.intValue = std::stoi(t->toString());
primitiveValueNode->data.intValue = parseInt(t->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree);
t->getSymbol()->getType() == SpiceParser::SHORT_LIT) {
primitiveValueNode->type = PrimitiveValueNode::TY_SHORT;
primitiveValueNode->data.shortValue = (short)std::stoi(t->toString());
primitiveValueNode->data.shortValue = parseShort(t->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::LONG_LIT) {
primitiveValueNode->type = PrimitiveValueNode::TY_LONG;
primitiveValueNode->data.longValue = std::stoll(t->toString());
primitiveValueNode->data.longValue = parseLong(t->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::CHAR_LIT) {
primitiveValueNode->type = PrimitiveValueNode::TY_CHAR;
primitiveValueNode->data.charValue = ctx->CHAR_LIT()->toString()[1];
primitiveValueNode->data.charValue = parseChar(ctx->CHAR_LIT()->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree);
t->getSymbol()->getType() == SpiceParser::STRING_LIT) {
primitiveValueNode->type = PrimitiveValueNode::TY_STRING;
std::string strValue = ctx->STRING_LIT()->toString();
strValue = strValue.substr(1, strValue.size() - 2);
replaceEscapeChars(strValue);
primitiveValueNode->data.stringValue = strValue;
primitiveValueNode->data.stringValue = parseString(ctx->STRING_LIT()->toString());
} else if (auto t = dynamic_cast<antlr4::tree::TerminalNode *>(subTree); t->getSymbol()->getType() == SpiceParser::TRUE) {
primitiveValueNode->type = PrimitiveValueNode::TY_BOOL;
primitiveValueNode->data.boolValue = true;
Expand Down Expand Up @@ -1479,4 +1476,61 @@ void AstBuilderVisitor::replaceEscapeChars(std::string &string) {
CommonUtil::replaceAll(string, "\\v", "\v");
CommonUtil::replaceAll(string, "\\'", "\'");
CommonUtil::replaceAll(string, "\\?", "\?");
}

int32_t AstBuilderVisitor::parseInt(const std::string &input) {
std::function<int32_t(const std::string &, int)> cb = [](const std::string &substr, int base) {
return std::stoi(substr, nullptr, base);
};
return parseNumeric(input, cb);
}
int16_t AstBuilderVisitor::parseShort(const std::string &input) {
std::function<int16_t(const std::string &, int)> cb = [](const std::string &substr, int base) {
return (int16_t)std::stoi(substr, nullptr, base);
};
return parseNumeric(input, cb);
}

int64_t AstBuilderVisitor::parseLong(const std::string &input) {
std::function<int64_t(const std::string &, int)> cb = [](const std::string &substr, int base) {
return std::stoll(substr, nullptr, base);
};
return parseNumeric(input, cb);
}

int8_t AstBuilderVisitor::parseChar(const std::string &input) { return input[1]; }

std::string AstBuilderVisitor::parseString(std::string input) {
input = input.substr(1, input.size() - 2);
replaceEscapeChars(input);
return input;
}

template <typename T> T AstBuilderVisitor::parseNumeric(const std::string &input, std::function<T(const std::string &, int)> cb) {
if (input.length() >= 3) {
char c1 = input[0];
char c2 = input[1];
std::string substr = input.substr(2);
if (c1 == '0') {
switch (c2) {
case 'd':
case 'D':
return cb(substr, 10);
case 'b':
case 'B':
return cb(substr, 2);
case 'h':
case 'H':
case 'x':
case 'X':
return cb(substr, 16);
case 'o':
case 'O':
return cb(substr, 8);
default:
return cb(input, 10);
}
}
}
return cb(input, 10);
}
7 changes: 7 additions & 0 deletions src/parser/AstBuilderVisitor.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

#include <SpiceVisitor.h>

#include <functional>
#include <utility>

// Forward declarations
Expand Down Expand Up @@ -86,5 +87,11 @@ class AstBuilderVisitor : public SpiceVisitor {
std::string fileName;

// Private methods
static int32_t parseInt(const std::string &input);
static int16_t parseShort(const std::string &input);
static int64_t parseLong(const std::string &input);
static int8_t parseChar(const std::string &input);
static std::string parseString(std::string input);
template <typename T> T static parseNumeric(const std::string &input, std::function<T(const std::string &, int)> cb);
static void replaceEscapeChars(std::string &string);
};

0 comments on commit 603e302

Please sign in to comment.