Files
crosslang/src/compiler/parser.cpp
Mike Nolan 991f2a217d
Some checks failed
Build and Deploy on Tag / update-tap (push) Has been cancelled
Build and Deploy on Tag / build-arch (push) Has been cancelled
Rework for git.tesses.org, GC* is std::shared_ptr maybe will fix crash during exit
2026-04-30 16:00:00 -05:00

1973 lines
80 KiB
C++

#include "CrossLang.hpp"
#include <iostream>
#include <stdexcept>
namespace Tesses::CrossLang
{
SyntaxNode TObject2SyntaxNode(TObject o)
{
if(std::holds_alternative<Undefined>(o)) return Undefined();
if(std::holds_alternative<std::nullptr_t>(o)) return nullptr;
if(std::holds_alternative<std::string>(o)) return std::get<std::string>(o);
if(std::holds_alternative<int64_t>(o)) return std::get<int64_t>(o);
if(std::holds_alternative<double>(o)) return std::get<double>(o);
if(std::holds_alternative<char>(o)) return std::get<char>(o);
if(std::holds_alternative<bool>(o)) return std::get<bool>(o);
TList* list;
TDictionary* dict;
TByteArray* byteArray;
if(GetObjectHeap(o,list))
{
if(list->Count() == 0) return AdvancedSyntaxNode::Create(ArrayExpression, true, {});
SyntaxNode node = TObject2SyntaxNode(list->Get(0));
for(int64_t i = 1; i < list->Count(); i++)
node = AdvancedSyntaxNode::Create(CommaExpression,true,{node,TObject2SyntaxNode(list->Get(i))});
return AdvancedSyntaxNode::Create(ArrayExpression, true, {node});
}
if(GetObjectHeap(o,dict))
{
bool has=false;
SyntaxNode node=nullptr;
for(auto item : dict->items)
{
if(has)
{
node = AdvancedSyntaxNode::Create(CommaExpression,true, {node,AdvancedSyntaxNode::Create(AssignExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}),
TObject2SyntaxNode(item.second)
})});
}
else {
node = AdvancedSyntaxNode::Create(AssignExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{TObject2SyntaxNode(item.first)}),
TObject2SyntaxNode(item.second)
});
has=true;
}
}
if(has) return AdvancedSyntaxNode::Create(DictionaryExpression,true,{node});
return AdvancedSyntaxNode::Create(DictionaryExpression,true,{});
}
if(GetObjectHeap(o,byteArray)) {
return byteArray->data;
}
return Undefined();
}
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 == ">")
{
if(i+1<tokens.size())
{
if((tokens[i+1].text == ">" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol) continue;
}
if(item == tokens[i].text)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
else if(item == ">>=")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
tkn.text = ">>=";
if(pop) i+=2;
return true;
}
}
}
else if(item == ">>")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
tkn.text = ">>";
if(pop) i+=2;
return true;
}
}
}
else {
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(txt == ">")
{
if(i+1<tokens.size())
{
if((tokens[i+1].text == ">" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol) return false;
}
if(txt == tokens[i].text)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
else if(txt == ">>=")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
tkn.text = ">>=";
if(pop) i+=2;
return true;
}
}
}
else if(txt == ">>")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
tkn.text = ">>";
if(pop) i+=2;
return true;
}
}
}
else if(tokens[i].text == txt)
{
tkn = tokens[i];
if(pop) i++;
return true;
}
}
return false;
}
static std::string EnsureSafeVariable(LexToken token)
{
if(token.text.find("__compGen") == 0)
{
throw SyntaxException(token.lineInfo,"__compGen* is reserved for compilers (this error is enforced by the compiler)");
}
return token.text;
}
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(txt == ">")
{
if(i+1<tokens.size())
{
if((tokens[i+1].text == ">" || tokens[i+1].text == ">=") && tokens[i+1].type == LexTokenType::Symbol)
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\"");;
}
if(txt == tokens[i].text)
{
tkn = tokens[i];
i++;
return;
}
}
if(txt == ">>=")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">=" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
i+=2;
return;
}
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\"");
}
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\"");
}
else if(txt == ">>")
{
if(i+1 < tokens.size())
{
if(tokens[i].text == ">" && tokens[i+1].text == ">" && tokens[i].type == LexTokenType::Symbol && tokens[i+1].type == LexTokenType::Symbol)
{
tkn = tokens[i];
i+=2;
return;
}
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + tokens[i+1].text + "\"");
}
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"" + txt + "\" but got the symbol \"" + tokens[i].text + "\"");
}
else 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) : Parser(tokens,nullptr,nullptr)
{
}
Parser::Parser(std::vector<LexToken> tokens, std::shared_ptr<GC> gc, TRootEnvironment* env)
{
this->i = 0;
this->tokens = tokens;
this->gc = gc;
this->env = env;
}
void Parser::ParseHtml(std::vector<SyntaxNode>& nodes,std::string var)
{
if(this->IsSymbol("!",true))
{
if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier)
{
std::string identifier = this->tokens[this->i++].text;
if(identifier == "DOCTYPE")
{
if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier)
{
std::string doctype_secArg = this->tokens[this->i++].text;
std::string r = "<!DOCTYPE " + doctype_secArg + ">";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),r})}));
this->EnsureSymbol(">");
if(this->IsSymbol("<"))
{
ParseHtml(nodes,var);
}
}
}
}
}
else
{
auto parseFn = [this,var](std::vector<SyntaxNode>& nodes,std::string tagName)->void{
while(this->i < this->tokens.size())
{
if(this->IsSymbol("<",false))
{
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(this->tokens[i].whiteSpaceCharsBefore)})}));
this->i++;
if(this->IsSymbol("/"))
{
if(this->IsIdentifier("if",false) && tagName == "if")
{
this->i-=2;
break;
}
if(!this->IsIdentifier(tagName))
{
//error
}
this->EnsureSymbol(">");
if(tagName != "if" && tagName != "true" && tagName != "false" && tagName != "for" && tagName != "while" && tagName != "do" && tagName != "each" && tagName != "null" && tagName != "return")
{
std::string myVal = "</";
myVal += tagName;
myVal += ">";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
break;
}
else
{
ParseHtml(nodes,var);
}
}
else if(this->IsSymbol("{",false))
{
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(this->tokens[i].whiteSpaceCharsBefore)})}));
this->i++;
auto expr = ParseExpression();
this->EnsureSymbol("}");
//Net.Http.HtmlEncode(expr.ToString())
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{var})
,
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true, {
AdvancedSyntaxNode::Create(GetVariableExpression,true, {
"Net"
}),
"Http"
}),
"HtmlEncode"
}),
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
AdvancedSyntaxNode::Create(ParenthesesExpression,true,{expr})
,
"ToString"
})
})
})
})
}));
}
else
{
std::string str = "";
while(this->i < this->tokens.size() && !this->IsSymbol("{",false) && !this->IsSymbol("<",false))
{
str+=this->tokens[this->i].whiteSpaceCharsBefore + this->tokens[this->i].text;
this->i++;
}
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),Tesses::Framework::Http::HttpUtils::HtmlEncode(str)})}));
}
}
};
if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier)
{
std::string tagName = this->tokens[this->i++].text;
if(tagName == "raw")
{
EnsureSymbol("(");
SyntaxNode expr = ParseExpression();
EnsureSymbol(")");
EnsureSymbol(">");
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
expr
,
"ToString"
})
})
})
}));
}
else if(tagName == "plink")
{
EnsureSymbol("(");
SyntaxNode expr = ParseExpression();
EnsureSymbol(")");
EnsureSymbol(">");
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),
AdvancedSyntaxNode::Create(AddExpression,true,{
"<p>",
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Net"}),
"Http"
})
,
"HtmlP"
}),
expr
})
,
"</p>"
})
})
})
}));
}
else if(tagName == "if")
{
EnsureSymbol("(");
SyntaxNode expr = ParseExpression();
SyntaxNode truth = nullptr;
SyntaxNode falsey = nullptr;
EnsureSymbol(")");
EnsureSymbol(">");
while(this->IsSymbol("<"))
{
if(this->IsSymbol("/"))
{
if(!this->IsIdentifier("if")) { this->i -= 3;}
this->EnsureSymbol(">");
break;
}
else if(this->IsIdentifier("true"))
{
this->EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"true");
truth = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
}
else if(this->IsIdentifier("false"))
{
this->EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"false");
falsey = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
}
}
nodes.push_back(AdvancedSyntaxNode::Create(IfStatement,false,{expr,truth,falsey}));
}
else if(tagName == "null")
{
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"null");
nodes.push_back(AdvancedSyntaxNode::Create(ScopeNode,false,_nodes));
}
else if(tagName == "return")
{
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"return");
nodes.push_back(AdvancedSyntaxNode::Create(ScopeNode,false,_nodes));
}
else if(tagName == "while")
{
EnsureSymbol("(");
SyntaxNode expr = ParseExpression();
SyntaxNode body = nullptr;
EnsureSymbol(")");
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"while");
body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
nodes.push_back(AdvancedSyntaxNode::Create(WhileStatement,false,{expr,body}));
}
else if(tagName == "do")
{
EnsureSymbol("(");
SyntaxNode expr = ParseExpression();
SyntaxNode body = nullptr;
EnsureSymbol(")");
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"do");
body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
nodes.push_back(AdvancedSyntaxNode::Create(DoStatement,false,{expr,body}));
}
else if(tagName == "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(")");
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"for");
body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
nodes.push_back(AdvancedSyntaxNode::Create(ForStatement,false,{init,cond,inc,body}));
}
else if(tagName == "each")
{
SyntaxNode item = nullptr;
EnsureSymbol("(");
SyntaxNode list = ParseExpression();
SyntaxNode body = nullptr;
if(IsSymbol(":"))
{
item = list;
list = ParseExpression();
}
EnsureSymbol(")");
EnsureSymbol(">");
std::vector<SyntaxNode> _nodes;
parseFn(_nodes,"each");
body = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes);
nodes.push_back(AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body}));
}
else
{
std::string s = "<";
s.append(tagName);
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),s})}));
while(!this->IsSymbol(">"))
{
//we need to get a name=value
if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::Identifier)
{
std::string key = "";
while(this->i < this->tokens.size())
{
if(this->tokens[i].type == Identifier)
{
key += this->tokens[i].text;
i++;
}
else if(this->tokens[i].type == Symbol)
{
if(this->tokens[i].text == "-" || this->tokens[i].text == ":" || this->tokens[i].text == "--" || tokens[i].text == ".")
{
key += this->tokens[i].text;
i++;
}
else break;
}
else break;
}
if(this->IsSymbol(">"))
{
std::string myVal = " " + key;
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
break;
}
else if(this->IsSymbol("="))
{
std::string myVal = " " + key + "=\"";
SyntaxNode expr;
if(this->i < this->tokens.size() && this->tokens[this->i].type == LexTokenType::String)
{
expr = this->tokens[this->i++].text;
}
else {
EnsureSymbol("{");
expr = ParseExpression();
EnsureSymbol("}");
}
if(std::holds_alternative<AdvancedSyntaxNode>(expr))
{
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),
AdvancedSyntaxNode::Create(AddExpression,true,{
myVal,
AdvancedSyntaxNode::Create(AddExpression,true,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true, {
AdvancedSyntaxNode::Create(GetVariableExpression,true, {
"Net"
}),
"Http"
}),
"HtmlEncode"
}),
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{
expr
,
"ToString"
})
})
}),
"\"",
})
})
})
}));
}
else if(std::holds_alternative<double>(expr))
{
myVal += std::to_string(std::get<double>(expr)) + "\"";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
else if(std::holds_alternative<int64_t>(expr))
{
myVal += std::to_string(std::get<int64_t>(expr)) + "\"";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
else if(std::holds_alternative<bool>(expr))
{
myVal += std::holds_alternative<bool>(expr) ? "true\"" : "false\"";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
else if(std::holds_alternative<std::string>(expr))
{
myVal += Tesses::Framework::Http::HttpUtils::HtmlEncode(std::get<std::string>(expr)) + "\"";
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
//key = value
}
else {
std::string myVal = " " + key;
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})}));
}
}
}
nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),">"})}));
if(tagName != "img" && tagName != "input" && tagName != "br" && tagName != "hr" && tagName != "link" && tagName != "meta")
{
parseFn(nodes,tagName);
}
}
}
}
}
uint32_t Parser::NewId()
{
return id++;
}
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(tokens[i].type == LexTokenType::Symbol && tokens[i].text == ".")
{
i++;
if(IsSymbol("["))
{
node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{ParseExpression()});
EnsureSymbol("]");
}
else
{
node = AdvancedSyntaxNode::Create(RelativePathExpression, true, {});
}
}
else if(IsSymbol("<"))
{
uint32_t htmlId = NewId();
std::string compHtml = "__compGenHtml";
compHtml.append(std::to_string(htmlId));
std::vector<SyntaxNode> syntaxNode = {
compHtml
};
ParseHtml(syntaxNode,compHtml);
return AdvancedSyntaxNode::Create(HtmlRootExpression,true,syntaxNode);
}
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::Symbol && variable.text == ".")
{
EnsureSymbol("[");
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()})
});
EnsureSymbol("]");
}
else if(variable.type == LexTokenType::Symbol && variable.text == "[")
{
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{
AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()})
});
EnsureSymbol("]");
}
else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
else
{
node = AdvancedSyntaxNode::Create(DeclareExpression,true,{EnsureSafeVariable(variable)});
}
}
else if(IsIdentifier("const"))
{
if(i >= tokens.size()) throw std::out_of_range("End of file");
auto variable = tokens[i];
i++;
if(variable.type == LexTokenType::Symbol && variable.text == ".")
{
EnsureSymbol("[");
node = AdvancedSyntaxNode::Create(ConstExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression ,true,{ParseExpression()})
});
EnsureSymbol("]");
}
else if(variable.type == LexTokenType::Symbol && variable.text == "[")
{
node = AdvancedSyntaxNode::Create(ConstExpression,true,{
AdvancedSyntaxNode::Create(ArrayExpression ,true,{ParseExpression()})
});
EnsureSymbol("]");
}
else if(variable.type != LexTokenType::Identifier) throw SyntaxException(variable.lineInfo, "Expected an identifier got a " + LexTokenType_ToString(variable.type) + " \"" + variable.text + "\"");
else
{
node = AdvancedSyntaxNode::Create(ConstExpression,true,{EnsureSafeVariable(variable)});
}
}
else if(IsIdentifier("comptime"))
{
SyntaxNode n = nullptr;
if(IsSymbol("{",false))
{
n = ParseNode();
if(std::holds_alternative<AdvancedSyntaxNode>(n))
{
std::get<AdvancedSyntaxNode>(n).nodeName = NodeList;
}
} else {
n = AdvancedSyntaxNode::Create(ReturnStatement,false,{ParseExpression()});
}
if(gc != nullptr && env != nullptr)
{
GCList ls(gc);
CodeGen gen;
gen.GenRoot(n);
auto ms = std::make_shared<Tesses::Framework::Streams::MemoryStream>(true);
gen.Save(ms);
ms->Seek(0, Tesses::Framework::Streams::SeekOrigin::Begin);
TFile* f = TFile::Create(ls);
f->Load(gc,ms);
node = TObject2SyntaxNode(env->LoadFile(gc,f));
}
else {
node = Undefined();
}
}
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("new"))
{
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(GetFieldExpression, true, {AdvancedSyntaxNode::Create(GetVariableExpression,true,{"New"}), 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(IsIdentifier("embedstrm"))
{
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(EmbedStreamExpression, true,{embed.text});
}
else if(IsIdentifier("embeddir"))
{
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(EmbedDirectoryExpression, true,{embed.text});
}
else if(tokens[i].type == LexTokenType::Identifier)
{
auto token=tokens[i];
i++;
bool hasNumber=true;
int64_t lngNum = 0;
if(token.text.size() == 1 && token.text[0] == '0')
{
lngNum = 0;
}
else
if(token.text.size() > 0 && token.text[0] == '0')
{
if(token.text.size() > 1 && token.text[1] == 'x')
{
lngNum = std::stoll(token.text.substr(2),nullptr,16);
}
else if(token.text.size() > 1 && token.text[1] == 'b')
{
lngNum = std::stoll(token.text.substr(2),nullptr,2);
}
else
{
lngNum = std::stoll(token.text.substr(1),nullptr,8);
}
}
else if(token.text.size() > 0 && token.text[0] >= '0' && token.text[0] <= '9')
{
lngNum=std::stoll(token.text,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.text == "true")
node = true;
else if(token.text == "false")
node = false;
else if(token.text == "null")
node = nullptr;
else if(token.text == "undefined")
node = Undefined();
else {
node = AdvancedSyntaxNode::Create(GetVariableExpression,true,{EnsureSafeVariable(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(IsSymbol("["))
{
node = AdvancedSyntaxNode::Create(GetFieldExpression, true, {node, ParseExpression()});
EnsureSymbol("]");
continue;
}
if(tokens[i].type != LexTokenType::Identifier) throw std::runtime_error("Not an identifier (member)");
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()});
}
else if(IsIdentifier("await"))
{
return AdvancedSyntaxNode::Create(YieldStatement,true,{ParseValue()});
}
else if(IsIdentifier("async"))
{
auto tkn = this->tkn;
auto v = ParseValue();
if(std::holds_alternative<AdvancedSyntaxNode>(v))
{
auto asn = std::get<AdvancedSyntaxNode>(v);
if(asn.nodeName != ClosureExpression)
throw SyntaxException(tkn.lineInfo,"async must be used only with a closure");
if(asn.nodes.size() != 2)
throw SyntaxException(tkn.lineInfo,"invalid closure");
return AdvancedSyntaxNode::Create(ClosureExpression,true,{
asn.nodes[0],
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]})
})
})
});
}
else {
throw SyntaxException(tkn.lineInfo,"async must be used only with a closure, not a simple value");
}
}
else if(IsIdentifier("enumerable"))
{
auto tkn = this->tkn;
auto v = ParseValue();
if(std::holds_alternative<AdvancedSyntaxNode>(v))
{
auto asn = std::get<AdvancedSyntaxNode>(v);
if(asn.nodeName != ClosureExpression)
throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure");
if(asn.nodes.size() != 2)
throw SyntaxException(tkn.lineInfo,"invalid closure");
return AdvancedSyntaxNode::Create(ClosureExpression,true,{
asn.nodes[0],
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), asn.nodes[1]})
})
})
});
}
else {
throw SyntaxException(tkn.lineInfo,"enumerable must be used only with a closure, not a simple value");
}
}
else if(IsSymbol("/"))
{
if(this->i < this->tokens.size() && (this->tokens[this->i].type == LexTokenType::String || this->tokens[this->i].type == LexTokenType::Identifier))
{
return AdvancedSyntaxNode::Create(DivideExpression,true,{
AdvancedSyntaxNode::Create(RootPathExpression,true,{}),
ParseValue()
});
}
else {
return AdvancedSyntaxNode::Create(RootPathExpression,true,{});
}
}
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()})});
}
else if(IsSymbol("?\?="))
{
return AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{ node,ParseAssignment()})});
}
return node;
}
bool Parser::CanEmit(LexTokenLineInfo& ifo)
{
if(!this->debug) return false;
bool same = ifo.line == this->lastLine && ifo.filename == this->lastFile;
this->lastFile = ifo.filename;
this->lastLine = ifo.line;
return !same;
}
SyntaxNode Parser::ParseNode(bool isRoot)
{
std::string documentation="";
if(i < tokens.size() && !isRoot && tokens[i].type == Documentation)
{
auto txt = tokens[i].text;
i++;
if(i < tokens.size() && tokens[i].text == "class" && tokens[i].type == LexTokenType::Identifier)
documentation = txt;
else
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)))
{
auto token = tokens[i];
if(CanEmit(token.lineInfo)) aSN.nodes.push_back(AdvancedSyntaxNode::Create(LineNode,false, {(int64_t)tokens[i].lineInfo.line,tokens[i].lineInfo.filename}));
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("switch"))
{
EnsureSymbol("(");
SyntaxNode cond = ParseExpression();
EnsureSymbol(")");
SyntaxNode body = ParseNode();
return AdvancedSyntaxNode::Create(SwitchStatement,false,{cond,body});
}
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(":") || IsIdentifier("in"))
{
item = list;
list = ParseExpression();
}
EnsureSymbol(")");
if(!IsSymbol(";"))
{
body = ParseNode();
}
if(std::holds_alternative<std::nullptr_t>(item))
item = AdvancedSyntaxNode::Create(DeclareExpression,true, {
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"item"})
});
return AdvancedSyntaxNode::Create(EachStatement,false,{item,list,body});
}
if(IsIdentifier("class"))
{
if(i < tokens.size())
{
std::vector<SyntaxNode> name_and_methods={documentation};
auto name = ParseExpression();
name_and_methods.push_back(name);
if(IsSymbol(":",true))
{
name_and_methods.push_back(ParseExpression());
}
else
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(GetVariableExpression,true,{"ClassObject"}));
}
EnsureSymbol("{");
while(!IsSymbol("}",false) && i < tokens.size())
{
documentation="";
if(tokens[i].type == LexTokenType::Documentation)
{
documentation = tokens[i++].text;
}
if(i < tokens.size())
{
if(IsAnyIdentifier({"public","private","protected","static"}))
{
auto myTkn = tkn;
if(IsIdentifier("abstract"))
{
if(myTkn.text == "static") throw SyntaxException(myTkn.lineInfo,"Static abstract function doesn't make sense");
auto nameAndArgs = ParseExpression();
EnsureSymbol(";");
name_and_methods.push_back(AdvancedSyntaxNode::Create(AbstractMethodStatement,false,{documentation,myTkn.text,nameAndArgs}));
}
else if(i + 1 < tokens.size() && (tokens[i+1].text == "=" || tokens[i+1].text == ";") && tokens[i+1].type == LexTokenType::Symbol)
{
auto setter = ParseExpression();
EnsureSymbol(";");
SyntaxNode field = AdvancedSyntaxNode::Create(FieldStatement,false,{
documentation,
myTkn.text,
setter
});
name_and_methods.push_back(field);
}
else
{
if(IsIdentifier("async"))
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
})
})
}));
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), AdvancedSyntaxNode::Create(ReturnStatement,false,{v})})
})
})
}));
}
}
else if(IsIdentifier("enumerable"))
{
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
})
})
}));
}
else
{
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\"");
}
}
else {
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,ParseNode()}));
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
name_and_methods.push_back(AdvancedSyntaxNode::Create(MethodStatement,false,{documentation,myTkn.text,nameAndArgs,AdvancedSyntaxNode::Create(ReturnStatement,false,{v})}));
}
}
}
}
else {
throw SyntaxException(tokens[i].lineInfo, "Need public, private, protected or static");
}
}
}
EnsureSymbol("}");
return AdvancedSyntaxNode::Create(ClassStatement, false, name_and_methods);
}
else throw std::out_of_range("End of file");
}
if(IsIdentifier("enumerable",false) && i+1<tokens.size() && tokens[i+1].text == "func" && i+1<tokens.size() && tokens[i+1].type == LexTokenType::Identifier)
{
i+=2;
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetVariableExpression,true,{"YieldEmumerable"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
})
})
});
}
else
{
throw SyntaxException(tokens[i].lineInfo, "expected the symbol \"{\" on enumerable but got the symbol or other token \"" + tokens[i].text + "\"");
}
}
if(IsIdentifier("async",false) && i+1<tokens.size() && tokens[i+1].text == "func" && tokens[i+1].type == LexTokenType::Identifier)
{
i+=2;
//async func
auto nameAndArgs = ParseExpression();
if(IsSymbol("{",false))
{
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), ParseNode()})
})
})
});
}
else
{
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(FunctionStatement,false,{
nameAndArgs,
AdvancedSyntaxNode::Create(ReturnStatement,false,{
AdvancedSyntaxNode::Create(FunctionCallExpression,true,{
AdvancedSyntaxNode::Create(GetFieldExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Task"}),"AsyncClosure"}),
AdvancedSyntaxNode::Create(ClosureExpression,true,{AdvancedSyntaxNode::Create(ParenthesesExpression,true,{}), AdvancedSyntaxNode::Create(ReturnStatement,false,{v})})
})
})
});
}
}
if(IsIdentifier("meta"))
{
if(i >= tokens.size() || tokens[i].type != LexTokenType::String)
{
std::cout << "WARN: meta is a conditional keyword,\nif you suffix it with a string, it will be assumed to be a metadata tag" << std::endl;
i--;
}
else {
std::string name = tokens[i++].text;
EnsureSymbol("{");
auto expr = ParseExpression();
EnsureSymbol("}");
return AdvancedSyntaxNode::Create(MetadataStatement,false,{name, AdvancedSyntaxNode::Create(DictionaryExpression,true,{expr})});
}
}
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("case"))
{
auto r = AdvancedSyntaxNode::Create(CaseStatement,false,{ParseExpression()});
EnsureSymbol(":");
return r;
}
if(IsIdentifier("default"))
{
auto r = AdvancedSyntaxNode::Create(DefaultStatement,false,{});
EnsureSymbol(":");
return r;
}
if(IsIdentifier("return"))
{
SyntaxNode v = Undefined();
if(!IsSymbol(";",true))
{
v = ParseExpression();
EnsureSymbol(";");
}
return AdvancedSyntaxNode::Create(ReturnStatement,false,{v});
}
if(IsSymbol("<",false) && this->i+1 < this->tokens.size() && this->tokens[this->i+1].type == LexTokenType::Identifier && this->tokens[this->i+1].text == "return")
{
this->i++;
uint32_t htmlId = NewId();
std::string compHtml = "__compGenHtml";
compHtml.append(std::to_string(htmlId));
std::vector<SyntaxNode> syntaxNode = {
compHtml
};
ParseHtml(syntaxNode,compHtml);
auto thytoken = AdvancedSyntaxNode::Create(HtmlRootExpression,true,syntaxNode);
return AdvancedSyntaxNode::Create(ReturnStatement,false,{thytoken});
}
if(IsIdentifier("yield"))
{
SyntaxNode v = Undefined();
if(!IsSymbol(";",true))
{
v = ParseExpression();
EnsureSymbol(";");
}
return AdvancedSyntaxNode::Create(YieldStatement,false,{v});
}
if(IsIdentifier("throw"))
{
auto tkn2 = tkn;
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(ThrowStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset});
}
if(IsIdentifier("breakpoint"))
{
auto tkn2 = tkn;
auto v = ParseExpression();
EnsureSymbol(";");
return AdvancedSyntaxNode::Create(BreakpointStatement,false,{v,tkn2.lineInfo.filename,(int64_t)tkn2.lineInfo.line,(int64_t)tkn2.lineInfo.column,(int64_t)tkn.lineInfo.offset});
}
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::ParseNullCoalescing()
{
SyntaxNode expr = ParseLOr();
while(IsSymbol("?\?"))
{
expr = AdvancedSyntaxNode::Create(NullCoalescingExpression,true,{expr,ParseLOr()});
}
return expr;
}
SyntaxNode Parser::ParseTernary()
{
SyntaxNode node = ParseNullCoalescing();
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;
}
}