forked from solstice/solstice
Better errors, comments
This commit is contained in:
@@ -4,14 +4,37 @@
|
|||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
namespace Error {
|
namespace Error {
|
||||||
[[noreturn]] void syntaxError(std::string what) {
|
// ANSI Color Codes
|
||||||
std::cout << "\033[31mSyntax error\n";
|
const std::string RED = "\033[31m";
|
||||||
std::cout << "What: " << what << "\n";
|
const std::string YELLOW = "\033[33m";
|
||||||
|
const std::string CYAN = "\033[36m";
|
||||||
|
const std::string RESET = "\033[0m";
|
||||||
|
const std::string BOLD = "\033[1m";
|
||||||
|
|
||||||
|
[[noreturn]] void syntaxError(std::string what, int line, std::string lineContent) {
|
||||||
|
std::cout << BOLD << RED << "Syntax Error" << RESET;
|
||||||
|
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
||||||
|
std::cout << ":\n";
|
||||||
|
|
||||||
|
if (!lineContent.empty()) {
|
||||||
|
std::cout << "\n " << CYAN << lineContent << RESET << "\n\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
[[noreturn]] void typingError(std::string what) {
|
[[noreturn]] void typingError(std::string what, int line, std::string lineContent) {
|
||||||
std::cout << "\033[31mTyping error\n";
|
std::cout << BOLD << RED << "Typing Error" << RESET;
|
||||||
std::cout << "What: " << what << "\n";
|
if (line > 0) std::cout << " on line " << BOLD << line << RESET;
|
||||||
|
std::cout << ":\n";
|
||||||
|
|
||||||
|
if (!lineContent.empty()) {
|
||||||
|
std::cout << "\n " << CYAN << lineContent << RESET << "\n\n";
|
||||||
|
} else {
|
||||||
|
std::cout << "\n";
|
||||||
|
}
|
||||||
|
std::cout << YELLOW << "-> " << what << RESET << "\n";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,8 +1,13 @@
|
|||||||
|
#ifndef ERROR_H
|
||||||
|
#define ERROR_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
namespace Error {
|
namespace Error {
|
||||||
[[noreturn]] void syntaxError(std::string what);
|
[[noreturn]] void syntaxError(std::string what, int line = 0, std::string lineContent = "");
|
||||||
[[noreturn]] void typingError(std::string what);
|
[[noreturn]] void typingError(std::string what, int line = 0, std::string lineContent = "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <sstream>
|
||||||
#include "lexer.h"
|
#include "lexer.h"
|
||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
@@ -21,45 +22,102 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Lexer::Lexer(std::string in) : input(in), size(in.size()) {}
|
Lexer::Lexer(std::string in) : input(in), size(in.size()) {
|
||||||
std::vector<std::string> Lexer::lex() {
|
std::stringstream ss(in);
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(ss, line)) {
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
if (lines.empty()) lines.push_back("");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Token> Lexer::lex() {
|
||||||
current = 0;
|
current = 0;
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
std::string buf;
|
std::string buf;
|
||||||
bool inString = false;
|
bool inString = false;
|
||||||
|
size_t currentLine = 1;
|
||||||
|
|
||||||
|
auto addToken = [&](std::string val) {
|
||||||
|
std::string content = "";
|
||||||
|
if (currentLine <= lines.size()) {
|
||||||
|
content = lines[currentLine - 1];
|
||||||
|
}
|
||||||
|
tokens.push_back({val, currentLine, content});
|
||||||
|
};
|
||||||
|
|
||||||
while (auto copt = consume()) {
|
while (auto copt = consume()) {
|
||||||
char c = copt.value();
|
char c = copt.value();
|
||||||
|
|
||||||
if (inString) {
|
if (inString) {
|
||||||
buf.push_back(c);
|
buf.push_back(c);
|
||||||
if (c == '"') {
|
if (c == '"') {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
inString = false;
|
inString = false;
|
||||||
}
|
}
|
||||||
|
if (c == '\n') currentLine++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
// double quotes are special
|
// double quotes are special
|
||||||
case '"': {
|
case '"': {
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
buf.push_back(c);
|
buf.push_back(c);
|
||||||
inString = true;
|
inString = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
// slash is special
|
||||||
|
case '/': {
|
||||||
|
if (peek(0).has_value() && peek(0).value() == '/') {
|
||||||
|
while (auto copt = consume()) {
|
||||||
|
char c = copt.value();
|
||||||
|
if (c == '\n') {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
std::string newToken(1, c);
|
||||||
|
auto tokenopt = peek(0);
|
||||||
|
if (tokenopt) {
|
||||||
|
char token = tokenopt.value();
|
||||||
|
if (token == '=') {
|
||||||
|
newToken += token;
|
||||||
|
consume();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!buf.empty()) {
|
||||||
|
addToken(buf);
|
||||||
|
buf.clear();
|
||||||
|
}
|
||||||
|
addToken(newToken);
|
||||||
|
break;
|
||||||
|
}
|
||||||
// tokens which are not followed by anything
|
// tokens which are not followed by anything
|
||||||
case '\n':
|
case '\n':
|
||||||
|
{
|
||||||
|
if (!buf.empty()) {
|
||||||
|
addToken(buf);
|
||||||
|
buf.clear();
|
||||||
|
}
|
||||||
|
addToken(std::string(1, c));
|
||||||
|
currentLine++;
|
||||||
|
break;
|
||||||
|
}
|
||||||
case '(':
|
case '(':
|
||||||
case ')':
|
case ')':
|
||||||
case '}':
|
case '}':
|
||||||
{
|
{
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
tokens.push_back(std::string(1, c));
|
addToken(std::string(1, c));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// tokens which may be followed by either themselves
|
// tokens which may be followed by either themselves
|
||||||
@@ -77,16 +135,15 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
tokens.push_back(newToken);
|
addToken(newToken);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// tokens which may be followed by an equals sign
|
// tokens which may be followed by an equals sign
|
||||||
case '!':
|
case '!':
|
||||||
case '*':
|
case '*':
|
||||||
case '/':
|
|
||||||
case '=':
|
case '=':
|
||||||
case '>':
|
case '>':
|
||||||
case '<':
|
case '<':
|
||||||
@@ -101,27 +158,29 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
tokens.push_back(newToken);
|
addToken(newToken);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// tokens which need a newline inserted for them
|
// tokens which need a newline inserted for them
|
||||||
case '{':
|
case '{':
|
||||||
{
|
{
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
tokens.push_back("\n");
|
addToken("\n");
|
||||||
tokens.push_back(std::string(1, c));
|
addToken(std::string(1, c));
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
// tokens which do not need to be included
|
// tokens which do not need to be included
|
||||||
case ' ':
|
case ' ':
|
||||||
|
case '\r':
|
||||||
{
|
{
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
buf.clear();
|
buf.clear();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -134,7 +193,7 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!buf.empty()) {
|
if (!buf.empty()) {
|
||||||
tokens.push_back(buf);
|
addToken(buf);
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
}
|
}
|
||||||
|
|||||||
14
src/lexer.h
14
src/lexer.h
@@ -1,17 +1,29 @@
|
|||||||
|
#ifndef LEXER_H
|
||||||
|
#define LEXER_H
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <optional>
|
#include <optional>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
|
struct Token {
|
||||||
|
std::string value;
|
||||||
|
int line;
|
||||||
|
std::string lineContent;
|
||||||
|
};
|
||||||
|
|
||||||
class Lexer {
|
class Lexer {
|
||||||
std::string input;
|
std::string input;
|
||||||
|
std::vector<std::string> lines;
|
||||||
size_t size;
|
size_t size;
|
||||||
size_t current;
|
size_t current;
|
||||||
std::optional<char> peek(int ahead = 1);
|
std::optional<char> peek(int ahead = 1);
|
||||||
std::optional<char> consume();
|
std::optional<char> consume();
|
||||||
public:
|
public:
|
||||||
Lexer(std::string in);
|
Lexer(std::string in);
|
||||||
std::vector<std::string> lex();
|
std::vector<Token> lex();
|
||||||
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
227
src/parser.cpp
227
src/parser.cpp
@@ -4,7 +4,7 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
||||||
#define parseOneToken(token) Parser({token.value()}).parse().children[0]
|
#define parseOneToken(token) Parser({token}).parse().children[0]
|
||||||
|
|
||||||
namespace Solstice {
|
namespace Solstice {
|
||||||
namespace Parser {
|
namespace Parser {
|
||||||
@@ -21,7 +21,7 @@ namespace Solstice {
|
|||||||
if (variables.find(i.outputId) != variables.end()) {
|
if (variables.find(i.outputId) != variables.end()) {
|
||||||
return variables[i.outputId];
|
return variables[i.outputId];
|
||||||
} else {
|
} else {
|
||||||
Error::syntaxError("Unknown variable");
|
Error::syntaxError("Unknown variable", i.line, i.lineContent);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -178,14 +178,14 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Add: {
|
case SolNodeType::Add: {
|
||||||
ensure3(children[0], SolDataType::Int, SolDataType::Double, SolDataType::String);
|
ensure3(children[0], SolDataType::Int, SolDataType::Double, SolDataType::String, "operator '+'");
|
||||||
ensure3(children[1], SolDataType::Int, SolDataType::Double, SolDataType::String);
|
ensure3(children[1], SolDataType::Int, SolDataType::Double, SolDataType::String, "operator '+'");
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '+'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(ADD);
|
GroundInstruction gi = groundCreateInstruction(ADD);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to add\n";
|
Error::typingError("Need more stuff to add", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -197,13 +197,13 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Subtract: {
|
case SolNodeType::Subtract: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double);
|
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '-'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double);
|
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '-'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(SUBTRACT);
|
GroundInstruction gi = groundCreateInstruction(SUBTRACT);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to add\n";
|
Error::typingError("Need more stuff to subtract", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -215,13 +215,13 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Multiply: {
|
case SolNodeType::Multiply: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double);
|
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '*'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double);
|
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '*'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(MULTIPLY);
|
GroundInstruction gi = groundCreateInstruction(MULTIPLY);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to add\n";
|
Error::typingError("Need more stuff to multiply", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -233,13 +233,13 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Divide: {
|
case SolNodeType::Divide: {
|
||||||
ensure2(children[0], SolDataType::Int, SolDataType::Double);
|
ensure2(children[0], SolDataType::Int, SolDataType::Double, "operator '/'");
|
||||||
ensure2(children[1], SolDataType::Int, SolDataType::Double);
|
ensure2(children[1], SolDataType::Int, SolDataType::Double, "operator '/'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(DIVIDE);
|
GroundInstruction gi = groundCreateInstruction(DIVIDE);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to add\n";
|
Error::typingError("Need more stuff to divide", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -251,12 +251,12 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Equal: {
|
case SolNodeType::Equal: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '=='");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(EQUAL);
|
GroundInstruction gi = groundCreateInstruction(EQUAL);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to equal\n";
|
Error::typingError("Need more stuff to equal", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -268,12 +268,12 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Inequal: {
|
case SolNodeType::Inequal: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '!='");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(INEQUAL);
|
GroundInstruction gi = groundCreateInstruction(INEQUAL);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to inequal\n";
|
Error::typingError("Need more stuff to inequal", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -285,12 +285,12 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Greater: {
|
case SolNodeType::Greater: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '>'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(GREATER);
|
GroundInstruction gi = groundCreateInstruction(GREATER);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to greater\n";
|
Error::typingError("Need more stuff to greater", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -302,12 +302,12 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Lesser: {
|
case SolNodeType::Lesser: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '<'");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
GroundInstruction gi = groundCreateInstruction(LESSER);
|
GroundInstruction gi = groundCreateInstruction(LESSER);
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to lesser\n";
|
Error::typingError("Need more stuff to lesser", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[1].outputId.data()));
|
||||||
@@ -319,10 +319,10 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::EqGreater: {
|
case SolNodeType::EqGreater: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '>='");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to inequal\n";
|
Error::typingError("Need more stuff to inequal", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
std::string trueLabelIdString = "internal_true" + std::to_string(labelIterator++);
|
std::string trueLabelIdString = "internal_true" + std::to_string(labelIterator++);
|
||||||
@@ -392,10 +392,10 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::EqLesser: {
|
case SolNodeType::EqLesser: {
|
||||||
ensuresame(children[0], children[1]);
|
ensuresame(children[0], children[1], "operator '<='");
|
||||||
SolGroundCodeBlock codeBlock;
|
SolGroundCodeBlock codeBlock;
|
||||||
if (children.size() < 2) {
|
if (children.size() < 2) {
|
||||||
std::cout << "Need more stuff to inequal\n";
|
Error::typingError("Need more stuff to inequal", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
std::string trueLabelIdString = "internal_true" + std::to_string(labelIterator++);
|
std::string trueLabelIdString = "internal_true" + std::to_string(labelIterator++);
|
||||||
@@ -469,7 +469,7 @@ namespace Solstice {
|
|||||||
exists(children[0]);
|
exists(children[0]);
|
||||||
GroundInstruction gi = groundCreateInstruction(PRINTLN);
|
GroundInstruction gi = groundCreateInstruction(PRINTLN);
|
||||||
if (children.size() < 1) {
|
if (children.size() < 1) {
|
||||||
std::cout << "Need more stuff to puts\n";
|
Error::typingError("Need more stuff to puts", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
groundAddReferenceToInstruction(&gi, groundCreateReference(VALREF, children[0].outputId.data()));
|
||||||
codeBlock.code.push_back(gi);
|
codeBlock.code.push_back(gi);
|
||||||
@@ -478,7 +478,7 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::If: {
|
case SolNodeType::If: {
|
||||||
ensure(children[0], SolDataType::Bool);
|
ensure(children[0], SolDataType::Bool, "if condition");
|
||||||
auto conditionCode = children[0].generateCode();
|
auto conditionCode = children[0].generateCode();
|
||||||
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
code.insert(code.end(), conditionCode.begin(), conditionCode.end());
|
||||||
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
outputId = "tmp_" + std::to_string(tmpIdIterator++);
|
||||||
@@ -510,7 +510,7 @@ namespace Solstice {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::While: {
|
case SolNodeType::While: {
|
||||||
ensure(children[0], SolDataType::Bool);
|
ensure(children[0], SolDataType::Bool, "while condition");
|
||||||
SolGroundCodeBlock startLabelBlock;
|
SolGroundCodeBlock startLabelBlock;
|
||||||
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
std::string startLabelIdString = "whilestart_" + std::to_string(labelIterator++);
|
||||||
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
std::string endLabelIdString = "whileend_" + std::to_string(labelIterator);
|
||||||
@@ -562,7 +562,7 @@ namespace Solstice {
|
|||||||
case SolNodeType::Set: {
|
case SolNodeType::Set: {
|
||||||
if (variables.find(children[0].outputId) != variables.end()) {
|
if (variables.find(children[0].outputId) != variables.end()) {
|
||||||
if (variables[children[0].outputId] != checkNodeReturnType(children[1])) {
|
if (variables[children[0].outputId] != checkNodeReturnType(children[1])) {
|
||||||
Error::typingError("Cannot change type of this variable");
|
Error::typingError("Cannot change type of this variable", children[0].line, children[0].lineContent);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exists(children[1]);
|
exists(children[1]);
|
||||||
@@ -580,7 +580,7 @@ namespace Solstice {
|
|||||||
case SolNodeType::FunctionCall: {
|
case SolNodeType::FunctionCall: {
|
||||||
// Take care of in built functions
|
// Take care of in built functions
|
||||||
if (children[0].outputId == "input") {
|
if (children[0].outputId == "input") {
|
||||||
ensure(children[1], SolDataType::String);
|
ensure(children[1], SolDataType::String, "input function argument");
|
||||||
SolGroundCodeBlock inputCodeBlock;
|
SolGroundCodeBlock inputCodeBlock;
|
||||||
if (children.size() > 1) {
|
if (children.size() > 1) {
|
||||||
GroundInstruction printInstruction = groundCreateInstruction(PRINT);
|
GroundInstruction printInstruction = groundCreateInstruction(PRINT);
|
||||||
@@ -604,9 +604,9 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Parser Implementation
|
// Parser Implementation
|
||||||
Parser::Parser(std::vector<std::string> in) : tokensToParse(in) {}
|
Parser::Parser(std::vector<Token> in) : tokensToParse(in) {}
|
||||||
|
|
||||||
std::optional<std::string> Parser::peek(int ahead) {
|
std::optional<Token> Parser::peek(int ahead) {
|
||||||
if (current + ahead < size) {
|
if (current + ahead < size) {
|
||||||
return tokensToParse[current + ahead];
|
return tokensToParse[current + ahead];
|
||||||
} else {
|
} else {
|
||||||
@@ -614,7 +614,7 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<std::string> Parser::consume() {
|
std::optional<Token> Parser::consume() {
|
||||||
if (current < size) {
|
if (current < size) {
|
||||||
return tokensToParse[current++];
|
return tokensToParse[current++];
|
||||||
} else {
|
} else {
|
||||||
@@ -752,14 +752,16 @@ namespace Solstice {
|
|||||||
SolNode Parser::parsePrimary() {
|
SolNode Parser::parsePrimary() {
|
||||||
auto tokenopt = consume();
|
auto tokenopt = consume();
|
||||||
if (!tokenopt) {
|
if (!tokenopt) {
|
||||||
std::cout << "Unexpected end of input\n";
|
Error::syntaxError("Unexpected end of input");
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
std::string token = tokenopt.value();
|
Token tokenObj = tokenopt.value();
|
||||||
|
std::string token = tokenObj.value;
|
||||||
SolNodeType type = getNodeType(token);
|
SolNodeType type = getNodeType(token);
|
||||||
|
|
||||||
if (type == SolNodeType::Value) {
|
if (type == SolNodeType::Value) {
|
||||||
SolNode node(SolNodeType::Value);
|
SolNode node(SolNodeType::Value);
|
||||||
|
node.line = tokenObj.line;
|
||||||
|
node.lineContent = tokenObj.lineContent;
|
||||||
switch (getDataType(token)) {
|
switch (getDataType(token)) {
|
||||||
case SolDataType::Int: node.setValue((int64_t) std::stoll(token)); break;
|
case SolDataType::Int: node.setValue((int64_t) std::stoll(token)); break;
|
||||||
case SolDataType::Double: node.setValue(std::stod(token)); break;
|
case SolDataType::Double: node.setValue(std::stod(token)); break;
|
||||||
@@ -774,19 +776,28 @@ namespace Solstice {
|
|||||||
if (type == SolNodeType::Identifier) {
|
if (type == SolNodeType::Identifier) {
|
||||||
SolNode idNode(SolNodeType::Identifier);
|
SolNode idNode(SolNodeType::Identifier);
|
||||||
idNode.outputId = token;
|
idNode.outputId = token;
|
||||||
if (peek().value_or("") == "(") {
|
idNode.line = tokenObj.line;
|
||||||
|
idNode.lineContent = tokenObj.lineContent;
|
||||||
|
|
||||||
|
auto peekOpt = peek();
|
||||||
|
if (peekOpt.has_value() && peekOpt.value().value == "(") {
|
||||||
consume(); // (
|
consume(); // (
|
||||||
SolNode fnCallNode(SolNodeType::FunctionCall);
|
SolNode fnCallNode(SolNodeType::FunctionCall);
|
||||||
|
fnCallNode.line = tokenObj.line;
|
||||||
|
fnCallNode.lineContent = tokenObj.lineContent;
|
||||||
fnCallNode.addNode(idNode);
|
fnCallNode.addNode(idNode);
|
||||||
|
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
while (auto t = consume()) {
|
while (auto t = consume()) {
|
||||||
if (t.value() == "(") brackets++;
|
if (t.value().value == "(") brackets++;
|
||||||
if (t.value() == ")") brackets--;
|
if (t.value().value == ")") brackets--;
|
||||||
if (brackets == 0) break;
|
if (brackets == 0) break;
|
||||||
tokens.push_back(t.value());
|
tokens.push_back(t.value());
|
||||||
}
|
}
|
||||||
|
if (brackets != 0) {
|
||||||
|
Error::syntaxError("Unclosed function call bracket", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
auto args = Parser(tokens).parse();
|
auto args = Parser(tokens).parse();
|
||||||
for(auto& child : args.children) fnCallNode.addNode(child);
|
for(auto& child : args.children) fnCallNode.addNode(child);
|
||||||
return fnCallNode;
|
return fnCallNode;
|
||||||
@@ -795,21 +806,23 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (type == SolNodeType::BracketStart) {
|
if (type == SolNodeType::BracketStart) {
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
while (auto t = consume()) {
|
while (auto t = consume()) {
|
||||||
if (t.value() == "(") brackets++;
|
if (t.value().value == "(") brackets++;
|
||||||
if (t.value() == ")") brackets--;
|
if (t.value().value == ")") brackets--;
|
||||||
if (brackets == 0) break;
|
if (brackets == 0) break;
|
||||||
tokens.push_back(t.value());
|
tokens.push_back(t.value());
|
||||||
}
|
}
|
||||||
|
if (brackets != 0) {
|
||||||
|
Error::syntaxError("Unclosed bracket", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
auto inner = Parser(tokens).parse();
|
auto inner = Parser(tokens).parse();
|
||||||
if (inner.children.size() > 0) return inner.children[0];
|
if (inner.children.size() > 0) return inner.children[0];
|
||||||
return SolNode(SolNodeType::None);
|
return SolNode(SolNodeType::None);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::cout << "Unexpected token in expression: " << token << "\n";
|
Error::syntaxError("Unexpected token in expression: " + token, tokenObj.line, tokenObj.lineContent);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SolNode Parser::parseExpression(int minPrec) {
|
SolNode Parser::parseExpression(int minPrec) {
|
||||||
@@ -817,13 +830,16 @@ namespace Solstice {
|
|||||||
while(true) {
|
while(true) {
|
||||||
auto opOpt = peek();
|
auto opOpt = peek();
|
||||||
if (!opOpt) break;
|
if (!opOpt) break;
|
||||||
std::string op = opOpt.value();
|
Token opToken = opOpt.value();
|
||||||
|
std::string op = opToken.value;
|
||||||
int prec = getPrecedence(op);
|
int prec = getPrecedence(op);
|
||||||
if (prec < minPrec) break;
|
if (prec < minPrec) break;
|
||||||
|
|
||||||
consume();
|
consume();
|
||||||
SolNode rhs = parseExpression(prec + 1);
|
SolNode rhs = parseExpression(prec + 1);
|
||||||
SolNode newNode(getNodeType(op));
|
SolNode newNode(getNodeType(op));
|
||||||
|
newNode.line = opToken.line;
|
||||||
|
newNode.lineContent = opToken.lineContent;
|
||||||
newNode.addNode(lhs);
|
newNode.addNode(lhs);
|
||||||
newNode.addNode(rhs);
|
newNode.addNode(rhs);
|
||||||
lhs = newNode;
|
lhs = newNode;
|
||||||
@@ -836,37 +852,48 @@ namespace Solstice {
|
|||||||
size = tokensToParse.size();
|
size = tokensToParse.size();
|
||||||
SolNode rootNode(SolNodeType::Root);
|
SolNode rootNode(SolNodeType::Root);
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
std::string token = tokenopt.value();
|
Token tokenObj = tokenopt.value();
|
||||||
|
std::string token = tokenObj.value;
|
||||||
switch (getNodeType(token)) {
|
switch (getNodeType(token)) {
|
||||||
case SolNodeType::Value: {
|
case SolNodeType::Value: {
|
||||||
switch (getDataType(token)) {
|
switch (getDataType(token)) {
|
||||||
case SolDataType::Int: {
|
case SolDataType::Int: {
|
||||||
SolNode intNode(SolNodeType::Value);
|
SolNode intNode(SolNodeType::Value);
|
||||||
intNode.setValue((int64_t) std::stoll(token));
|
intNode.setValue((int64_t) std::stoll(token));
|
||||||
|
intNode.line = tokenObj.line;
|
||||||
|
intNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(intNode);
|
rootNode.addNode(intNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolDataType::Double: {
|
case SolDataType::Double: {
|
||||||
SolNode doubleNode(SolNodeType::Value);
|
SolNode doubleNode(SolNodeType::Value);
|
||||||
doubleNode.setValue(std::stod(token));
|
doubleNode.setValue(std::stod(token));
|
||||||
|
doubleNode.line = tokenObj.line;
|
||||||
|
doubleNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(doubleNode);
|
rootNode.addNode(doubleNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolDataType::String: {
|
case SolDataType::String: {
|
||||||
SolNode stringNode(SolNodeType::Value);
|
SolNode stringNode(SolNodeType::Value);
|
||||||
stringNode.setValue(token.substr(1, token.size() - 2));
|
stringNode.setValue(token.substr(1, token.size() - 2));
|
||||||
|
stringNode.line = tokenObj.line;
|
||||||
|
stringNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(stringNode);
|
rootNode.addNode(stringNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolDataType::Char: {
|
case SolDataType::Char: {
|
||||||
SolNode charNode(SolNodeType::Value);
|
SolNode charNode(SolNodeType::Value);
|
||||||
charNode.setValue(token[1]);
|
charNode.setValue(token[1]);
|
||||||
|
charNode.line = tokenObj.line;
|
||||||
|
charNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(charNode);
|
rootNode.addNode(charNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolDataType::Bool: {
|
case SolDataType::Bool: {
|
||||||
SolNode boolNode(SolNodeType::Value);
|
SolNode boolNode(SolNodeType::Value);
|
||||||
boolNode.setValue(token == "true");
|
boolNode.setValue(token == "true");
|
||||||
|
boolNode.line = tokenObj.line;
|
||||||
|
boolNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(boolNode);
|
rootNode.addNode(boolNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -879,9 +906,11 @@ namespace Solstice {
|
|||||||
case SolNodeType::Divide:
|
case SolNodeType::Divide:
|
||||||
{
|
{
|
||||||
SolNode opNode(getNodeType(token));
|
SolNode opNode(getNodeType(token));
|
||||||
|
opNode.line = tokenObj.line;
|
||||||
|
opNode.lineContent = tokenObj.lineContent;
|
||||||
|
|
||||||
if (rootNode.children.empty()) {
|
if (rootNode.children.empty()) {
|
||||||
std::cout << "Expected operand before operator\n";
|
Error::syntaxError("Expected operand before operator", tokenObj.line, tokenObj.lineContent);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
opNode.addNode(rootNode.children.back());
|
opNode.addNode(rootNode.children.back());
|
||||||
rootNode.children.pop_back();
|
rootNode.children.pop_back();
|
||||||
@@ -901,15 +930,17 @@ namespace Solstice {
|
|||||||
case SolNodeType::EqGreater:
|
case SolNodeType::EqGreater:
|
||||||
{
|
{
|
||||||
SolNode equalNode(getNodeType(token));
|
SolNode equalNode(getNodeType(token));
|
||||||
|
equalNode.line = tokenObj.line;
|
||||||
|
equalNode.lineContent = tokenObj.lineContent;
|
||||||
|
|
||||||
if (rootNode.children.empty()) {
|
if (rootNode.children.empty()) {
|
||||||
std::cout << "ah dingus\n";
|
Error::syntaxError("Expected operand before comparison", tokenObj.line, tokenObj.lineContent);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
equalNode.addNode(rootNode.children.back());
|
equalNode.addNode(rootNode.children.back());
|
||||||
rootNode.children.pop_back();
|
rootNode.children.pop_back();
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "\n") {
|
if (tokenopt.value().value == "\n") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
@@ -921,9 +952,11 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
case SolNodeType::Puts: {
|
case SolNodeType::Puts: {
|
||||||
SolNode putsNode(SolNodeType::Puts);
|
SolNode putsNode(SolNodeType::Puts);
|
||||||
std::vector<std::string> tokens;
|
putsNode.line = tokenObj.line;
|
||||||
|
putsNode.lineContent = tokenObj.lineContent;
|
||||||
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "\n") {
|
if (tokenopt.value().value == "\n") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
@@ -937,9 +970,11 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
case SolNodeType::If: {
|
case SolNodeType::If: {
|
||||||
SolNode ifNode(SolNodeType::If);
|
SolNode ifNode(SolNodeType::If);
|
||||||
std::vector<std::string> tokens;
|
ifNode.line = tokenObj.line;
|
||||||
|
ifNode.lineContent = tokenObj.lineContent;
|
||||||
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "\n") {
|
if (tokenopt.value().value == "\n") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
@@ -950,27 +985,28 @@ namespace Solstice {
|
|||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
auto tokenopt = consume();
|
auto tokenopt = consume();
|
||||||
if (tokenopt) {
|
if (tokenopt) {
|
||||||
if (tokenopt.value() == "{") {
|
if (tokenopt.value().value == "{") {
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
if (tokenopt.value() == "{") {
|
if (tokenopt.value().value == "{") {
|
||||||
brackets++;
|
brackets++;
|
||||||
}
|
}
|
||||||
if (tokenopt.value() == "}") {
|
if (tokenopt.value().value == "}") {
|
||||||
brackets--;
|
brackets--;
|
||||||
}
|
}
|
||||||
if (brackets == 0) {
|
if (brackets == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (brackets != 0) {
|
||||||
std::cout << "I want a code block instead of a " + tokenopt.value() + "\n";
|
Error::syntaxError("Unclosed code block", tokenopt.value().line, tokenopt.value().lineContent);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "FEED ME MORE TOKENSSSSS\n";
|
Error::syntaxError("I want a code block instead of a " + tokenopt.value().value, tokenopt.value().line, tokenopt.value().lineContent);
|
||||||
exit(1);
|
}
|
||||||
|
} else {
|
||||||
|
Error::syntaxError("Expected code block after if condition", ifNode.line, ifNode.lineContent);
|
||||||
}
|
}
|
||||||
auto childCodeBlock = Parser(tokens).parse();
|
auto childCodeBlock = Parser(tokens).parse();
|
||||||
ifNode.addNode(childCodeBlock.children[0]);
|
ifNode.addNode(childCodeBlock.children[0]);
|
||||||
@@ -979,9 +1015,11 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
case SolNodeType::While: {
|
case SolNodeType::While: {
|
||||||
SolNode whileNode(SolNodeType::While);
|
SolNode whileNode(SolNodeType::While);
|
||||||
std::vector<std::string> tokens;
|
whileNode.line = tokenObj.line;
|
||||||
|
whileNode.lineContent = tokenObj.lineContent;
|
||||||
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "\n") {
|
if (tokenopt.value().value == "\n") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
@@ -992,27 +1030,28 @@ namespace Solstice {
|
|||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
auto tokenopt = consume();
|
auto tokenopt = consume();
|
||||||
if (tokenopt) {
|
if (tokenopt) {
|
||||||
if (tokenopt.value() == "{") {
|
if (tokenopt.value().value == "{") {
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
if (tokenopt.value() == "{") {
|
if (tokenopt.value().value == "{") {
|
||||||
brackets++;
|
brackets++;
|
||||||
}
|
}
|
||||||
if (tokenopt.value() == "}") {
|
if (tokenopt.value().value == "}") {
|
||||||
brackets--;
|
brackets--;
|
||||||
}
|
}
|
||||||
if (brackets == 0) {
|
if (brackets == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
if (brackets != 0) {
|
||||||
std::cout << "I want a code block instead of a " + tokenopt.value() + "\n";
|
Error::syntaxError("Unclosed code block", tokenopt.value().line, tokenopt.value().lineContent);
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
std::cout << "FEED ME MORE TOKENSSSSS\n";
|
Error::syntaxError("I want a code block instead of a " + tokenopt.value().value, tokenopt.value().line, tokenopt.value().lineContent);
|
||||||
exit(1);
|
}
|
||||||
|
} else {
|
||||||
|
Error::syntaxError("Expected code block after while condition", whileNode.line, whileNode.lineContent);
|
||||||
}
|
}
|
||||||
auto childCodeBlock = Parser(tokens).parse();
|
auto childCodeBlock = Parser(tokens).parse();
|
||||||
whileNode.addNode(childCodeBlock.children[0]);
|
whileNode.addNode(childCodeBlock.children[0]);
|
||||||
@@ -1021,13 +1060,15 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
case SolNodeType::CodeBlockStart: {
|
case SolNodeType::CodeBlockStart: {
|
||||||
SolNode codeBlockNode(SolNodeType::CodeBlock);
|
SolNode codeBlockNode(SolNodeType::CodeBlock);
|
||||||
|
codeBlockNode.line = tokenObj.line;
|
||||||
|
codeBlockNode.lineContent = tokenObj.lineContent;
|
||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "{") {
|
if (tokenopt.value().value == "{") {
|
||||||
brackets++;
|
brackets++;
|
||||||
}
|
}
|
||||||
if (tokenopt.value() == "}") {
|
if (tokenopt.value().value == "}") {
|
||||||
brackets--;
|
brackets--;
|
||||||
}
|
}
|
||||||
if (brackets == 0) {
|
if (brackets == 0) {
|
||||||
@@ -1035,6 +1076,9 @@ namespace Solstice {
|
|||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
}
|
}
|
||||||
|
if (brackets != 0) {
|
||||||
|
Error::syntaxError("Unclosed code block", tokenObj.line, tokenObj.lineContent);
|
||||||
|
}
|
||||||
codeBlockNode.children = Parser(tokens).parse().children;
|
codeBlockNode.children = Parser(tokens).parse().children;
|
||||||
rootNode.addNode(codeBlockNode);
|
rootNode.addNode(codeBlockNode);
|
||||||
break;
|
break;
|
||||||
@@ -1042,16 +1086,21 @@ namespace Solstice {
|
|||||||
case SolNodeType::Identifier: {
|
case SolNodeType::Identifier: {
|
||||||
SolNode idNode(SolNodeType::Identifier);
|
SolNode idNode(SolNodeType::Identifier);
|
||||||
idNode.outputId = token;
|
idNode.outputId = token;
|
||||||
|
idNode.line = tokenObj.line;
|
||||||
|
idNode.lineContent = tokenObj.lineContent;
|
||||||
rootNode.addNode(idNode);
|
rootNode.addNode(idNode);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case SolNodeType::Set: {
|
case SolNodeType::Set: {
|
||||||
SolNode setNode(SolNodeType::Set);
|
SolNode setNode(SolNodeType::Set);
|
||||||
|
setNode.line = tokenObj.line;
|
||||||
|
setNode.lineContent = tokenObj.lineContent;
|
||||||
|
|
||||||
setNode.addNode(rootNode.children.back());
|
setNode.addNode(rootNode.children.back());
|
||||||
rootNode.children.pop_back();
|
rootNode.children.pop_back();
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "\n") {
|
if (tokenopt.value().value == "\n") {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
tokens.push_back(tokenopt.value());
|
tokens.push_back(tokenopt.value());
|
||||||
@@ -1064,15 +1113,17 @@ namespace Solstice {
|
|||||||
case SolNodeType::BracketStart: {
|
case SolNodeType::BracketStart: {
|
||||||
if (rootNode.children.back().nodeType == SolNodeType::Identifier) {
|
if (rootNode.children.back().nodeType == SolNodeType::Identifier) {
|
||||||
SolNode fnCallNode(SolNodeType::FunctionCall);
|
SolNode fnCallNode(SolNodeType::FunctionCall);
|
||||||
|
fnCallNode.line = tokenObj.line;
|
||||||
|
fnCallNode.lineContent = tokenObj.lineContent;
|
||||||
fnCallNode.addNode(rootNode.children.back());
|
fnCallNode.addNode(rootNode.children.back());
|
||||||
rootNode.children.pop_back();
|
rootNode.children.pop_back();
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "(") {
|
if (tokenopt.value().value == "(") {
|
||||||
brackets++;
|
brackets++;
|
||||||
}
|
}
|
||||||
if (tokenopt.value() == ")") {
|
if (tokenopt.value().value == ")") {
|
||||||
brackets--;
|
brackets--;
|
||||||
}
|
}
|
||||||
if (brackets < 1) {
|
if (brackets < 1) {
|
||||||
@@ -1084,13 +1135,13 @@ namespace Solstice {
|
|||||||
fnCallNode.children.insert(fnCallNode.children.end(), node.children.begin(), node.children.end());
|
fnCallNode.children.insert(fnCallNode.children.end(), node.children.begin(), node.children.end());
|
||||||
rootNode.addNode(fnCallNode);
|
rootNode.addNode(fnCallNode);
|
||||||
} else {
|
} else {
|
||||||
std::vector<std::string> tokens;
|
std::vector<Token> tokens;
|
||||||
size_t brackets = 1;
|
size_t brackets = 1;
|
||||||
while (auto tokenopt = consume()) {
|
while (auto tokenopt = consume()) {
|
||||||
if (tokenopt.value() == "(") {
|
if (tokenopt.value().value == "(") {
|
||||||
brackets++;
|
brackets++;
|
||||||
}
|
}
|
||||||
if (tokenopt.value() == ")") {
|
if (tokenopt.value().value == ")") {
|
||||||
brackets--;
|
brackets--;
|
||||||
}
|
}
|
||||||
if (brackets < 1) {
|
if (brackets < 1) {
|
||||||
|
|||||||
31
src/parser.h
31
src/parser.h
@@ -7,32 +7,34 @@
|
|||||||
#include <optional>
|
#include <optional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <variant>
|
#include <variant>
|
||||||
|
#include "lexer.h"
|
||||||
|
#include "error.h"
|
||||||
|
|
||||||
#define ensure(node, datatype) \
|
#define ensure(node, datatype, op) \
|
||||||
if (checkNodeReturnType(node) != datatype) { \
|
if (checkNodeReturnType(node) != datatype) { \
|
||||||
Error::typingError("Expected " #datatype); \
|
Error::typingError("Expected " #datatype " for " op, node.line, node.lineContent); \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensure2(node, datatype1, datatype2) { \
|
#define ensure2(node, datatype1, datatype2, op) { \
|
||||||
SolDataType dataType = checkNodeReturnType(node); \
|
SolDataType dataType = checkNodeReturnType(node); \
|
||||||
if (!(dataType == datatype1 || dataType == datatype2)) { \
|
if (!(dataType == datatype1 || dataType == datatype2)) { \
|
||||||
Error::typingError("Expected either " #datatype1 " or " #datatype2); \
|
Error::typingError("Expected either " #datatype1 " or " #datatype2 " for " op, node.line, node.lineContent); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensure3(node, datatype1, datatype2, datatype3) { \
|
#define ensure3(node, datatype1, datatype2, datatype3, op) { \
|
||||||
SolDataType dataType = checkNodeReturnType(node); \
|
SolDataType dataType = checkNodeReturnType(node); \
|
||||||
if (!(dataType == datatype1 || dataType == datatype2 || dataType == datatype3)) { \
|
if (!(dataType == datatype1 || dataType == datatype2 || dataType == datatype3)) { \
|
||||||
Error::typingError("Expected either " #datatype1 ", " #datatype2 ", or " #datatype3); \
|
Error::typingError("Expected either " #datatype1 ", " #datatype2 ", or " #datatype3 " for " op, node.line, node.lineContent); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ensuresame(node1, node2) { \
|
#define ensuresame(node1, node2, op) { \
|
||||||
SolDataType n1t = checkNodeReturnType(node1); \
|
SolDataType n1t = checkNodeReturnType(node1); \
|
||||||
SolDataType n2t = checkNodeReturnType(node2); \
|
SolDataType n2t = checkNodeReturnType(node2); \
|
||||||
if (n1t != n2t) { \
|
if (n1t != n2t) { \
|
||||||
if (!(n1t == SolDataType::Int && n2t == SolDataType::Double || n1t == SolDataType::Double && n2t == SolDataType::Int)) { \
|
if (!(n1t == SolDataType::Int && n2t == SolDataType::Double || n1t == SolDataType::Double && n2t == SolDataType::Int)) { \
|
||||||
Error::typingError("Expected types to be the same"); \
|
Error::typingError("Expected types to be the same for " op, node1.line, node1.lineContent); \
|
||||||
} \
|
} \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
@@ -40,7 +42,7 @@
|
|||||||
#define exists(node) \
|
#define exists(node) \
|
||||||
if (node.nodeType == SolNodeType::Identifier) { \
|
if (node.nodeType == SolNodeType::Identifier) { \
|
||||||
if (variables.find(node.outputId) == variables.end()) { \
|
if (variables.find(node.outputId) == variables.end()) { \
|
||||||
Error::syntaxError("Variable does not exist"); \
|
Error::syntaxError("Variable does not exist", node.line, node.lineContent); \
|
||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -96,6 +98,9 @@ namespace Solstice {
|
|||||||
SolNodeType nodeType = SolNodeType::None;
|
SolNodeType nodeType = SolNodeType::None;
|
||||||
std::vector<SolNode> children;
|
std::vector<SolNode> children;
|
||||||
std::string outputId;
|
std::string outputId;
|
||||||
|
int line = 0;
|
||||||
|
std::string lineContent = "";
|
||||||
|
|
||||||
SolNode(SolNodeType nodeType);
|
SolNode(SolNodeType nodeType);
|
||||||
SolNode(SolNodeType nodeType, SolData data);
|
SolNode(SolNodeType nodeType, SolData data);
|
||||||
SolNode() = default;
|
SolNode() = default;
|
||||||
@@ -105,12 +110,12 @@ namespace Solstice {
|
|||||||
};
|
};
|
||||||
|
|
||||||
class Parser {
|
class Parser {
|
||||||
std::vector<std::string> tokensToParse;
|
std::vector<Token> tokensToParse;
|
||||||
size_t current;
|
size_t current;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
|
||||||
std::optional<std::string> peek(int ahead = 0);
|
std::optional<Token> peek(int ahead = 0);
|
||||||
std::optional<std::string> consume();
|
std::optional<Token> consume();
|
||||||
bool isInt(std::string in);
|
bool isInt(std::string in);
|
||||||
bool isDouble(std::string in);
|
bool isDouble(std::string in);
|
||||||
bool isString(std::string in);
|
bool isString(std::string in);
|
||||||
@@ -124,7 +129,7 @@ namespace Solstice {
|
|||||||
int getPrecedence(std::string token);
|
int getPrecedence(std::string token);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Parser(std::vector<std::string> in);
|
Parser(std::vector<Token> in);
|
||||||
SolNode parse();
|
SolNode parse();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user