First commit
This commit is contained in:
151
src/compiler/ast.cpp
Normal file
151
src/compiler/ast.cpp
Normal 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
1251
src/compiler/codegen.cpp
Normal file
File diff suppressed because it is too large
Load Diff
687
src/compiler/lexer.cpp
Normal file
687
src/compiler/lexer.cpp
Normal 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
750
src/compiler/parser.cpp
Normal 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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user