#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 == tokens[i].text) { tkn = tokens[i]; if (pop) i++; return true; } } } return false; } bool Parser::IsSymbol(std::string txt, bool pop) { if (i < tokens.size()) { if (tokens[i].type != LexTokenType::Symbol) return false; if (tokens[i].text == txt) { tkn = tokens[i]; if (pop) i++; return true; } } return false; } 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 (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(":") || IsIdentifier("in")) { item = list; list = ParseExpression(); } EnsureSymbol(")"); EnsureSymbol(">"); if (std::holds_alternative(item)) item = AdvancedSyntaxNode::Create( DeclareExpression, true, {"item"}); 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, "ToStr" "in" "g"})})}), "\"", }) })})})); } 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 (IsIdentifier("private")) { node = AdvancedSyntaxNode::Create(GetPrivateExpression, true, {}); } 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) EnsureSymbol("}"); 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("using")) { EnsureSymbol("("); SyntaxNode expr = ParseExpression(); EnsureSymbol(")"); SyntaxNode body = nullptr; if (!IsSymbol(";")) { body = ParseNode(); } return AdvancedSyntaxNode::Create(UsingStatement, false, {expr, 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, {"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 + 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 = {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; } } // namespace Tesses::CrossLang