Commit 94d28dcc authored by Tobias WEBER's avatar Tobias WEBER
Browse files

general functions

parent d9c1309c
......@@ -19,6 +19,23 @@ using t_real = t_real_cli;
// evaluation of symbols
// ----------------------------------------------------------------------------
/**
* symbol type name
*/
const std::string& Symbol::get_type_name(const Symbol &sym)
{
static const std::unordered_map<SymbolType, std::string> map =
{
std::make_pair(SymbolType::REAL, "real"),
std::make_pair(SymbolType::STRING, "string"),
std::make_pair(SymbolType::LIST, "list"),
std::make_pair(SymbolType::DATASET, "dataset"),
};
return map.find(sym.GetType())->second;
}
/**
* unary minus of a symbol
*/
......@@ -285,21 +302,34 @@ std::shared_ptr<Symbol> CliASTAssign::Eval(CliParserContext& ctx) const
if(!m_left || !m_right)
return nullptr;
if(m_left->GetType() != CliASTType::IDENT && m_left->GetType() != CliASTType::STRING)
if(m_left->GetType() != CliASTType::IDENT /*&& m_left->GetType() != CliASTType::STRING*/)
{
ctx.PrintError("Left-hand side of assignment has to be an identifier.");
return nullptr;
}
if(auto righteval=m_right->Eval(ctx); righteval)
// get identifier to be assigned
std::string ident;
if(m_left->GetType() == CliASTType::IDENT)
ident = dynamic_cast<CliASTIdent&>(*m_left).GetValue();
//else if(m_left->GetType() == CliASTType::STRING)
// ident = dynamic_cast<CliASTString&>(*m_left).GetValue();
// // TODO: Check if string is also a valid identifier!
// is this variable already in the constants map?
auto iterConst = g_consts_real.find(ident);
if(iterConst != g_consts_real.end())
{
std::string ident;
if(m_left->GetType() == CliASTType::IDENT)
ident = dynamic_cast<CliASTIdent&>(*m_left).GetValue();
else if(m_left->GetType() == CliASTType::STRING)
ident = dynamic_cast<CliASTString&>(*m_left).GetValue();
// TODO: Check if string is also a valid identifier!
ctx.PrintError("Identifier \"", ident, "\" cannot be re-assigned, it names an internal constant.");
return nullptr;
}
// assign variable
if(auto righteval=m_right->Eval(ctx); righteval)
{
const auto [iter, insert_ok] =
workspace->emplace(std::make_pair(ident, righteval));
......@@ -450,39 +480,42 @@ std::shared_ptr<Symbol> CliASTCall::Eval(CliParserContext& ctx) const
if(args.size() == 1) // function call with one argument requested
{
// real argument
if(args[0]->GetType() == SymbolType::REAL)
{
auto iter = g_funcs_real_1arg.find(ident);
if(iter == g_funcs_real_1arg.end())
{
ctx.PrintError("No real one-argument function \"", ident, "\" was found.");
return nullptr;
}
if(auto iter = g_funcs_gen_1arg.find(ident); iter != g_funcs_gen_1arg.end())
{ // general function
return (*iter->second)(args[0]);
}
else if(auto iter = g_funcs_real_1arg.find(ident);
iter != g_funcs_real_1arg.end() && args[0]->GetType() == SymbolType::REAL)
{ // real function
t_real funcval = (*iter->second)(dynamic_cast<SymbolReal&>(*args[0]).GetValue());
return std::make_shared<SymbolReal>(funcval);
}
else
{
ctx.PrintError("No suitable one-argument function \"", ident, "\" was found.");
return nullptr;
}
}
else if(args.size() == 2) // function call with two arguments requested
{
// real arguments
if(args[0]->GetType() == SymbolType::REAL && args[1]->GetType() == SymbolType::REAL)
// real function
if(auto iter = g_funcs_real_2args.find(ident);
iter != g_funcs_real_2args.end() &&
args[0]->GetType() == SymbolType::REAL && args[1]->GetType() == SymbolType::REAL)
{
auto iter = g_funcs_real_2args.find(ident);
if(iter == g_funcs_real_2args.end())
{
ctx.PrintError("No real two-argument function \"", ident, "\" was found.");
return nullptr;
}
t_real arg1 = dynamic_cast<SymbolReal&>(*args[0]).GetValue();
t_real arg2 = dynamic_cast<SymbolReal&>(*args[1]).GetValue();
t_real funcval = (*iter->second)(arg1, arg2);
return std::make_shared<SymbolReal>(funcval);
}
else
{
ctx.PrintError("No suitable two-argument function \"", ident, "\" was found.");
return nullptr;
}
}
ctx.PrintError("No suitable ", args.size(), "-argument function \"", ident, "\" was found.");
return nullptr;
}
......@@ -528,6 +561,18 @@ std::shared_ptr<Symbol> CliASTExprList::Eval(CliParserContext& ctx) const
return std::make_shared<SymbolList>(vec);
}
/**
* array
*/
std::shared_ptr<Symbol> CliASTArray::Eval(CliParserContext& ctx) const
{
if(!m_left)
return nullptr;
return nullptr;
}
// ----------------------------------------------------------------------------
......@@ -623,4 +668,11 @@ void CliASTExprList::Print(std::ostringstream &ostr, int indent) const
ostr << "op: expr_list\n";
CliAST::Print(ostr, indent);
}
void CliASTArray::Print(std::ostringstream &ostr, int indent) const
{
for(int i=0; i<indent; ++i) ostr << "\t";
ostr << "op: array\n";
CliAST::Print(ostr, indent);
}
// ----------------------------------------------------------------------------
......@@ -37,6 +37,8 @@ real (([0-9]+\.?[0-9]*)|(\.[0-9]+))
"(" { return yy::CliParser::make_TOK_BRACKET_OPEN(); }
")" { return yy::CliParser::make_TOK_BRACKET_CLOSE(); }
"[" { return yy::CliParser::make_TOK_SQBRACKET_OPEN(); }
"]" { return yy::CliParser::make_TOK_SQBRACKET_CLOSE(); }
"+" { return yy::CliParser::make_TOK_PLUS(); }
"-" { return yy::CliParser::make_TOK_MINUS(); }
"*" { return yy::CliParser::make_TOK_MULT(); }
......
......@@ -129,6 +129,8 @@ public:
static std::shared_ptr<Symbol> div(const Symbol &sym1, const Symbol &sym2);
static std::shared_ptr<Symbol> mod(const Symbol &sym1, const Symbol &sym2);
static std::shared_ptr<Symbol> pow(const Symbol &sym1, const Symbol &sym2);
static const std::string& get_type_name(const Symbol &sym);
};
......@@ -225,7 +227,8 @@ enum class CliASTType
MOD,
POW,
CALL,
EXPRLIST
EXPRLIST,
ARRAY,
};
......@@ -402,6 +405,18 @@ public:
virtual CliASTType GetType() const override { return CliASTType::EXPRLIST; }
};
class CliASTArray : public CliAST
{
public:
using CliAST::CliAST;
virtual void Print(std::ostringstream &ostr, int indent = 0) const override;
virtual std::shared_ptr<Symbol> Eval(CliParserContext& ctx) const override;
virtual CliASTType GetType() const override { return CliASTType::ARRAY; }
};
// ----------------------------------------------------------------------------
......
......@@ -18,6 +18,7 @@
%token<t_real_cli> TOK_REAL
%token<std::string> TOK_STRING TOK_IDENT
%token TOK_BRACKET_OPEN TOK_BRACKET_CLOSE
%token TOK_SQBRACKET_OPEN TOK_SQBRACKET_CLOSE
%token TOK_PLUS TOK_MINUS TOK_MULT TOK_DIV TOK_MOD TOK_POW
%token TOK_ASSIGN
%token TOK_COMMA
......@@ -69,6 +70,9 @@ expression
{ $$ = std::make_shared<CliASTAssign>($1, $3); }
| ident TOK_BRACKET_OPEN expressions TOK_BRACKET_CLOSE
{ $$ = std::make_shared<CliASTCall>($1, $3); }
| TOK_SQBRACKET_OPEN expressions TOK_SQBRACKET_CLOSE
{ $$ = std::make_shared<CliASTArray>($2); }
| TOK_BRACKET_OPEN expression TOK_BRACKET_CLOSE
{ $$ = $2; }
......
......@@ -12,8 +12,9 @@
using t_real = t_real_cli;
// ----------------------------------------------------------------------------
/**
* real functions with one argument
* map of real functions with one argument
*/
std::unordered_map<std::string, t_real_cli(*)(t_real)> g_funcs_real_1arg =
{
......@@ -56,7 +57,7 @@ std::unordered_map<std::string, t_real_cli(*)(t_real)> g_funcs_real_1arg =
/**
* real functions with two arguments
* map of real functions with two arguments
*/
std::unordered_map<std::string, t_real_cli(*)(t_real, t_real)> g_funcs_real_2args =
{
......@@ -74,13 +75,40 @@ std::unordered_map<std::string, t_real_cli(*)(t_real, t_real)> g_funcs_real_2arg
std::make_pair("copysign", static_cast<t_real(*)(t_real, t_real)>(&std::copysign)),
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* typeof function
*/
static std::shared_ptr<Symbol> func_typeof(std::shared_ptr<Symbol> sym)
{
const std::string& ty = Symbol::get_type_name(*sym);
return std::make_shared<SymbolString>(ty);
}
/**
* real constants
* map of general functions with one argument
*/
std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbol>)> g_funcs_gen_1arg =
{
std::make_pair("typeof", &func_typeof),
};
// ----------------------------------------------------------------------------
// ----------------------------------------------------------------------------
/**
* map of real constants
*/
std::unordered_map<std::string, t_real_cli> g_consts_real
{
std::make_pair("pi", t_real(M_PI)),
};
\ No newline at end of file
};
// ----------------------------------------------------------------------------
......@@ -10,14 +10,18 @@
#include <unordered_map>
#include <string>
#include <memory>
#include "cliparser_types.h"
#include "cliparser.h"
// functions
// real functions
extern std::unordered_map<std::string, t_real_cli(*)(t_real_cli)> g_funcs_real_1arg;
extern std::unordered_map<std::string, t_real_cli(*)(t_real_cli, t_real_cli)> g_funcs_real_2args;
// general functions
extern std::unordered_map<std::string, std::shared_ptr<Symbol>(*)(std::shared_ptr<Symbol>)> g_funcs_gen_1arg;
// constants
extern std::unordered_map<std::string, t_real_cli> g_consts_real;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment