From ba9a9199d01b0fdd4bf9a54914f8058bf71f30c5 Mon Sep 17 00:00:00 2001
From: Ferenc Szontágh <szf@fsociety.hu>
Date: Thu, 17 Apr 2025 16:03:01 +0000
Subject: [PATCH] unary and binary operations
---
src/Parser/Parser.hpp | 484 +++++++++++++++++++++++++++++-----------------------
1 files changed, 269 insertions(+), 215 deletions(-)
diff --git a/src/Parser/Parser.hpp b/src/Parser/Parser.hpp
index b40397e..41a7545 100644
--- a/src/Parser/Parser.hpp
+++ b/src/Parser/Parser.hpp
@@ -3,17 +3,19 @@
#include <algorithm>
#include <memory>
-#include <sstream> // Hibaüzenetekhez
+#include <stack>
#include <stdexcept>
#include <string>
#include <vector>
-// Szükséges header-ök a Lexer és Symbol komponensekből
+#include "Interpreter/ExpressionBuilder.hpp"
+#include "Interpreter/OperationsFactory.hpp"
#include "Lexer/Token.hpp"
-#include "Lexer/TokenType.hpp" // Enum és TypeToString
+#include "Lexer/TokenType.hpp"
+#include "Parser/ParsedExpression.hpp"
+#include "Symbols/ParameterContainer.hpp"
#include "Symbols/SymbolContainer.hpp"
-#include "Symbols/SymbolFactory.hpp"
-#include "Symbols/Value.hpp" // Symbols::Value miatt
+#include "Symbols/Value.hpp"
namespace Parser {
@@ -32,11 +34,13 @@
public:
Parser() {}
- void parseProgram(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string) {
+ void parseScript(const std::vector<Lexer::Tokens::Token> & tokens, std::string_view input_string,
+ const std::string & filename) {
tokens_ = tokens;
input_str_view_ = input_string;
current_token_index_ = 0;
- symbol_container_ = std::make_unique<Symbols::SymbolContainer>();
+ current_filename_ = filename;
+
try {
while (!isAtEnd() && currentToken().type != Lexer::Tokens::Type::END_OF_FILE) {
parseStatement();
@@ -52,21 +56,14 @@
}
}
- const std::shared_ptr<Symbols::SymbolContainer> & getSymbolContainer() const {
- if (!symbol_container_) {
- throw std::runtime_error("Symbol container is not initialized.");
- }
- return symbol_container_;
- }
-
static const std::unordered_map<std::string, Lexer::Tokens::Type> keywords;
static const std::unordered_map<Lexer::Tokens::Type, Symbols::Variables::Type> variable_types;
private:
- std::vector<Lexer::Tokens::Token> tokens_;
- std::string_view input_str_view_;
- size_t current_token_index_;
- std::shared_ptr<Symbols::SymbolContainer> symbol_container_;
+ std::vector<Lexer::Tokens::Token> tokens_;
+ std::string_view input_str_view_;
+ size_t current_token_index_;
+ std::string current_filename_;
// Token Stream Kezelő és Hibakezelő segédfüggvények (változatlanok)
const Lexer::Tokens::Token & currentToken() const {
@@ -182,7 +179,7 @@
void parseStatement() {
const auto & token_type = currentToken().type;
- if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION) {
+ if (token_type == Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION) {
parseFunctionDefinition();
return;
}
@@ -197,40 +194,33 @@
reportError("Unexpected token at beginning of statement");
}
- // parseVariableDefinition (SymbolFactory használata már korrekt volt)
void parseVariableDefinition() {
- Symbols::Variables::Type var_type_enum = parseType();
- // A típus stringjének tárolása csak a debug kiíráshoz kell
- //std::string var_type_str = tokens_[current_token_index_ - 1].value;
- std::cout << "var_name: " << currentToken().lexeme << std::endl;
+ Symbols::Variables::Type var_type = parseType();
+
Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::VARIABLE_IDENTIFIER);
std::string var_name = id_token.value;
- // Levágjuk a '$' jelet, ha a lexer mégis benne hagyta
+
if (!var_name.empty() && var_name[0] == '$') {
var_name = var_name.substr(1);
}
+ const auto ns = Symbols::SymbolContainer::instance()->currentScopeName();
expect(Lexer::Tokens::Type::OPERATOR_ASSIGNMENT, "=");
- Symbols::Value initial_value = parseValue(var_type_enum);
+ /*
+ Symbols::Value initial_value = parseValue(var_type);
+
+ Interpreter::OperationsFactory::defineSimpleVariable(var_name, initial_value, ns, this->current_filename_,
+ id_token.line_number, id_token.column_number);
+*/
+
+ auto expr = parseParsedExpression(var_type);
+ Interpreter::OperationsFactory::defineVariableWithExpression(
+ var_name, var_type, std::move(expr), ns, current_filename_, id_token.line_number, id_token.column_number);
expect(Lexer::Tokens::Type::PUNCTUATION, ";");
-
- std::string context = "global"; // Globális változó
- // SymbolFactory használata a létrehozáshoz
- auto variable_symbol = Symbols::SymbolFactory::createVariable(var_name, initial_value, context, var_type_enum);
-
- // Ellenőrzés és definíció az *aktuális* scope-ban (ami itt a globális)
- if (symbol_container_->exists("variables", var_name)) {
- reportError("Variable '" + var_name + "' already defined in this scope");
- }
- symbol_container_->define("variables", variable_symbol);
-
- // Debugging kiírás (változatlan)
- // std::cout << "Parsed variable: " << var_type_str << " " << id_token.value << " = ... ;\n";
}
- // *** MÓDOSÍTOTT parseFunctionDefinition ***
void parseFunctionDefinition() {
- expect(Lexer::Tokens::Type::KEYWORD_FUNCTION);
+ expect(Lexer::Tokens::Type::KEYWORD_FUNCTION_DECLARATION);
Lexer::Tokens::Token id_token = expect(Lexer::Tokens::Type::IDENTIFIER);
std::string func_name = id_token.value;
Symbols::Variables::Type func_return_type = Symbols::Variables::Type::NULL_TYPE;
@@ -242,7 +232,6 @@
if (currentToken().type != Lexer::Tokens::Type::PUNCTUATION || currentToken().value != ")") {
while (true) {
// Paraméter típusa
- //size_t type_token_index = current_token_index_; // Elmentjük a típus token indexét
Symbols::Variables::Type param_type = parseType(); // Ez elfogyasztja a type tokent
// Paraméter név ($variable)
@@ -275,50 +264,10 @@
}
}
- auto function_symbol =
- Symbols::SymbolFactory::createFunction(func_name, "global", param_infos, "", func_return_type);
- if (symbol_container_->exists("functions", func_name)) {
- reportError("Function '" + func_name + "' already defined in this scope");
- }
-
Lexer::Tokens::Token opening_brace = expect(Lexer::Tokens::Type::PUNCTUATION, "{");
- symbol_container_->define("functions", function_symbol);
-
// only parse the body if we checked out if not exists the function and created the symbol
- Symbols::SymbolContainer func_symbols =
- parseFunctionBody(opening_brace, func_return_type != Symbols::Variables::Type::NULL_TYPE);
-
- // create new container for the function
-
- std::cout << "Defined function symbol: " << func_name << " in global scope.\n";
-
- // 3. Új scope nyitása a függvény paraméterei (és később lokális változói) számára
- symbol_container_->enterScope();
- //std::cout << "Entered scope for function: " << func_name << "\n";
-
- // 4. Paraméterek definiálása mint változók az *új* (függvény) scope-ban
- const std::string & param_context = func_name; // Paraméter kontextusa a függvény neve
- for (const auto & p_info : param_infos) {
- auto param_symbol = Symbols::SymbolFactory::createVariable(p_info.name, // Név '$' nélkül
- Symbols::Value(), // Alapértelmezett/üres érték
- param_context, // Kontextus
- p_info.type // Típus
- );
-
- if (symbol_container_->exists("variables", p_info.name)) {
- reportError("Parameter name '" + p_info.name + "' conflicts with another symbol in function '" +
- func_name + "'");
- }
- symbol_container_->define("variables", param_symbol);
- }
-
- // 5. Függvény scope elhagyása
- symbol_container_->leaveScope();
- //std::cout << "Left scope for function: " << func_name << "\n";
-
- // Debugging kiírás (változatlan)
- // std::cout << "Parsed function: " << func_name << " (...) { ... } scope handled.\n";
+ parseFunctionBody(opening_brace, func_name, func_return_type, param_infos);
}
// --- Elemzési Segédfüggvények ---
@@ -337,118 +286,96 @@
reportError("Expected type keyword (string, int, double, float)");
}
- // value : STRING_LITERAL | NUMBER
- // Feldolgozza az értéket a várt típus alapján.
Symbols::Value parseValue(Symbols::Variables::Type expected_var_type) {
- Lexer::Tokens::Token token = currentToken();
+ Lexer::Tokens::Token token = currentToken();
+ bool is_negative = false;
- /// find if this is a function call
- if (token.type == Lexer::Tokens::Type::IDENTIFIER && peekToken().lexeme == "(") {
- for (const auto & symbol_ptr : this->symbol_container_->listNamespace("functions")) {
- if (auto func_symbol = std::dynamic_pointer_cast<Symbols::FunctionSymbol>(symbol_ptr)) {
- // TODO: A függvény hívását kellene feldolgozni, a func_symbol-ból kellene lekérni a paramétereket, func_symbol->plainBody() tartalmazza a függvény törzsét
- // A függvény hívásának feldolgozása
- std::cout << "Function call: " << token.value << "\n";
- while (consumeToken().lexeme != ")") {
- // Feltételezzük, hogy a függvény hívását a lexer már feldolgozta
- }
- return Symbols::Value(""); // TODO: Implementálni a függvény hívását
- }
- }
- }
-
- bool is_negative = false;
- std::cout << "Peek: " << peekToken().lexeme << "\n";
- if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC && peekToken().type == Lexer::Tokens::Type::NUMBER) {
- is_negative = true;
+ // Előjel kezelése
+ if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC && (token.lexeme == "-" || token.lexeme == "+") &&
+ peekToken().type == Lexer::Tokens::Type::NUMBER) {
+ is_negative = (token.lexeme == "-");
token = peekToken();
- consumeToken();
+ consumeToken(); // előjelet elfogyasztottuk
}
+ // STRING típus
if (expected_var_type == Symbols::Variables::Type::STRING) {
if (token.type == Lexer::Tokens::Type::STRING_LITERAL) {
consumeToken();
- return Symbols::Value(token.value); // A lexer value-ja már a feldolgozott string
+ return Symbols::Value(token.value);
}
reportError("Expected string literal value");
- } else if (expected_var_type == Symbols::Variables::Type::INTEGER) {
- if (token.type == Lexer::Tokens::Type::NUMBER) {
- // Konvertálás int-re, hibakezeléssel
- try {
- // TODO: Ellenőrizni, hogy a szám valóban egész-e (nincs benne '.')
- // Most egyszerűen std::stoi-t használunk.
- int int_value = std::stoi(token.value);
- if (is_negative) {
- int_value = -int_value;
- }
- consumeToken();
- return Symbols::Value(int_value);
- } catch (const std::invalid_argument & e) {
- reportError("Invalid integer literal: " + token.value);
- } catch (const std::out_of_range & e) {
- reportError("Integer literal out of range: " + token.value);
- }
- }
- reportError("Expected integer literal value");
- } else if (expected_var_type == Symbols::Variables::Type::DOUBLE) {
- if (token.type == Lexer::Tokens::Type::NUMBER) {
- // Konvertálás double-re, hibakezeléssel
- try {
- double double_value = std::stod(token.value);
- if (is_negative) {
- double_value = -double_value;
- }
- consumeToken();
- return Symbols::Value(double_value);
- } catch (const std::invalid_argument & e) {
- reportError("Invalid double literal: " + token.value);
- } catch (const std::out_of_range & e) {
- reportError("Double literal out of range: " + token.value);
- }
- }
- reportError("Expected numeric literal value for double");
- } else if (expected_var_type == Symbols::Variables::Type::FLOAT) {
- if (token.type == Lexer::Tokens::Type::NUMBER) {
- // Konvertálás double-re, hibakezeléssel
- try {
-
- float float_value = std::atof(token.value.data());
- if (is_negative) {
- float_value = -float_value;
- }
- consumeToken();
- return Symbols::Value(float_value);
- } catch (const std::invalid_argument & e) {
- reportError("Invalid float literal: " + token.value);
- } catch (const std::out_of_range & e) {
- reportError("Float literal out of range: " + token.value);
- }
- }
- reportError("Expected numeric literal value for double");
- } else if (expected_var_type == Symbols::Variables::Type::BOOLEAN) {
- if (token.type == Lexer::Tokens::Type::KEYWORD) {
- consumeToken();
- return Symbols::Value(token.value == "true"); // A lexer value-ja már a feldolgozott string
- }
- reportError("Expected boolean literal value");
- } else {
- // Más típusok (pl. boolean) itt kezelendők, ha lennének
- reportError("Unsupported variable type encountered during value parsing");
}
- // Should not reach here due to reportError throwing
- return Symbols::Value(); // Default return to satisfy compiler
+
+ // BOOLEAN típus
+ if (expected_var_type == Symbols::Variables::Type::BOOLEAN) {
+ if (token.type == Lexer::Tokens::Type::KEYWORD && (token.value == "true" || token.value == "false")) {
+ consumeToken();
+ return Symbols::Value(token.value == "true");
+ }
+ reportError("Expected boolean literal value (true or false)");
+ }
+
+ // NUMERIC típusok
+ if (expected_var_type == Symbols::Variables::Type::INTEGER ||
+ expected_var_type == Symbols::Variables::Type::DOUBLE ||
+ expected_var_type == Symbols::Variables::Type::FLOAT) {
+ if (token.type == Lexer::Tokens::Type::NUMBER) {
+ Symbols::Value val = parseNumericLiteral(token.value, is_negative, expected_var_type);
+ consumeToken();
+ return val;
+ }
+
+ reportError("Expected numeric literal value");
+ }
+
+ reportError("Unsupported variable type encountered during value parsing");
+ return Symbols::Value(); // compiler happy
}
- Symbols::SymbolContainer parseFunctionBody(const Lexer::Tokens::Token & opening_brace,
- bool return_required = false) {
+ Symbols::Value parseNumericLiteral(const std::string & value, bool is_negative, Symbols::Variables::Type type) {
+ try {
+ switch (type) {
+ case Symbols::Variables::Type::INTEGER:
+ {
+ if (value.find('.') != std::string::npos) {
+ throw std::invalid_argument("Floating point value in integer context: " + value);
+ }
+ int v = std::stoi(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ case Symbols::Variables::Type::DOUBLE:
+ {
+ double v = std::stod(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ case Symbols::Variables::Type::FLOAT:
+ {
+ float v = std::stof(value);
+ return Symbols::Value(is_negative ? -v : v);
+ }
+ default:
+ throw std::invalid_argument("Unsupported numeric type");
+ }
+ } catch (const std::invalid_argument & e) {
+ reportError("Invalid numeric literal: " + value + " (" + e.what() + ")");
+ } catch (const std::out_of_range & e) {
+ reportError("Numeric literal out of range: " + value + " (" + e.what() + ")");
+ }
+
+ return Symbols::Value(); // unreachable
+ }
+
+ void parseFunctionBody(const Lexer::Tokens::Token & opening_brace, const std::string & function_name,
+ Symbols::Variables::Type return_type, const Symbols::FunctionParameterInfo & params) {
size_t braceDepth = 0;
+ int peek = 0;
int tokenIndex = current_token_index_;
Lexer::Tokens::Token currentToken_;
Lexer::Tokens::Token closing_brace;
while (tokenIndex < tokens_.size()) {
- currentToken_ = peekToken();
-
+ currentToken_ = peekToken(peek);
if (currentToken_.type == Lexer::Tokens::Type::PUNCTUATION) {
if (currentToken_.value == "{") {
++braceDepth;
@@ -460,6 +387,8 @@
--braceDepth;
}
}
+ tokenIndex++;
+ peek++;
}
if (braceDepth != 0) {
reportError("Unmatched braces in function body");
@@ -468,65 +397,190 @@
auto startIt = std::find(tokens_.begin(), tokens_.end(), opening_brace);
auto endIt = std::find(tokens_.begin(), tokens_.end(), closing_brace);
- // Ellenőrzés: mindkét token megtalálva és start_token megelőzi az end_token-t
if (startIt != tokens_.end() && endIt != tokens_.end() && startIt < endIt) {
filtered_tokens = std::vector<Lexer::Tokens::Token>(startIt + 1, endIt);
}
std::string_view input_string = input_str_view_.substr(opening_brace.end_pos, closing_brace.end_pos);
- auto parser = Parser();
- parser.parseProgram(filtered_tokens, input_string);
- return *parser.getSymbolContainer();
+ current_token_index_ = tokenIndex;
+ expect(Lexer::Tokens::Type::PUNCTUATION, "}");
+ const std::string newns = Symbols::SymbolContainer::instance()->currentScopeName() + "." + function_name;
+ Symbols::SymbolContainer::instance()->create(newns);
+ std::shared_ptr<Parser> parser = std::make_shared<Parser>();
+ parser->parseScript(filtered_tokens, input_string, this->current_filename_);
+ Symbols::SymbolContainer::instance()->enterPreviousScope();
+ // create function
+ Interpreter::OperationsFactory::defineFunction(
+ function_name, params, return_type, Symbols::SymbolContainer::instance()->currentScopeName(),
+ this->current_filename_, currentToken_.line_number, currentToken_.column_number);
}
- std::string parseFunctionBodyOld(size_t body_start_pos, bool return_required = false) {
- std::stringstream body_ss;
- int brace_level = 1;
- size_t last_token_end_pos = body_start_pos;
- bool has_return = false;
+ ParsedExpressionPtr parseParsedExpression(const Symbols::Variables::Type & expected_var_type) {
+ std::stack<std::string> operator_stack;
+ std::vector<ParsedExpressionPtr> output_queue;
+
+ auto getPrecedence = [](const std::string & op) -> int {
+ if (op == "+" || op == "-") {
+ return 1;
+ }
+ if (op == "*" || op == "/") {
+ return 2;
+ }
+ if (op == "u-" || op == "u+") {
+ return 3;
+ }
+ return 0;
+ };
+
+ auto isLeftAssociative = [](const std::string & op) -> bool {
+ return !(op == "u-" || op == "u+");
+ };
+
+ auto applyOperator = [](const std::string & op, ParsedExpressionPtr rhs, ParsedExpressionPtr lhs = nullptr) {
+ if (op == "u-" || op == "u+") {
+ std::string real_op = (op == "u-") ? "-" : "+";
+ return ParsedExpression::makeUnary(real_op, std::move(rhs));
+ } else {
+ return ParsedExpression::makeBinary(op, std::move(lhs), std::move(rhs));
+ }
+ };
+
+ auto pushOperand = [&](const Lexer::Tokens::Token & token) {
+ if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
+ token.type == Lexer::Tokens::Type::KEYWORD) {
+ output_queue.push_back(
+ ParsedExpression::makeLiteral(Symbols::Value::fromString(token.value, expected_var_type)));
+ } else if (token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
+ std::string name = token.value;
+ if (!name.empty() && name[0] == '$') {
+ name = name.substr(1);
+ }
+ output_queue.push_back(ParsedExpression::makeVariable(name));
+ } else {
+ reportError("Expected literal or variable");
+ }
+ };
+
+ bool expect_unary = true;
while (true) {
- if (isAtEnd()) {
- reportError("Unexpected end of file inside function body (missing '}')");
- }
- const auto & token = currentToken();
+ auto token = currentToken();
- // Whitespace visszaállítása (ha volt) az 'input_str_view_' alapján
- if (token.start_pos > last_token_end_pos) {
- if (last_token_end_pos < input_str_view_.length() && token.start_pos <= input_str_view_.length()) {
- body_ss << input_str_view_.substr(last_token_end_pos, token.start_pos - last_token_end_pos);
- } else {
- reportError("Invalid position range in body reconstruction");
+ if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == "(") {
+ operator_stack.push("(");
+ consumeToken();
+ expect_unary = true;
+ } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.lexeme == ")") {
+ consumeToken();
+ while (!operator_stack.empty() && operator_stack.top() != "(") {
+ std::string op = operator_stack.top();
+ operator_stack.pop();
+
+ if (op == "u-" || op == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(op, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
+ }
}
- }
- if (token.type == Lexer::Tokens::Type::KEYWORD_RETURN) {
- has_return = true;
- }
-
- if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.value == "{") {
- brace_level++;
- body_ss << token.lexeme;
- } else if (token.type == Lexer::Tokens::Type::PUNCTUATION && token.value == "}") {
- brace_level--;
- if (brace_level == 0) {
- consumeToken(); // Záró '}' elfogyasztása
- break;
+ if (operator_stack.empty() || operator_stack.top() != "(") {
+ reportError("Mismatched parentheses");
}
- body_ss << token.lexeme;
+ operator_stack.pop(); // remove "("
+ expect_unary = false;
+ } else if (token.type == Lexer::Tokens::Type::OPERATOR_ARITHMETIC) {
+ std::string op = std::string(token.lexeme);
+ if (expect_unary && (op == "-" || op == "+")) {
+ op = "u" + op; // pl. u-
+ }
+
+ while (!operator_stack.empty()) {
+ const std::string & top = operator_stack.top();
+ if ((isLeftAssociative(op) && getPrecedence(op) <= getPrecedence(top)) ||
+ (!isLeftAssociative(op) && getPrecedence(op) < getPrecedence(top))) {
+ operator_stack.pop();
+
+ if (top == "u-" || top == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(top, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(top, std::move(rhs), std::move(lhs)));
+ }
+ } else {
+ break;
+ }
+ }
+
+ operator_stack.push(op);
+ consumeToken();
+ expect_unary = true;
+ } else if (token.type == Lexer::Tokens::Type::NUMBER || token.type == Lexer::Tokens::Type::STRING_LITERAL ||
+ token.type == Lexer::Tokens::Type::KEYWORD ||
+ token.type == Lexer::Tokens::Type::VARIABLE_IDENTIFIER) {
+ pushOperand(token);
+ consumeToken();
+ expect_unary = false;
} else {
- body_ss << token.lexeme;
+ break;
+ }
+ }
+
+ // Kiürítjük az operator stack-et
+ while (!operator_stack.empty()) {
+ std::string op = operator_stack.top();
+ operator_stack.pop();
+
+ if (op == "(" || op == ")") {
+ reportError("Mismatched parentheses");
}
- last_token_end_pos = token.end_pos;
- consumeToken();
+ if (op == "u-" || op == "u+") {
+ if (output_queue.empty()) {
+ reportError("Missing operand for unary operator");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(op, std::move(rhs)));
+ } else {
+ if (output_queue.size() < 2) {
+ reportError("Malformed expression");
+ }
+ auto rhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ auto lhs = std::move(output_queue.back());
+ output_queue.pop_back();
+ output_queue.push_back(applyOperator(op, std::move(rhs), std::move(lhs)));
+ }
}
- if (return_required && !has_return) {
- return "";
+ if (output_queue.size() != 1) {
+ reportError("Expression could not be parsed cleanly");
}
- return body_ss.str();
+ return std::move(output_queue.back());
}
}; // class Parser
--
Gitblit v1.9.3