First commit

This commit is contained in:
2024-12-28 14:38:00 -06:00
commit 9c27f339be
56 changed files with 289761 additions and 0 deletions

151
src/compiler/ast.cpp Normal file
View File

@ -0,0 +1,151 @@
#include "CrossLang.hpp"
#if defined(CROSSLANG_ENABLE_JSON)
#include <jansson.h>
#endif
namespace Tesses::CrossLang
{
AdvancedSyntaxNode AdvancedSyntaxNode::Create(std::string_view nodeName,bool isExpression, std::vector<SyntaxNode> nodes)
{
AdvancedSyntaxNode asn;
asn.nodeName = std::string(nodeName);
asn.isExpression = isExpression;
asn.nodes = nodes;
return asn;
}
#if defined(CROSSLANG_ENABLE_JSON)
static SyntaxNode Deserialize2(json_t* json)
{
if(json_is_null(json)) return nullptr;
if(json_is_true(json)) return true;
if(json_is_false(json)) return false;
if(json_is_integer(json)) return (int64_t)json_integer_value(json);
if(json_is_real(json)) return json_real_value(json);
if(json_is_string(json)) return std::string(json_string_value(json),json_string_length(json));
if(json_is_object(json))
{
json_t* typ = json_object_get(json, "type");
if(json_is_string(typ))
{
std::string type(json_string_value(typ),json_string_length(typ));
if(type == CharExpression)
{
json_t* chrData = json_object_get(json,"value");
if(json_is_integer(chrData))
{
return (char)(uint8_t)json_integer_value(chrData);
}
}
if(type == UndefinedExpression)
{
return Undefined();
}
json_t* isExpr = json_object_get(json,"isExpression");
bool isExprB = json_is_true(isExpr);
AdvancedSyntaxNode asn;
asn.nodeName = type;
asn.isExpression = isExprB;
json_t* args = json_object_get(json, "args");
if(json_is_array(args))
{
size_t index;
json_t* value;
json_array_foreach(args, index, value)
{
asn.nodes.push_back(Deserialize2(value));
}
}
return asn;
}
}
return nullptr;
}
#endif
SyntaxNode Deserialize(std::string astData)
{
#if defined(CROSSLANG_ENABLE_JSON)
json_t* json = json_loadb(astData.c_str(),astData.size(), 0, NULL);
auto r = Deserialize2(json);
json_decref(json);
return r;
#endif
return nullptr;
}
#if defined(CROSSLANG_ENABLE_JSON)
static json_t* Serialize2(SyntaxNode node)
{
if(std::holds_alternative<std::nullptr_t>(node))
return json_null();
if(std::holds_alternative<int64_t>(node))
{
return json_integer(std::get<int64_t>(node));
}
if(std::holds_alternative<double>(node))
{
return json_real(std::get<double>(node));
}
if(std::holds_alternative<bool>(node))
{
return json_boolean(std::get<bool>(node));
}
if(std::holds_alternative<std::string>(node))
{
std::string str = std::get<std::string>(node);
return json_stringn(str.c_str(),str.size());
}
if(std::holds_alternative<char>(node))
{
char c = std::get<char>(node);
json_t* json = json_object();
json_object_set_new(json,"type",json_string(CharExpression.begin()));
json_object_set_new(json, "value", json_integer((uint8_t)c));
return json;
}
if(std::holds_alternative<Undefined>(node))
{
json_t* json = json_object();
json_object_set_new(json,"type",json_string(UndefinedExpression.begin()));
return json;
}
if(std::holds_alternative<AdvancedSyntaxNode>(node))
{
auto asn = std::get<AdvancedSyntaxNode>(node);
json_t* j = json_object();
json_object_set_new(j, "type", json_string(asn.nodeName.c_str()));
json_object_set_new(j, "isExpression",json_boolean(asn.isExpression));
json_t* arr=json_array();
for(auto item : asn.nodes)
{
json_array_append_new(arr,Serialize2(item));
}
json_object_set_new(j, "args", arr);
return j;
}
return json_null();
}
#endif
std::string Serialize(SyntaxNode node)
{
#if defined(CROSSLANG_ENABLE_JSON)
json_t* json = Serialize2(node);
char* txt = json_dumps(json,0);
std::string str(txt);
free(json);
json_decref(json);
return str;
#endif
return "";
}
}

1251
src/compiler/codegen.cpp Normal file

File diff suppressed because it is too large Load Diff

687
src/compiler/lexer.cpp Normal file
View File

@ -0,0 +1,687 @@
#include "CrossLang.hpp"
#include <iostream>
namespace Tesses::CrossLang
{
std::string EscapeString(std::string text,bool quote)
{
std::string str={};
if(quote) str.push_back('\"');
for(auto item : text)
{
if(item == '\\' || item == '\"' || item == '\'')
{
str.push_back('\\');
str.push_back(item);
}
else if(item == '\n')
{
str.push_back('\\');
str.push_back('n');
}
else if(item == '\r')
{
str.push_back('\\');
str.push_back('r');
}
else if(item == '\t')
{
str.push_back('\\');
str.push_back('t');
}
else if(item == '\f')
{
str.push_back('\\');
str.push_back('f');
}
else if(item == '\0')
{
str.push_back('\\');
str.push_back('0');
}
else if(item == '\b')
{
str.push_back('\\');
str.push_back('b');
}
else if(item == '\a')
{
str.push_back('\\');
str.push_back('a');
}
else if(item == '\v')
{
str.push_back('\\');
str.push_back('v');
}
else if(item == '\e')
{
str.push_back('\\');
str.push_back('e');
}
else if((uint8_t)item < 32 || (uint8_t)item > 126)
{
str.append("\\x");
str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex(((uint8_t)item >> 4)&0x0F));
str.push_back(Tesses::Framework::Http::HttpUtils::NibbleToHex((uint8_t)item & 0x0F));
}
else
{
str.push_back(item);
}
}
if(quote) str.push_back('\"');
return str;
}
void LexTokenLineInfo::Subtract(size_t len)
{
this->offset -= len;
this->column -= len;
}
void LexTokenLineInfo::Add(int c)
{
this->offset++;
switch(c)
{
case ' ':
this->column++;
break;
case '\n':
this->column=1;
this->line++;
break;
case '\t':
this->column += 4;
break;
case '\r':
this->column++;
break;
default:
this->column++;
break;
}
}
int Lex(std::string filename, std::istream& strm, std::vector<LexToken>& tokens)
{
int _peeked=-1;
auto Read = [&_peeked,&strm]()->int {
if(_peeked > -1)
{
int _peek2 = _peeked;
_peeked=-1;
return _peek2;
}
uint8_t b;
strm.read((char*)&b,1);
if(strm.eof()) return -1;
return b;
};
auto Peek = [&_peeked,Read]()->int {
if(_peeked > -1) return _peeked;
_peeked = Read();
return _peeked;
};
int read;
int peek;
std::string buffer={};
LexTokenLineInfo lineInfo;
lineInfo.filename = filename;
lineInfo.column = 1;
lineInfo.line = 1;
lineInfo.offset = 0;
auto Flush = [&buffer,&tokens,&lineInfo]() -> void {
if(!buffer.empty())
{
LexToken token;
token.text = buffer;
token.type = LexTokenType::Identifier;
token.lineInfo = lineInfo;
token.lineInfo.Subtract(buffer.size());
tokens.push_back(token);
buffer.clear();
}
};
auto Symbol = [&tokens,&lineInfo](std::initializer_list<int> chrs)-> void {
LexToken token;
token.type = LexTokenType::Symbol;
token.lineInfo = lineInfo;
token.text.reserve(chrs.size());
for(auto i : chrs)
token.text.push_back((char)i);
tokens.push_back(token);
};
auto ReadChr = [&lineInfo, &strm, Read]() -> std::pair<int,bool> {
int read=Read();
lineInfo.Add(read);
if(read == -1)
{
return std::pair<int,bool>(-1,false);
}
if(read == '\\')
{
read = Read();
lineInfo.Add(read);
if(read == -1)
{
return std::pair<int,bool>(-1,true);
}
else if(read == 'n')
{
return std::pair<int,bool>('\n',true);
}
else if(read == 'r')
{
return std::pair<int,bool>('\r',true);
}
else if(read == 'f')
{
return std::pair<int,bool>('\f',true);
}
else if(read == 'b')
{
return std::pair<int,bool>('\b',true);
}
else if(read == 'a')
{
return std::pair<int,bool>('\a',true);
}
else if(read == '0')
{
return std::pair<int,bool>('\0',true);
}
else if(read == 'v')
{
return std::pair<int,bool>('\v',true);
}
else if(read == 'e')
{
return std::pair<int,bool>('\e',true);
}
else if(read == 't')
{
return std::pair<int,bool>('\t',true);
}
else if(read == 'x')
{
int r1 = Read();
lineInfo.Add(r1);
if(r1 == -1)
{
return std::pair<int,bool>(-1,true);
}
int r2 = Read();
lineInfo.Add(r2);
if(r2 == -1)
{
return std::pair<int,bool>(-1,true);
}
uint8_t c = (uint8_t)std::stoi(std::string{(char)r1,(char)r2},nullptr,16);
return std::pair<int,bool>(c,true);
}
else
{
return std::pair<int,bool>(read,true);
}
}
else
{
return std::pair<int,bool>(read,false);
}
};
auto ParseString = [&lineInfo, &strm, Read, ReadChr,&tokens](bool interopolated)->int {
auto lI = lineInfo;
std::string b={};
auto rChr = ReadChr();
lineInfo.Add(rChr.first);
while(rChr.first != '\"' || rChr.second)
{
if(rChr.first == -1) return lineInfo.line;
b.push_back((char)rChr.first);
rChr = ReadChr();
lineInfo.Add(rChr.first);
}
if(interopolated)
{
int e = 0;
int escapeI = 0;
std::string b2 = {};
for(size_t i = 0; i< b.size();i++)
{
if(b[i] == '{')
{
if((i+1 < b.size() && b[i+1] != '{') || escapeI >= 1)
{
if(b2.size() > 0 && escapeI < 1)
{
if(e > 0)
{
LexToken _tkn;
_tkn.type = LexTokenType::Symbol;
_tkn.text = "+";
_tkn.lineInfo = lI;
tokens.push_back(_tkn);
}
LexToken _tkn2;
_tkn2.type = LexTokenType::String;
_tkn2.text = b2;
_tkn2.lineInfo = lI;
tokens.push_back(_tkn2);
b2.clear();
e++;
}
escapeI++;
if(escapeI > 1)
{
b2.push_back('{');
}
}
else
{
b2.push_back('{');
i++;
}
}
else if(b[i] == '}')
{
if(escapeI >= 1)
{
escapeI--;
if(b2.size() > 0 && escapeI == 0)
{
if(e > 0)
{
LexToken _tkn;
_tkn.type = LexTokenType::Symbol;
_tkn.text = "+";
_tkn.lineInfo = lI;
tokens.push_back(_tkn);
}
LexToken _tkn2;
_tkn2.type = LexTokenType::Symbol;
_tkn2.text = "(";
_tkn2.lineInfo = lI;
tokens.push_back(_tkn2);
std::stringstream strm2(b2,std::ios_base::in | std::ios_base::binary);
int res = Lex("lexGen", strm2, tokens);
if(res != 0) return res;
_tkn2.text = ")";
tokens.push_back(_tkn2);
_tkn2.text = ".";
tokens.push_back(_tkn2);
_tkn2.type = LexTokenType::Identifier;
_tkn2.text = "ToString";
tokens.push_back(_tkn2);
_tkn2.type = LexTokenType::Symbol;
_tkn2.text = "(";
tokens.push_back(_tkn2);
_tkn2.text = ")";
tokens.push_back(_tkn2);
b2.clear();
e++;
}
if(escapeI >= 1)
{
b2.push_back('}');
}
}
} else {
b2.push_back(b[i]);
}
}
if(b2.size() > 0)
{
if(escapeI > 0)
{
if(e > 0)
{
LexToken _tkn;
_tkn.type = LexTokenType::Symbol;
_tkn.text = "+";
_tkn.lineInfo = lI;
tokens.push_back(_tkn);
}
LexToken _tkn2;
_tkn2.type = LexTokenType::Symbol;
_tkn2.text = "(";
_tkn2.lineInfo = lI;
tokens.push_back(_tkn2);
std::stringstream strm2(b2,std::ios_base::in | std::ios_base::binary);
int res = Lex("lexGen", strm2, tokens);
if(res != 0) return res;
_tkn2.text = ")";
tokens.push_back(_tkn2);
_tkn2.text = ".";
tokens.push_back(_tkn2);
_tkn2.type = LexTokenType::Identifier;
_tkn2.text = "ToString";
tokens.push_back(_tkn2);
_tkn2.type = LexTokenType::Symbol;
_tkn2.text = "(";
tokens.push_back(_tkn2);
_tkn2.text = ")";
tokens.push_back(_tkn2);
b2.clear();
e++;
}
else
{
if(e > 0)
{
LexToken _tkn;
_tkn.type = LexTokenType::Symbol;
_tkn.text = "+";
_tkn.lineInfo = lI;
tokens.push_back(_tkn);
}
LexToken _tkn2;
_tkn2.type = LexTokenType::String;
_tkn2.text = b2;
_tkn2.lineInfo = lI;
tokens.push_back(_tkn2);
b2.clear();
e++;
}
}
} else {
LexToken _tkn2;
_tkn2.type = LexTokenType::String;
_tkn2.text = b;
_tkn2.lineInfo = lI;
tokens.push_back(_tkn2);
}
return 0;
};
while((read = Read()) != -1)
{
peek = Peek();
switch(read)
{
case '$':
if(peek == '\"')
{
Flush();
lineInfo.Add(Read());
int re = ParseString(true);
if(re != 0) return re;
}
else
{
Flush();
Symbol({read});
}
break;
case '\"':
{
Flush();
int re = ParseString(false);
if(re != 0) return re;
}
break;
case '\'':
{
Flush();
auto res = ReadChr();
if(res.first == -1) return lineInfo.line;
int r = Read();
lineInfo.Add(r);
if(r != '\'')
return lineInfo.line;
LexToken token;
token.text = {(char)(uint8_t)res.first};
token.lineInfo = lineInfo;
token.type = LexTokenType::Char;
tokens.push_back(token);
}
break;
case '#':
Flush();
while(true)
{
int r = Read();
lineInfo.Add(r);
if(r == '\n' || r == -1) break;
}
break;
case '/':
if(peek == '/')
{
Flush();
while(true)
{
int r = Read();
lineInfo.Add(r);
if(r == '\n' || r == -1) break;
}
}
else if(peek == '*')
{
Flush();
while(true)
{
int r = Read();
lineInfo.Add(r);
if(r == -1)
{
return lineInfo.line;
}
if(r == '*')
{
r = Read();
lineInfo.Add(r);
if(r == -1)
return lineInfo.line;
if(r == '/')
break;
}
}
}
else if(peek == '^')
{
Flush();
lineInfo.Add(Read());
std::string str={};
while(true)
{
int r = Read();
std::cout << r <<std::endl;
lineInfo.Add(r);
if(r == -1)
{
return lineInfo.line;
}
if(r == '^')
{
r = Read();
lineInfo.Add(r);
if(r == -1)
return lineInfo.line;
if(r == '^')
{
str.push_back('^');
continue;
}
if(r == '/')
break;
str.push_back('^');
}
str.push_back((char)r);
}
LexToken token;
token.type = LexTokenType::Documentation;
token.lineInfo = lineInfo;
token.text = str;
tokens.push_back(token);
}
else if(peek == '=')
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else
{
Flush();
Symbol({read});
}
break;
case '<':
case '>':
if(peek == read)
{
Flush();
lineInfo.Add(Read());
int peek2=Peek();
if(peek2 == '=')
{
lineInfo.Add(Read());
Symbol({read,peek,peek2});
}
else
{
Symbol({read,peek});
}
}
else if(peek == '=')
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else
{
Flush();
Symbol({read});
}
break;
case '+':
case '-':
case '|':
case '&':
if(peek == '=' || peek == read)
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else
{
Flush();
Symbol({read});
}
break;
case '=':
if(peek == '>')
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else if(peek == '=')
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else
{
Flush();
Symbol({read});
}
break;
case '^':
case '~':
case '!':
case '*':
case '%':
//*
//*=
if(peek == '=')
{
Flush();
lineInfo.Add(Read());
Symbol({read,peek});
}
else
{
Flush();
Symbol({read});
}
break;
case '(':
case ')':
case '[':
case ']':
case '{':
case '}':
case '.':
case ':':
case ';':
case ',':
case '?':
Flush();
Symbol({read});
break;
case '\n':
case '\t':
case '\r':
case ' ':
Flush();
break;
default:
buffer.push_back((char)read);
break;
}
lineInfo.Add(read);
}
Flush();
return 0;
}
}

750
src/compiler/parser.cpp Normal file
View File

@ -0,0 +1,750 @@
#include "CrossLang.hpp"
#include <iostream>
namespace Tesses::CrossLang
{
std::string LexTokenType_ToString(LexTokenType t)
{
switch(t)
{
case LexTokenType::Char:
return "char";
case LexTokenType::Documentation:
return "documentation";
case LexTokenType::Identifier:
return "identifier";
case LexTokenType::String:
return "string";
case LexTokenType::Symbol:
return "symbol";
}
return "";
}
bool Parser::IsAnyIdentifier(std::initializer_list<std::string> idents, bool pop)
{
if(i < tokens.size())
{
if(tokens[i].type != LexTokenType::Identifier) return false;
for(auto item : idents)
{
if(item == tokens[i].text)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
}
return false;
}
bool Parser::IsIdentifier(std::string txt,bool pop)
{
if(i < tokens.size())
{
if(tokens[i].type != LexTokenType::Identifier) return false;
if(tokens[i].text == txt)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
return false;
}
bool Parser::IsAnySymbol(std::initializer_list<std::string> idents, bool pop)
{
if(i < tokens.size())
{
if(tokens[i].type != LexTokenType::Symbol) return false;
for(auto item : idents)
{
if(item == tokens[i].text)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
}
return false;
}
bool Parser::IsSymbol(std::string txt,bool pop)
{
if(i < tokens.size())
{
if(tokens[i].type != LexTokenType::Symbol) return false;
if(tokens[i].text == txt)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
return false;
}
void Parser::EnsureSymbol(std::string txt)
{
if(i < tokens.size())
{
if(tokens[i].type != LexTokenType::Symbol)
{
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the " + LexTokenType_ToString(tokens[i].type) + " \"" + tokens[i].text + "\" which is not a symbol at all.");
}
if(tokens[i].text != txt)
{
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\"");
}
tkn = tokens[i];
i++;
return;
}
throw std::out_of_range("End of file");
}
Parser::Parser(std::vector<LexToken> tokens)
{
this->i = 0;
this->tokens = tokens;
}
SyntaxNode Parser::ParseValue()
{
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto tkn2 = tokens[i];
SyntaxNode node = nullptr;
if(tokens[i].type == LexTokenType::String)
{
node = tkn2.text;
i++;
}
else if(tokens[i].type == LexTokenType::Char)
{
node = tkn2.text.empty() ? '\0' : tkn2.text.front();
i++;
}
else if(IsSymbol("["))
{
if(IsSymbol("]",false))
node = AdvancedSyntaxNode::Create(ArrayExpression, true, {});
else
node = AdvancedSyntaxNode::Create(ArrayExpression, true, {ParseExpression()});
EnsureSymbol("]");
}
else if(IsSymbol("{"))
{
if(IsSymbol("}",false))
node = AdvancedSyntaxNode::Create(DictionaryExpression,true,{});
else
node = AdvancedSyntaxNode::Create(DictionaryExpression,true,{ParseExpression()});
EnsureSymbol("}");
}
else if(IsSymbol("("))
{
if(IsSymbol(")",false))
node = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{});
else
node = AdvancedSyntaxNode::Create(ParenthesesExpression,true,{ParseExpression()});
EnsureSymbol(")");
}
else if(IsIdentifier("var"))
{
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto variable = tokens[i];
i++;
if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{variable.text});
}
else if(IsIdentifier("operator"))
{
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto variable = tokens[i];
i++;
if(variable.type != LexTokenType::Identifier && variable.type != LexTokenType::Symbol) throw SyntaxException(variable.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
node = AdvancedSyntaxNode::Create(GetVariableExpression, true,{"operator"+variable.text});
}
else if(IsIdentifier("embed"))
{
EnsureSymbol("(");
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto embed = tokens[i];
i++;
if(embed.type != LexTokenType::String) throw SyntaxException(embed.lineInfo, "Expected an string for embed got a " + LexTokenType_ToString(embed.type) + " \"" + embed.text + "\"");
EnsureSymbol(")");
node = AdvancedSyntaxNode::Create(EmbedExpression, true,{embed.text});
}
else if(tokens[i].type == LexTokenType::Identifier)
{
std::string token = tokens[i].text;
i++;
bool hasNumber=true;
int64_t lngNum = 0;
if(token.size() == 1 && token[0] == '0')
{
lngNum = 0;
}
else
if(token.size() > 0 && token[0] == '0')
{
if(token.size() > 1 && token[1] == 'x')
{
lngNum = std::stoll(token.substr(2),nullptr,16);
}
else if(token.size() > 1 && token[1] == 'b')
{
lngNum = std::stoll(token.substr(2),nullptr,2);
}
else
{
lngNum = std::stoll(token.substr(1),nullptr,8);
}
}
else if(token.size() > 0 && token[0] >= '0' && token[0] <= '9')
{
lngNum=std::stoll(token,nullptr,10);
}
else
{
hasNumber = false;
}
if(hasNumber && this->IsSymbol(".",false) && i+1 < tokens.size() && tokens[i+1].type == LexTokenType::Identifier)
{
std::string myToken = tokens[i+1].text;
if(myToken.size() > 0 && myToken[0] >= '0' && myToken[0] <= '9')
{
i+=2;
std::string myN = std::to_string(lngNum) + "." + myToken;
double v = std::stod(myN,nullptr);
node = v;
}
else
{
node = lngNum;
}
}
else if(hasNumber)
{
node = lngNum;
}
if(!hasNumber)
{
if(token == "true")
node = true;
else if(token == "false")
node = false;
else if(token == "null")
node = nullptr;
else if(token == "undefined")
node = Undefined();
else {
node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{token});
}
}
}
if(IsSymbol("=>"))
{
if(IsSymbol("{",false))
{
node = AdvancedSyntaxNode::Create(ClosureExpression,true,{node,ParseNode()});
}
else
{
node = AdvancedSyntaxNode::Create(ClosureExpression,true,{node, AdvancedSyntaxNode::Create(ReturnStatement,false,{ParseExpression()})});
}
}
while(IsAnySymbol({".","[","("}))
{
if(tkn.text == ".")
{
if(i>=tokens.size()) throw std::out_of_range("End of file");
if(tokens[i].type != LexTokenType::Identifier) throw std::exception();
std::string name = tokens[i].text;
if(name == "operator")
{
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto op = tokens[i];
if(op.type != LexTokenType::Identifier && op.type != LexTokenType::Symbol) throw SyntaxException(op.lineInfo, "Expected an identifier or a symbol got a " + LexTokenType_ToString(op.type) + " \"" + op.text + "\"");
name += tokens[i+1].text;
i++;
}
i++;
node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {node, name});
}
else if(tkn.text == "[")
{
node = AdvancedSyntaxNode::Create(GetArrayExpression,true,{node,ParseExpression()});
EnsureSymbol("]");
}
else if(tkn.text == "(")
{
if(IsSymbol(")",false))
{
node = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{node});
}
else
{
node = AdvancedSyntaxNode::Create(FunctionCallExpression,true,{node,ParseExpression()});
}
EnsureSymbol(")");
}
}
if(IsSymbol("++"))
{
node = AdvancedSyntaxNode::Create(PostfixIncrementExpression,true,{node});
}
else if(IsSymbol("--"))
{
node = AdvancedSyntaxNode::Create(PostfixDecrementExpression,true,{node});
}
return node;
}
SyntaxNode Parser::ParseUnary()
{
if(IsSymbol("-"))
{
return AdvancedSyntaxNode::Create(NegativeExpression,true,{ParseUnary()});
}
else if(IsSymbol("!"))
{
return AdvancedSyntaxNode::Create(NotExpression,true,{ParseUnary()});
}
else if(IsSymbol("~"))
{
return AdvancedSyntaxNode::Create(BitwiseNotExpression,true,{ParseUnary()});
}
else if(IsSymbol("++"))
{
return AdvancedSyntaxNode::Create(PrefixIncrementExpression,true,{ParseUnary()});
}
else if(IsSymbol("--"))
{
return AdvancedSyntaxNode::Create(PrefixDecrementExpression,true,{ParseUnary()});
}
return ParseValue();
}
SyntaxNode Parser::ParseFactor()
{
SyntaxNode expr = ParseUnary();
while(IsAnySymbol({"*","/","%"},true))
{
if(tkn.text == "*")
{
expr = AdvancedSyntaxNode::Create(TimesExpression, true, {expr,ParseUnary()});
}
else if(tkn.text == "/")
{
expr = AdvancedSyntaxNode::Create(DivideExpression, true, {expr,ParseUnary()});
}
else if(tkn.text == "%")
{
expr = AdvancedSyntaxNode::Create(ModExpression, true, {expr,ParseUnary()});
}
}
return expr;
}
SyntaxNode Parser::ParseSum()
{
SyntaxNode expr = ParseFactor();
while(IsAnySymbol({"+","-"},true))
{
if(tkn.text == "+")
{
expr = AdvancedSyntaxNode::Create(AddExpression, true, {expr,ParseFactor()});
}
else if(tkn.text == "-")
{
expr = AdvancedSyntaxNode::Create(SubExpression, true, {expr,ParseFactor()});
}
}
return expr;
}
SyntaxNode Parser::ParseAssignment()
{
SyntaxNode node = ParseTernary();
if(IsSymbol("="))
{
return AdvancedSyntaxNode::Create(AssignExpression,true,{node,ParseAssignment()});
}
else if(IsSymbol("+="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("-="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(SubExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("*="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(TimesExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("/="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(DivideExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("%="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(ModExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("<<="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(LeftShiftExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol(">>="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(RightShiftExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("|="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(BitwiseOrExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("&="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(BitwiseAndExpression,true,{ node,ParseAssignment()})});
}
else if(IsSymbol("^="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(XOrExpression,true,{ node,ParseAssignment()})});
}
return node;
}
SyntaxNode Parser::ParseNode(bool isRoot)
{
if(i < tokens.size() && !isRoot && tokens[i].type == Documentation)
{
auto txt = tokens[i].text;
i++;
return AdvancedSyntaxNode::Create(DocumentationStatement,false,{txt,ParseNode()});
}
if(IsSymbol("{") || isRoot)
{
AdvancedSyntaxNode aSN;
aSN.isExpression=false;
aSN.nodeName = isRoot ? NodeList : ScopeNode;
while(i < tokens.size() && (isRoot || !IsSymbol("}",false)))
{
aSN.nodes.push_back(ParseNode());
IsSymbol(";");
}
if(!isRoot) i++;
return aSN;
}
if(IsIdentifier("if"))
{
EnsureSymbol("(");
SyntaxNode cond = ParseExpression();
EnsureSymbol(")");
SyntaxNode truthy = nullptr;
SyntaxNode falsey = nullptr;
if(!IsIdentifier("else",false))
{
truthy = ParseNode();
}
if(IsIdentifier("else"))
{
falsey = ParseNode();
}
return AdvancedSyntaxNode::Create(IfStatement, false, {cond, truthy,falsey});
}
if(IsIdentifier("while"))
{
EnsureSymbol("(");
SyntaxNode cond = ParseExpression();
EnsureSymbol(")");
SyntaxNode body = nullptr;
if(!IsSymbol(";"))
{
body = ParseNode();
}
return AdvancedSyntaxNode::Create(WhileStatement,false,{cond,body});
}
if(IsIdentifier("do"))
{
EnsureSymbol("(");
SyntaxNode cond = ParseExpression();
EnsureSymbol(")");
SyntaxNode body = nullptr;
if(!IsSymbol(";"))
{
body = ParseNode();
}
return AdvancedSyntaxNode::Create(DoStatement,false,{cond,body});
}
if(IsIdentifier("for"))
{
SyntaxNode init = nullptr;
SyntaxNode cond = true;
SyntaxNode inc = nullptr;
SyntaxNode body = nullptr;
EnsureSymbol("(");
if(!IsSymbol(";",false))
{
init = ParseExpression();
}
EnsureSymbol(";");
if(!IsSymbol(";",false))
{
cond = ParseExpression();
}
EnsureSymbol(";");
if(!IsSymbol(")",false))
{
inc = ParseExpression();
}
EnsureSymbol(")");
if(!IsSymbol(";"))
{
body = ParseNode();
}
return AdvancedSyntaxNode::Create(ForStatement,false,{init,cond,inc,body});
}
if(IsIdentifier("each"))
{
SyntaxNode item = nullptr;
EnsureSymbol("(");
SyntaxNode list = ParseExpression();
SyntaxNode body = nullptr;
if(IsSymbol(":"))
{
item = list;
list = ParseExpression();
}
EnsureSymbol(")");
if(!IsSymbol(";"))
{
body = ParseNode();
}
return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body});
}
if(IsIdentifier("func"))
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
return AdvancedSyntaxNode::Create(FunctionStatement,false,{nameAndArgs,ParseNode()});
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(FunctionStatement,false,{nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})});
}
}
if(IsIdentifier("break"))
{
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(BreakStatement,false,{});
}
if(IsIdentifier("continue"))
{
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(ContinueStatement,false,{});
}
if(IsIdentifier("return"))
{
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(ReturnStatement,false,{v});
}
if(IsIdentifier("throw"))
{
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(ThrowStatement,false,{v});
}
if(IsIdentifier("try"))
{
auto tryBody = ParseNode();
SyntaxNode catchNode = nullptr;
SyntaxNode catchEx = nullptr;
SyntaxNode finally=nullptr;
if(IsIdentifier("catch"))
{
EnsureSymbol("(");
catchEx = ParseExpression();
EnsureSymbol(")");
catchNode = ParseNode();
}
if(IsIdentifier("finally"))
{
finally = ParseNode();
}
return AdvancedSyntaxNode::Create(TryStatement, false, {tryBody,catchNode,catchEx, finally});
}
if(IsIdentifier("defer"))
{
if(IsSymbol("{",false))
{
return AdvancedSyntaxNode::Create(DeferStatement,false,{ParseNode()});
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(DeferStatement,false,{AdvancedSyntaxNode::Create(ReturnStatement,false,{v})});
}
}
auto v = ParseExpression();
EnsureSymbol(";");
return v;
}
SyntaxNode Parser::ParseTernary()
{
SyntaxNode node = ParseLOr();
if(IsSymbol("?"))
{
auto yes = ParseTernary();
EnsureSymbol(":");
auto no = ParseTernary();
return AdvancedSyntaxNode::Create(TernaryExpression,true,{node,yes,no});
}
return node;
}
SyntaxNode Parser::ParseShift()
{
SyntaxNode expr = ParseSum();
while(IsAnySymbol({"<<",">>"},true))
{
if(tkn.text == "<<")
{
expr = AdvancedSyntaxNode::Create(LeftShiftExpression, true, {expr,ParseSum()});
}
else if(tkn.text == ">>")
{
expr = AdvancedSyntaxNode::Create(RightShiftExpression, true, {expr,ParseSum()});
}
}
return expr;
}
SyntaxNode Parser::ParseRel()
{
SyntaxNode expr = ParseShift();
while(IsAnySymbol({"<",">","<=",">="},true))
{
if(tkn.text == "<")
{
expr = AdvancedSyntaxNode::Create(LessThanExpression, true, {expr,ParseShift()});
}
else if(tkn.text == ">")
{
expr = AdvancedSyntaxNode::Create(GreaterThanExpression, true, {expr,ParseShift()});
}
else if(tkn.text == "<=")
{
expr = AdvancedSyntaxNode::Create(LessThanEqualsExpression, true, {expr,ParseShift()});
}
else if(tkn.text == ">")
{
expr = AdvancedSyntaxNode::Create(GreaterThanEqualsExpression, true, {expr,ParseShift()});
}
}
return expr;
}
SyntaxNode Parser::ParseEq()
{
SyntaxNode expr = ParseRel();
while(IsAnySymbol({"==","!="},true))
{
if(tkn.text == "==")
{
expr = AdvancedSyntaxNode::Create(EqualsExpression, true, {expr,ParseRel()});
}
else if(tkn.text == "!=")
{
expr = AdvancedSyntaxNode::Create(NotEqualsExpression, true, {expr,ParseRel()});
}
}
return expr;
}
SyntaxNode Parser::ParseBAnd()
{
SyntaxNode expr = ParseEq();
while(IsSymbol("&"))
{
expr = AdvancedSyntaxNode::Create(BitwiseAndExpression,true,{expr,ParseEq()});
}
return expr;
}
SyntaxNode Parser::ParseExpression()
{
SyntaxNode expr = ParseAssignment();
while(IsSymbol(","))
{
expr = AdvancedSyntaxNode::Create(CommaExpression,true,{expr,ParseAssignment()});
}
return expr;
}
SyntaxNode Parser::ParseXOr()
{
SyntaxNode expr = ParseBAnd();
while(IsSymbol("^"))
{
expr = AdvancedSyntaxNode::Create(XOrExpression,true,{expr,ParseBAnd()});
}
return expr;
}
SyntaxNode Parser::ParseBOr()
{
SyntaxNode expr = ParseXOr();
while(IsSymbol("|"))
{
expr = AdvancedSyntaxNode::Create(BitwiseOrExpression,true,{expr,ParseXOr()});
}
return expr;
}
SyntaxNode Parser::ParseLAnd()
{
SyntaxNode expr = ParseBOr();
while(IsSymbol("&&"))
{
expr = AdvancedSyntaxNode::Create(LogicalAndExpression,true,{expr,ParseBOr()});
}
return expr;
}
SyntaxNode Parser::ParseLOr()
{
SyntaxNode expr = ParseLAnd();
while(IsSymbol("||"))
{
expr = AdvancedSyntaxNode::Create(LogicalOrExpression,true,{expr,ParseLAnd()});
}
return expr;
}
}