149 lines
5.0 KiB
C++
149 lines
5.0 KiB
C++
#include "parser.h"
|
|
|
|
#include <iostream>
|
|
|
|
namespace calc {
|
|
|
|
Parser::Parser(CalcLexer lex) : m_lex(lex)
|
|
{}
|
|
|
|
Parser::Token Parser::lex() {
|
|
while (true) {
|
|
try {
|
|
CalcLexer::Token orig = m_lex.nextToken();
|
|
if (orig.type == CalcLexer::NUM) {
|
|
return { calcParser_Symbol::T_NUM, std::make_unique<Number>(std::stod(orig.content)) };
|
|
} else if (orig.type == CalcLexer::IDENT) {
|
|
return { calcParser_Symbol::T_IDENT, std::make_unique<Var>(orig.content) };
|
|
} else {
|
|
return { static_cast<calcParser_Symbol>(orig.type), nullptr };
|
|
}
|
|
}
|
|
catch (CalcLexer::NoMoreTokens) {
|
|
return { calcParser_Symbol::T_EOF, nullptr };
|
|
}
|
|
catch (CalcLexer::NoMatch) {
|
|
std::cerr << "Syntax error: unrecognized token" << std::endl;
|
|
m_lex.skip(1);
|
|
}
|
|
}
|
|
}
|
|
|
|
Parser::Value Parser::error(Token, const std::vector<calcParser_Symbol>&) {
|
|
return nullptr;
|
|
}
|
|
|
|
Parser::Value Parser::reduce_toplevel(std::deque<Token> subparts) {
|
|
if (subparts.empty()) return nullptr;
|
|
if (subparts[0].symbol == calcParser_Symbol::V_expr) {
|
|
std::cout << "=> " << subparts[0].value->eval(m_variables, m_functions) << std::endl;
|
|
} else if (subparts[0].symbol == calcParser_Symbol::V_error) {
|
|
std::cout << "=> <syntax error>" << std::endl;
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
Parser::Value Parser::reduce_binop(std::deque<Token> 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;
|
|
default:
|
|
break;
|
|
}
|
|
return std::make_unique<Binop>(std::move(subparts[0].value), op, std::move(subparts[2].value));
|
|
}
|
|
|
|
Parser::Value Parser::reduce_expr_simple(std::deque<Token> subparts) {
|
|
return std::move(subparts[0].value);
|
|
}
|
|
|
|
Parser::Value Parser::reduce_umin(std::deque<Token> subparts) {
|
|
return std::make_unique<Unop>("-", std::move(subparts[1].value));
|
|
}
|
|
|
|
Parser::Value Parser::reduce_parenthesized(std::deque<Token> subparts) {
|
|
return std::move(subparts[1].value);
|
|
}
|
|
|
|
Parser::Value Parser::reduce_functioncall(std::deque<Token> subparts) {
|
|
auto args = dynamic_cast<FunctionArguments*>(subparts[2].value.get());
|
|
subparts[2].value.release();
|
|
return std::make_unique<FunctionCall>(dynamic_cast<Var*>(subparts[0].value.get())->getName(), std::unique_ptr<FunctionArguments>(args));
|
|
}
|
|
|
|
Parser::Value Parser::reduce_opt_arguments(std::deque<Token> subparts) {
|
|
if (subparts.size()) {
|
|
return std::move(subparts[0].value);
|
|
} else {
|
|
return std::make_unique<FunctionArguments>();
|
|
}
|
|
}
|
|
|
|
Parser::Value Parser::reduce_arguments(std::deque<Token> subparts) {
|
|
std::unique_ptr<FunctionArguments> args;
|
|
if (subparts.size() > 1) {
|
|
args = std::unique_ptr<FunctionArguments>(dynamic_cast<FunctionArguments*>(subparts[0].value.get()));
|
|
subparts[0].value.release();
|
|
} else {
|
|
args = std::make_unique<FunctionArguments>();
|
|
}
|
|
args->push_back(std::move(subparts[subparts.size() - 1].value));
|
|
return args;
|
|
}
|
|
|
|
Parser::Value Parser::reduce_functiondef(std::deque<Token> subparts) {
|
|
std::string name = dynamic_cast<Var*>(subparts[1].value.get())->getName();
|
|
std::deque<std::string> formalParams;
|
|
FormalParameters* fp = dynamic_cast<FormalParameters*>(subparts[3].value.get());
|
|
for (const std::unique_ptr<AST>& param : *fp) {
|
|
formalParams.push_back(dynamic_cast<Var*>(param.get())->getName());
|
|
}
|
|
|
|
m_functions[name] = std::make_unique<Function>(std::move(formalParams), std::move(subparts[6].value));
|
|
std::cout << "=> Function " << name << " defined." << std::endl;
|
|
return nullptr;
|
|
}
|
|
|
|
Parser::Value Parser::reduce_opt_idents(std::deque<Token> subparts) {
|
|
if (subparts.size()) {
|
|
return std::move(subparts[0].value);
|
|
} else {
|
|
return std::make_unique<FormalParameters>();
|
|
}
|
|
}
|
|
|
|
Parser::Value Parser::reduce_idents(std::deque<Token> subparts) {
|
|
std::unique_ptr<FormalParameters> args;
|
|
if (subparts.size() > 1) {
|
|
args = std::unique_ptr<FormalParameters>(dynamic_cast<FormalParameters*>(subparts[0].value.get()));
|
|
subparts[0].value.release();
|
|
} else {
|
|
args = std::make_unique<FormalParameters>();
|
|
}
|
|
args->push_back(std::move(subparts[subparts.size() - 1].value));
|
|
return args;
|
|
}
|
|
|
|
Parser::Value Parser::reduce_assign(std::deque<Token> subparts) {
|
|
std::string name = dynamic_cast<Var*>(subparts[0].value.get())->getName();
|
|
m_variables[name] = subparts[2].value->eval(m_variables, m_functions);
|
|
std::cout << "=> " << name << " = " << m_variables[name] << std::endl;
|
|
return nullptr;
|
|
}
|
|
|
|
} /* calc */
|