#include "CrossLang.hpp" #include #include namespace Tesses::CrossLang { SyntaxNode TObject2SyntaxNode(TObject o) { if(std::holds_alternative(o)) return Undefined(); if(std::holds_alternative(o)) return nullptr; if(std::holds_alternative(o)) return std::get(o); if(std::holds_alternative(o)) return std::get(o); if(std::holds_alternative(o)) return std::get(o); if(std::holds_alternative(o)) return std::get(o); if(std::holds_alternative(o)) return std::get(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 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 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[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[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[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 tokens) : Parser(tokens,nullptr,nullptr) { } Parser::Parser(std::vector tokens, std::shared_ptr gc, TRootEnvironment* env) { this->i = 0; this->tokens = tokens; this->gc = gc; this->env = env; } void Parser::ParseHtml(std::vector& 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 = ""; 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& 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 = ""; 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,{ "

", AdvancedSyntaxNode::Create(AddExpression,true,{ AdvancedSyntaxNode::Create(FunctionCallExpression,true,{ AdvancedSyntaxNode::Create(GetFieldExpression,true,{ AdvancedSyntaxNode::Create(GetFieldExpression,true,{ AdvancedSyntaxNode::Create(GetVariableExpression,true,{"Net"}), "Http" }) , "HtmlP" }), expr }) , "

" }) }) }) })); } 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 _nodes; parseFn(_nodes,"true"); truth = AdvancedSyntaxNode::Create(ScopeNode,false,_nodes); } else if(this->IsIdentifier("false")) { this->EnsureSymbol(">"); std::vector _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 _nodes; parseFn(_nodes,"null"); nodes.push_back(AdvancedSyntaxNode::Create(ScopeNode,false,_nodes)); } else if(tagName == "return") { EnsureSymbol(">"); std::vector _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 _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 _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 _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 _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(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(expr)) { myVal += std::to_string(std::get(expr)) + "\""; nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); } else if(std::holds_alternative(expr)) { myVal += std::to_string(std::get(expr)) + "\""; nodes.push_back(AdvancedSyntaxNode::Create(CompoundAssignExpression,true,{AdvancedSyntaxNode::Create(AddExpression,true,{AdvancedSyntaxNode::Create(GetVariableExpression,true,{var}),myVal})})); } else if(std::holds_alternative(expr)) { myVal += std::holds_alternative(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(expr)) { myVal += Tesses::Framework::Http::HttpUtils::HtmlEncode(std::get(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 = { 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(n)) { std::get(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(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(v)) { auto asn = std::get(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(v)) { auto asn = std::get(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(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 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].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 = { 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; } }