forked from solstice/solstice
refactor
This commit is contained in:
684
src/parser.cpp
Normal file
684
src/parser.cpp
Normal file
@@ -0,0 +1,684 @@
|
||||
#include "parser.h"
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
|
||||
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
||||
|
||||
namespace Solstice {
|
||||
namespace Parser {
|
||||
|
||||
// SolData Implementation
|
||||
SolData::SolData(int64_t in) : data(in), type(SolDataType::Int) {}
|
||||
SolData::SolData(double in) : data(in), type(SolDataType::Double) {}
|
||||
SolData::SolData(std::string in) : data(in), type(SolDataType::String) {}
|
||||
SolData::SolData(char in) : data(in), type(SolDataType::Char) {}
|
||||
SolData::SolData(bool in) : data(in), type(SolDataType::Bool) {}
|
||||
|
||||
std::optional<int64_t> SolData::getInt() {
|
||||
if (type == SolDataType::Int) {
|
||||
return std::get<int64_t>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
std::optional<double> SolData::getDouble() {
|
||||
if (type == SolDataType::Double) {
|
||||
return std::get<double>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
std::optional<std::string> SolData::getString() {
|
||||
if (type == SolDataType::String) {
|
||||
return std::get<std::string>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
std::optional<char> SolData::getChar() {
|
||||
if (type == SolDataType::Char) {
|
||||
return std::get<char>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
std::optional<bool> SolData::getBool() {
|
||||
if (type == SolDataType::Bool) {
|
||||
return std::get<bool>(data);
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// SolNode Implementation
|
||||
SolNode::SolNode(SolNodeType nodeType) : nodeType(nodeType) {}
|
||||
SolNode::SolNode(SolNodeType nodeType, SolData data) : data(data), nodeType(nodeType) {}
|
||||
|
||||
void SolNode::addNode(SolNode in) {
|
||||
children.push_back(in);
|
||||
}
|
||||
void SolNode::setValue(SolData in) {
|
||||
data = in;
|
||||
}
|
||||
|
||||
const std::vector<SolGroundCodeBlock> SolNode::generateCode() {
|
||||
std::vector<SolGroundCodeBlock> code;
|
||||
if (nodeType != SolNodeType::If && nodeType != SolNodeType::While) for (auto& child : children) {
|
||||
auto childCode = child.generateCode();
|
||||
code.insert(code.end(), childCode.begin(), childCode.end());
|
||||
}
|
||||
switch (nodeType) {
|
||||
case SolNodeType::Value: {
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
SolGroundCodeBlock codeBlock;
|
||||
GroundInstruction gi = groundCreateInstruction(SET);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
switch (data.type) {
|
||||
case SolDataType::Int: {
|
||||
auto dataopt = data.getInt();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(INT, dataopt.value()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolDataType::Double: {
|
||||
auto dataopt = data.getDouble();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(DOUBLE, dataopt.value()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolDataType::String: {
|
||||
auto dataopt = data.getString();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(STRING, dataopt.value().c_str()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolDataType::Char: {
|
||||
auto dataopt = data.getChar();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(CHAR, dataopt.value()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolDataType::Bool: {
|
||||
auto dataopt = data.getBool();
|
||||
if (dataopt) {
|
||||
groundAddValueToInstruction(&gi, groundCreateValue(BOOL, dataopt.value()));
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Add: {
|
||||
SolGroundCodeBlock codeBlock;
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
GroundInstruction gi = groundCreateInstruction(ADD);
|
||||
if (children.size() < 2) {
|
||||
std::cout << "Need more stuff to add\n";
|
||||
}
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Equal: {
|
||||
SolGroundCodeBlock codeBlock;
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
GroundInstruction gi = groundCreateInstruction(EQUAL);
|
||||
if (children.size() < 2) {
|
||||
std::cout << "Need more stuff to equal\n";
|
||||
}
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Inequal: {
|
||||
SolGroundCodeBlock codeBlock;
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
GroundInstruction gi = groundCreateInstruction(INEQUAL);
|
||||
if (children.size() < 2) {
|
||||
std::cout << "Need more stuff to inequal\n";
|
||||
}
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Puts: {
|
||||
SolGroundCodeBlock codeBlock;
|
||||
GroundInstruction gi = groundCreateInstruction(PRINTLN);
|
||||
if (children.size() < 1) {
|
||||
std::cout << "Need more stuff to puts\n";
|
||||
}
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
codeBlock.code.push_back(gi);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::If: {
|
||||
auto conditionCode = children[0].generateCode();
|
||||
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
SolGroundCodeBlock codeBlock;
|
||||
GroundInstruction gi = groundCreateInstruction(NOT);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
codeBlock.code.push_back(gi);
|
||||
std::string labelIdString = "if_" + std::to_string(labelIterator++);
|
||||
char* labelId = (char*) malloc(sizeof(char) * labelIdString.size() + 1);
|
||||
strcpy(labelId, labelIdString.data());
|
||||
GroundInstruction gi2 = groundCreateInstruction(IF);
|
||||
groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi2, groundCreateReference(LINEREF, labelId));
|
||||
codeBlock.code.push_back(gi2);
|
||||
code.push_back(codeBlock);
|
||||
for (size_t i = 1; i < children.size(); i++) {
|
||||
auto childCode = children[i].generateCode();
|
||||
code.insert(code.end(), childCode.begin(), childCode.end());
|
||||
}
|
||||
codeBlock.code.clear();
|
||||
GroundInstruction gi3 = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&gi3, groundCreateReference(LABEL, labelId));
|
||||
codeBlock.code.push_back(gi3);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::While: {
|
||||
SolGroundCodeBlock startLabelBlock;
|
||||
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
||||
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
||||
char* startLabelId = (char*) malloc(sizeof(char) * (startLabelIdString.size() + 1));
|
||||
strcpy(startLabelId, startLabelIdString.data());
|
||||
char* endLabelId = (char*) malloc(sizeof(char) * (endLabelIdString.size() + 1));
|
||||
strcpy(endLabelId, endLabelIdString.data());
|
||||
|
||||
GroundInstruction startLabel = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&startLabel, groundCreateReference(LABEL, startLabelId));
|
||||
startLabelBlock.code.push_back(startLabel);
|
||||
code.push_back(startLabelBlock);
|
||||
|
||||
auto conditionCode = children[0].generateCode();
|
||||
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
||||
|
||||
SolGroundCodeBlock checkBlock;
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
GroundInstruction gi = groundCreateInstruction(NOT);
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi, groundCreateReference(DIRREF, outputId.data()));
|
||||
checkBlock.code.push_back(gi);
|
||||
GroundInstruction gi2 = groundCreateInstruction(IF);
|
||||
groundAddReferenceToInstruction(&gi2, groundCreateReference(VALREF, outputId.data()));
|
||||
groundAddReferenceToInstruction(&gi2, groundCreateReference(LINEREF, endLabelId));
|
||||
checkBlock.code.push_back(gi2);
|
||||
code.push_back(checkBlock);
|
||||
|
||||
for (size_t i = 1; i < children.size(); i++) {
|
||||
auto childCode = children[i].generateCode();
|
||||
code.insert(code.end(), childCode.begin(), childCode.end());
|
||||
}
|
||||
|
||||
SolGroundCodeBlock endBlock;
|
||||
GroundInstruction gi3 = groundCreateInstruction(JUMP);
|
||||
groundAddReferenceToInstruction(&gi3, groundCreateReference(LINEREF, startLabelId));
|
||||
endBlock.code.push_back(gi3);
|
||||
GroundInstruction gi4 = groundCreateInstruction(CREATELABEL);
|
||||
groundAddReferenceToInstruction(&gi4, groundCreateReference(LABEL, endLabelId));
|
||||
endBlock.code.push_back(gi4);
|
||||
code.push_back(endBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Identifier: {
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Set: {
|
||||
SolGroundCodeBlock codeBlock;
|
||||
GroundInstruction setInstruction = groundCreateInstruction(SET);
|
||||
groundAddReferenceToInstruction(&setInstruction, groundCreateReference(DIRREF, children[0].outputId.data()));
|
||||
groundAddReferenceToInstruction(&setInstruction, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||
codeBlock.code.push_back(setInstruction);
|
||||
code.push_back(codeBlock);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::FunctionCall: {
|
||||
// Take care of in built functions
|
||||
if (children[0].outputId == "input") {
|
||||
SolGroundCodeBlock inputCodeBlock;
|
||||
if (children.size() > 1) {
|
||||
GroundInstruction printInstruction = groundCreateInstruction(PRINT);
|
||||
groundAddReferenceToInstruction(&printInstruction, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||
inputCodeBlock.code.push_back(printInstruction);
|
||||
}
|
||||
GroundInstruction inputInstruction = groundCreateInstruction(INPUT);
|
||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||
groundAddReferenceToInstruction(&inputInstruction, groundCreateReference(DIRREF, outputId.data()));
|
||||
inputCodeBlock.code.push_back(inputInstruction);
|
||||
code.push_back(inputCodeBlock);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
default: {}
|
||||
}
|
||||
return code;
|
||||
}
|
||||
|
||||
// Parser Implementation
|
||||
Parser::Parser(std::vector<std::string> in) : tokensToParse(in) {}
|
||||
|
||||
std::optional<std::string> Parser::peek(int ahead) {
|
||||
if (current + ahead < size) {
|
||||
return tokensToParse[current + ahead];
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<std::string> Parser::consume() {
|
||||
if (current < size) {
|
||||
return tokensToParse[current++];
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
// Helper functions
|
||||
bool Parser::isInt(std::string in) {
|
||||
for (const char& c : in) {
|
||||
if (!std::isdigit(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Parser::isDouble(std::string in) {
|
||||
bool foundDot = false;
|
||||
for (const char& c : in) {
|
||||
if (!std::isdigit(c)) {
|
||||
if (!foundDot && c == '.') {
|
||||
foundDot = true;
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool Parser::isString(std::string in) {
|
||||
if (in.size() > 1 && in[0] == '"' && in.back() == '"') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Parser::isChar(std::string in) {
|
||||
if (in.size() == 3 && in[0] == '\'' && in.back() == '\'') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
bool Parser::isBool(std::string in) {
|
||||
if (in == "true" || in == "false") {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
SolDataType Parser::getDataType(std::string in) {
|
||||
if (isInt(in)) {
|
||||
return SolDataType::Int;
|
||||
}
|
||||
if (isDouble(in)) {
|
||||
return SolDataType::Double;
|
||||
}
|
||||
if (isString(in)) {
|
||||
return SolDataType::String;
|
||||
}
|
||||
if (isChar(in)) {
|
||||
return SolDataType::Char;
|
||||
}
|
||||
if (isBool(in)) {
|
||||
return SolDataType::Bool;
|
||||
}
|
||||
return SolDataType::None;
|
||||
}
|
||||
|
||||
SolNodeType Parser::getNodeType(std::string in) {
|
||||
if (getDataType(in) != SolDataType::None) {
|
||||
return SolNodeType::Value;
|
||||
}
|
||||
if (in == "+") {
|
||||
return SolNodeType::Add;
|
||||
}
|
||||
if (in == "=") {
|
||||
return SolNodeType::Set;
|
||||
}
|
||||
if (in == "==") {
|
||||
return SolNodeType::Equal;
|
||||
}
|
||||
if (in == "!=") {
|
||||
return SolNodeType::Inequal;
|
||||
}
|
||||
if (in == "puts") {
|
||||
return SolNodeType::Puts;
|
||||
}
|
||||
if (in == "if") {
|
||||
return SolNodeType::If;
|
||||
}
|
||||
if (in == "while") {
|
||||
return SolNodeType::While;
|
||||
}
|
||||
if (in == "{") {
|
||||
return SolNodeType::CodeBlockStart;
|
||||
}
|
||||
if (in == "}") {
|
||||
return SolNodeType::CodeBlockEnd;
|
||||
}
|
||||
if (in == "(") {
|
||||
return SolNodeType::BracketStart;
|
||||
}
|
||||
if (in == ")") {
|
||||
return SolNodeType::BracketEnd;
|
||||
}
|
||||
return SolNodeType::Identifier;
|
||||
}
|
||||
|
||||
SolNode Parser::parse() {
|
||||
current = 0;
|
||||
size = tokensToParse.size();
|
||||
SolNode rootNode(SolNodeType::Root);
|
||||
while (auto tokenopt = consume()) {
|
||||
std::string token = tokenopt.value();
|
||||
switch (getNodeType(token)) {
|
||||
case SolNodeType::Value: {
|
||||
switch (getDataType(token)) {
|
||||
case SolDataType::Int: {
|
||||
SolNode intNode(SolNodeType::Value);
|
||||
intNode.setValue((int64_t) std::stoll(token));
|
||||
rootNode.addNode(intNode);
|
||||
break;
|
||||
}
|
||||
case SolDataType::Double: {
|
||||
SolNode doubleNode(SolNodeType::Value);
|
||||
doubleNode.setValue(std::stod(token));
|
||||
rootNode.addNode(doubleNode);
|
||||
break;
|
||||
}
|
||||
case SolDataType::String: {
|
||||
SolNode stringNode(SolNodeType::Value);
|
||||
stringNode.setValue(token.substr(1, token.size() - 2));
|
||||
rootNode.addNode(stringNode);
|
||||
break;
|
||||
}
|
||||
case SolDataType::Char: {
|
||||
SolNode charNode(SolNodeType::Value);
|
||||
charNode.setValue(token[1]);
|
||||
rootNode.addNode(charNode);
|
||||
break;
|
||||
}
|
||||
case SolDataType::Bool: {
|
||||
SolNode boolNode(SolNodeType::Value);
|
||||
boolNode.setValue(token == "true");
|
||||
rootNode.addNode(boolNode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Add: {
|
||||
SolNode addNode(SolNodeType::Add);
|
||||
addNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
addNode.addNode(parseOneToken(tokenopt));
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENS\n";
|
||||
exit(1);
|
||||
}
|
||||
rootNode.addNode(addNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Equal: {
|
||||
SolNode equalNode(SolNodeType::Equal);
|
||||
equalNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
equalNode.addNode(parseOneToken(tokenopt));
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENS\n";
|
||||
exit(1);
|
||||
}
|
||||
rootNode.addNode(equalNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Inequal: {
|
||||
SolNode inequalNode(SolNodeType::Inequal);
|
||||
inequalNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
inequalNode.addNode(parseOneToken(tokenopt));
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENS\n";
|
||||
exit(1);
|
||||
}
|
||||
rootNode.addNode(inequalNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Puts: {
|
||||
SolNode putsNode(SolNodeType::Puts);
|
||||
std::vector<std::string> tokens;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "\n") {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto children = Parser(tokens).parse();
|
||||
for (auto& child : children.children) {
|
||||
putsNode.addNode(child);
|
||||
}
|
||||
rootNode.addNode(putsNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::If: {
|
||||
SolNode ifNode(SolNodeType::If);
|
||||
std::vector<std::string> tokens;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "\n") {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto children = Parser(tokens).parse();
|
||||
ifNode.addNode(children.children[0]);
|
||||
tokens.clear();
|
||||
size_t brackets = 1;
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
if (tokenopt.value() == "{") {
|
||||
tokens.push_back(tokenopt.value());
|
||||
while (auto tokenopt = consume()) {
|
||||
tokens.push_back(tokenopt.value());
|
||||
if (tokenopt.value() == "{") {
|
||||
brackets++;
|
||||
}
|
||||
if (tokenopt.value() == "}") {
|
||||
brackets--;
|
||||
}
|
||||
if (brackets == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "I want a code block instead of a " + tokenopt.value() + "\n";
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENSSSSS\n";
|
||||
exit(1);
|
||||
}
|
||||
auto childCodeBlock = Parser(tokens).parse();
|
||||
ifNode.addNode(childCodeBlock.children[0]);
|
||||
rootNode.addNode(ifNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::While: {
|
||||
SolNode whileNode(SolNodeType::While);
|
||||
std::vector<std::string> tokens;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "\n") {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto children = Parser(tokens).parse();
|
||||
whileNode.addNode(children.children[0]);
|
||||
tokens.clear();
|
||||
size_t brackets = 1;
|
||||
auto tokenopt = consume();
|
||||
if (tokenopt) {
|
||||
if (tokenopt.value() == "{") {
|
||||
tokens.push_back(tokenopt.value());
|
||||
while (auto tokenopt = consume()) {
|
||||
tokens.push_back(tokenopt.value());
|
||||
if (tokenopt.value() == "{") {
|
||||
brackets++;
|
||||
}
|
||||
if (tokenopt.value() == "}") {
|
||||
brackets--;
|
||||
}
|
||||
if (brackets == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
std::cout << "I want a code block instead of a " + tokenopt.value() + "\n";
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
std::cout << "FEED ME MORE TOKENSSSSS\n";
|
||||
exit(1);
|
||||
}
|
||||
auto childCodeBlock = Parser(tokens).parse();
|
||||
whileNode.addNode(childCodeBlock.children[0]);
|
||||
rootNode.addNode(whileNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::CodeBlockStart: {
|
||||
SolNode codeBlockNode(SolNodeType::CodeBlock);
|
||||
size_t brackets = 1;
|
||||
std::vector<std::string> tokens;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "{") {
|
||||
brackets++;
|
||||
}
|
||||
if (tokenopt.value() == "}") {
|
||||
brackets--;
|
||||
}
|
||||
if (brackets == 0) {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
codeBlockNode.children = Parser(tokens).parse().children;
|
||||
rootNode.addNode(codeBlockNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Identifier: {
|
||||
SolNode idNode(SolNodeType::Identifier);
|
||||
idNode.outputId = token;
|
||||
rootNode.addNode(idNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::Set: {
|
||||
SolNode setNode(SolNodeType::Set);
|
||||
setNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
std::vector<std::string> tokens;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "\n") {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto children = Parser(tokens).parse();
|
||||
setNode.addNode(children.children[0]);
|
||||
rootNode.addNode(setNode);
|
||||
break;
|
||||
}
|
||||
case SolNodeType::BracketStart: {
|
||||
if (rootNode.children.back().nodeType == SolNodeType::Identifier) {
|
||||
SolNode fnCallNode(SolNodeType::FunctionCall);
|
||||
fnCallNode.addNode(rootNode.children.back());
|
||||
rootNode.children.pop_back();
|
||||
std::vector<std::string> tokens;
|
||||
size_t brackets = 1;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "(") {
|
||||
brackets++;
|
||||
}
|
||||
if (tokenopt.value() == ")") {
|
||||
brackets--;
|
||||
}
|
||||
if (brackets < 1) {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto node = Parser(tokens).parse();
|
||||
fnCallNode.children.insert(fnCallNode.children.end(), node.children.begin(), node.children.end());
|
||||
rootNode.addNode(fnCallNode);
|
||||
} else {
|
||||
std::vector<std::string> tokens;
|
||||
size_t brackets = 1;
|
||||
while (auto tokenopt = consume()) {
|
||||
if (tokenopt.value() == "(") {
|
||||
brackets++;
|
||||
}
|
||||
if (tokenopt.value() == ")") {
|
||||
brackets--;
|
||||
}
|
||||
if (brackets < 1) {
|
||||
break;
|
||||
}
|
||||
tokens.push_back(tokenopt.value());
|
||||
}
|
||||
auto node = Parser(tokens).parse();
|
||||
node.nodeType = SolNodeType::Expression;
|
||||
rootNode.addNode(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return rootNode;
|
||||
}
|
||||
|
||||
GroundProgram assembleProgram(SolNode& rootNode) {
|
||||
GroundProgram gp = groundCreateProgram();
|
||||
auto code = rootNode.generateCode();
|
||||
for (int i = 0; i < code.size(); i++) {
|
||||
for (const auto& inst : code[i].code) {
|
||||
groundAddInstructionToProgram(&gp, inst);
|
||||
}
|
||||
}
|
||||
return gp;
|
||||
}
|
||||
|
||||
} // namespace Parser
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user