/* * Parsodus - A language agnostic parser generator * Copyright © 2016-2017 Thomas Avé, Robin Jadoul, Kobe Wullaert * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ #include "parser.h" #include namespace calc { Parser::Parser(CalcLexer lex) : m_lex(lex) { std::cout << ">>> "; std::cout.flush(); } Parser::Token Parser::lex() { while (true) { try { CalcLexer::Token orig = m_lex.nextToken(); Token ret{calcParser_Symbol::T_EOF, nullptr}; if (orig.type == CalcLexer::NUM) { ret = { calcParser_Symbol::T_NUM, std::make_unique(std::stod(orig.content)) }; } else if (orig.type == CalcLexer::IDENT) { ret = { calcParser_Symbol::T_IDENT, std::make_unique(orig.content) }; } else { ret = { static_cast(orig.type), nullptr }; } return ret; } catch (CalcLexer::NoMoreTokens) { return { calcParser_Symbol::T_EOF, nullptr }; } catch (CalcLexer::NoMatch) { m_lex.skip(1); return { calcParser_Symbol::V_error, nullptr }; //Somewhat dependent on the generated code, but this should always give an error } } } Parser::Value Parser::error(Token, const std::vector&) { return nullptr; } Parser::Value Parser::reduce_toplevel(std::deque subparts) { if (subparts.empty()) return nullptr; if (subparts[0].symbol == calcParser_Symbol::V_expr) { std::cout << "\033[3;34m => " << subparts[0].value->eval(m_variables, m_functions) << "\033[0m" << std::endl; } else if (subparts[0].symbol == calcParser_Symbol::V_error) { std::cout << "\033[3;31m => " << "\033[0m" << std::endl; } try { if (m_lex.peek() == '\n') { std::cout << ">>> "; std::cout.flush(); } } catch (CalcLexer::NoMoreTokens) {} return nullptr; } Parser::Value Parser::reduce_binop(std::deque subparts) { std::string op; switch (subparts[1].symbol) { case calcParser_Symbol::T_PLUS: op = "+"; break; case calcParser_Symbol::T_MINUS: op = "-"; break; case calcParser_Symbol::T_TIMES: op = "*"; break; case calcParser_Symbol::T_DIVIDE: op = "/"; break; case calcParser_Symbol::T_EXPONENT: op = "^"; break; case calcParser_Symbol::T_LT: op = "<"; break; default: break; } return std::make_unique(std::move(subparts[0].value), op, std::move(subparts[2].value)); } Parser::Value Parser::reduce_expr_simple(std::deque subparts) { return std::move(subparts[0].value); } Parser::Value Parser::reduce_umin(std::deque subparts) { return std::make_unique("-", std::move(subparts[1].value)); } Parser::Value Parser::reduce_parenthesized(std::deque subparts) { return std::move(subparts[1].value); } Parser::Value Parser::reduce_functioncall(std::deque subparts) { auto args = dynamic_cast(subparts[2].value.get()); subparts[2].value.release(); return std::make_unique(dynamic_cast(subparts[0].value.get())->getName(), std::unique_ptr(args)); } Parser::Value Parser::reduce_opt_arguments(std::deque subparts) { if (subparts.size()) { return std::move(subparts[0].value); } else { return std::make_unique(); } } Parser::Value Parser::reduce_arguments(std::deque subparts) { std::unique_ptr args; if (subparts.size() > 1) { args = std::unique_ptr(dynamic_cast(subparts[0].value.get())); subparts[0].value.release(); } else { args = std::make_unique(); } args->push_back(std::move(subparts[subparts.size() - 1].value)); return args; } Parser::Value Parser::reduce_functiondef(std::deque subparts) { std::string name = dynamic_cast(subparts[1].value.get())->getName(); std::deque formalParams; FormalParameters* fp = dynamic_cast(subparts[3].value.get()); for (const std::unique_ptr& param : *fp) { formalParams.push_back(dynamic_cast(param.get())->getName()); } m_functions[name] = std::make_unique(std::move(formalParams), std::move(subparts[6].value)); std::cout << "\033[3;32m => Function " << name << " defined.\033[0m" << std::endl; return nullptr; } Parser::Value Parser::reduce_opt_idents(std::deque subparts) { if (subparts.size()) { return std::move(subparts[0].value); } else { return std::make_unique(); } } Parser::Value Parser::reduce_idents(std::deque subparts) { std::unique_ptr args; if (subparts.size() > 1) { args = std::unique_ptr(dynamic_cast(subparts[0].value.get())); subparts[0].value.release(); } else { args = std::make_unique(); } args->push_back(std::move(subparts[subparts.size() - 1].value)); return args; } Parser::Value Parser::reduce_assign(std::deque subparts) { std::string name = dynamic_cast(subparts[0].value.get())->getName(); m_variables[name] = subparts[2].value->eval(m_variables, m_functions); std::cout << "\033[3;34m => " << name << " = " << m_variables[name] << "\033[0m" <