mirror of
https://github.com/mamedev/mame.git
synced 2024-11-16 07:48:32 +01:00
Added infix notation parsing to the function parser. (nw)
This commit is contained in:
parent
624463dc34
commit
093bda0193
9 changed files with 154 additions and 32 deletions
|
@ -374,7 +374,7 @@ NETLIST_START(G501534_DIP)
|
|||
//AFUNC(f, 2, "A0 A1 A1 A1 * * 0.01 * *")
|
||||
//AFUNC(f, 2, "A0")
|
||||
//AFUNC(f, 2, "A0 6 - A1 3 pow * 0.02 * 6 +")
|
||||
AFUNC(f, 2, "A0 A1 3 pow * 0.02 *")
|
||||
AFUNC(f, 2, "A0 * pow(A1,3.0) * 0.02")
|
||||
|
||||
/*
|
||||
* 12: VCC
|
||||
|
|
|
@ -323,7 +323,7 @@ namespace netlist
|
|||
inps.push_back(n);
|
||||
m_vals.push_back(0.0);
|
||||
}
|
||||
m_precompiled.compile_postfix(inps, m_func());
|
||||
m_precompiled.compile(inps, m_func());
|
||||
}
|
||||
|
||||
protected:
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
*/
|
||||
|
||||
#include <cmath>
|
||||
#include <stack>
|
||||
#include "pfunction.h"
|
||||
#include "pfmtlog.h"
|
||||
#include "putil.h"
|
||||
|
@ -13,13 +14,27 @@
|
|||
|
||||
namespace plib {
|
||||
|
||||
void pfunction::compile(const std::vector<pstring> &inputs, const pstring expr)
|
||||
{
|
||||
if (expr.startsWith("rpn:"))
|
||||
compile_postfix(inputs, expr.substr(4));
|
||||
else
|
||||
compile_infix(inputs, expr);
|
||||
}
|
||||
|
||||
void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstring expr)
|
||||
{
|
||||
plib::pstring_vector_t cmds(expr, " ");
|
||||
compile_postfix(inputs, cmds, expr);
|
||||
}
|
||||
|
||||
void pfunction::compile_postfix(const std::vector<pstring> &inputs,
|
||||
const std::vector<pstring> &cmds, const pstring expr)
|
||||
{
|
||||
m_precompiled.clear();
|
||||
int stk = 0;
|
||||
|
||||
for (pstring &cmd : cmds)
|
||||
for (const pstring &cmd : cmds)
|
||||
{
|
||||
rpn_inst rc;
|
||||
if (cmd == "+")
|
||||
|
@ -66,6 +81,99 @@ void pfunction::compile_postfix(const std::vector<pstring> &inputs, const pstrin
|
|||
throw plib::pexception(plib::pfmt("nld_function: stack count different to one on <{2}>")(expr));
|
||||
}
|
||||
|
||||
int get_prio(pstring v)
|
||||
{
|
||||
if (v == "(" or v == ")")
|
||||
return 1;
|
||||
else if (v.left(v.begin()+1) >= "a" && v.left(v.begin()+1) <= "z")
|
||||
return 0;
|
||||
else if (v == "*" or v == "/")
|
||||
return 20;
|
||||
else if (v == "+" or v == "-")
|
||||
return 10;
|
||||
else if (v == "^")
|
||||
return 30;
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
|
||||
static pstring pop_check(std::stack<pstring> &stk, const pstring &expr)
|
||||
{
|
||||
if (stk.size() == 0)
|
||||
throw plib::pexception(plib::pfmt("nld_function: stack underflow during infix parsing of: <{1}>")(expr));
|
||||
pstring res = stk.top();
|
||||
stk.pop();
|
||||
return res;
|
||||
}
|
||||
|
||||
void pfunction::compile_infix(const std::vector<pstring> &inputs, const pstring expr)
|
||||
{
|
||||
// Shunting-yard infix parsing
|
||||
std::vector<pstring> sep = {"(", ")", ",", "*", "/", "+", "-", "^"};
|
||||
plib::pstring_vector_t sexpr(expr.replace(" ",""), sep);
|
||||
std::stack<pstring> opstk;
|
||||
plib::pstring_vector_t postfix;
|
||||
|
||||
//printf("dbg: %s\n", expr.c_str());
|
||||
for (unsigned i = 0; i < sexpr.size(); i++)
|
||||
{
|
||||
pstring &s = sexpr[i];
|
||||
if (s=="(")
|
||||
opstk.push(s);
|
||||
else if (s==")")
|
||||
{
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
if (opstk.size() > 0 && get_prio(opstk.top()) == 0)
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
}
|
||||
else if (s==",")
|
||||
{
|
||||
pstring x = pop_check(opstk, expr);
|
||||
while (x != "(")
|
||||
{
|
||||
postfix.push_back(x);
|
||||
x = pop_check(opstk, expr);
|
||||
}
|
||||
opstk.push(x);
|
||||
}
|
||||
else {
|
||||
int p = get_prio(s);
|
||||
if (p>0)
|
||||
{
|
||||
if (opstk.size() == 0)
|
||||
opstk.push(s);
|
||||
else
|
||||
{
|
||||
if (get_prio(opstk.top()) >= get_prio(s))
|
||||
postfix.push_back(pop_check(opstk, expr));
|
||||
opstk.push(s);
|
||||
}
|
||||
}
|
||||
else if (p == 0) // Function or variable
|
||||
{
|
||||
if (sexpr[i+1] == "(")
|
||||
opstk.push(s);
|
||||
else
|
||||
postfix.push_back(s);
|
||||
}
|
||||
else
|
||||
postfix.push_back(s);
|
||||
}
|
||||
}
|
||||
while (opstk.size() > 0)
|
||||
{
|
||||
postfix.push_back(opstk.top());
|
||||
opstk.pop();
|
||||
}
|
||||
compile_postfix(inputs, postfix, expr);
|
||||
}
|
||||
|
||||
|
||||
#define ST1 stack[ptr]
|
||||
#define ST2 stack[ptr-1]
|
||||
|
||||
|
|
|
@ -16,10 +16,10 @@
|
|||
namespace plib {
|
||||
|
||||
//============================================================
|
||||
// function evaluation - reverse polish notation
|
||||
// function evaluation
|
||||
//============================================================
|
||||
|
||||
/*! Class providing support for precompiled rpn expressions
|
||||
/*! Class providing support for evaluating expressions
|
||||
*
|
||||
*/
|
||||
class pfunction
|
||||
|
@ -47,12 +47,26 @@ namespace plib {
|
|||
{
|
||||
}
|
||||
|
||||
/*! Compile an expression
|
||||
*
|
||||
* @param inputs Vector of input variables, e.g. {"A","B"}
|
||||
* @param expr infix or postfix expression. default is infix, postrix
|
||||
* to be prefixed with rpn, e.g. "rpn:A B + 1.3 /"
|
||||
*/
|
||||
void compile(const std::vector<pstring> &inputs, const pstring expr);
|
||||
|
||||
/*! Compile a rpn expression
|
||||
*
|
||||
* @param inputs Vector of input variables, e.g. {"A","B"}
|
||||
* @param expr Reverse polish notation expression, e.g. "A B + 1.3 /"
|
||||
*/
|
||||
void compile_postfix(const std::vector<pstring> &inputs, const pstring expr);
|
||||
/*! Compile an infix expression
|
||||
*
|
||||
* @param inputs Vector of input variables, e.g. {"A","B"}
|
||||
* @param expr Infix expression, e.g. "(A+B)/1.3"
|
||||
*/
|
||||
void compile_infix(const std::vector<pstring> &inputs, const pstring expr);
|
||||
/*! Evaluate the expression
|
||||
*
|
||||
* @param values for input variables, e.g. {1.1, 2.2}
|
||||
|
@ -61,6 +75,10 @@ namespace plib {
|
|||
double evaluate(const std::vector<double> &values);
|
||||
|
||||
private:
|
||||
|
||||
void compile_postfix(const std::vector<pstring> &inputs,
|
||||
const std::vector<pstring> &cmds, const pstring expr);
|
||||
|
||||
std::vector<rpn_inst> m_precompiled; //!< precompiled expression
|
||||
};
|
||||
|
||||
|
|
|
@ -6,10 +6,6 @@
|
|||
*/
|
||||
|
||||
#include <cstring>
|
||||
//FIXME:: pstring should be locale free
|
||||
#include <cctype>
|
||||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
#include <algorithm>
|
||||
#include <stack>
|
||||
|
||||
|
@ -17,6 +13,8 @@
|
|||
#include "palloc.h"
|
||||
#include "plists.h"
|
||||
|
||||
template <typename F> pstr_t pstring_t<F>::m_zero(0);
|
||||
|
||||
template<typename F>
|
||||
pstring_t<F>::~pstring_t()
|
||||
{
|
||||
|
@ -373,7 +371,7 @@ void pstringbuffer::pcat(const pstring &s)
|
|||
* This improves startup performance by 30%.
|
||||
*/
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
|
||||
static std::stack<pstr_t *> *stk = nullptr;
|
||||
|
||||
|
@ -416,8 +414,8 @@ static inline std::size_t countleadbits(std::size_t x)
|
|||
template<typename F>
|
||||
void pstring_t<F>::sfree(pstr_t *s)
|
||||
{
|
||||
s->m_ref_count--;
|
||||
if (s->m_ref_count == 0 && s != &m_zero)
|
||||
bool b = s->dec_and_check();
|
||||
if ( b && s != &m_zero)
|
||||
{
|
||||
if (stk != nullptr)
|
||||
{
|
||||
|
@ -472,8 +470,8 @@ void pstring_t<F>::resetmem()
|
|||
template<typename F>
|
||||
void pstring_t<F>::sfree(pstr_t *s)
|
||||
{
|
||||
s->m_ref_count--;
|
||||
if (s->m_ref_count == 0 && s != &m_zero)
|
||||
bool b = s->dec_and_check();
|
||||
if ( b && s != &m_zero)
|
||||
{
|
||||
plib::pfree_array(((char *)s));
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#include <cstdarg>
|
||||
#include <cstddef>
|
||||
#include <iterator>
|
||||
#include <exception>
|
||||
|
||||
#include "pconfig.h"
|
||||
|
||||
|
@ -22,27 +23,24 @@
|
|||
|
||||
struct pstr_t
|
||||
{
|
||||
//str_t() : m_ref_count(1), m_len(0) { m_str[0] = 0; }
|
||||
pstr_t(const std::size_t alen)
|
||||
{
|
||||
init(alen);
|
||||
}
|
||||
pstr_t(const int alen) { init(alen); }
|
||||
void init(const std::size_t alen)
|
||||
{
|
||||
m_ref_count = 1;
|
||||
m_len = alen;
|
||||
m_str[0] = 0;
|
||||
m_ref_count = 1;
|
||||
m_len = alen;
|
||||
m_str[0] = 0;
|
||||
}
|
||||
char *str() { return &m_str[0]; }
|
||||
unsigned char *ustr() { return reinterpret_cast<unsigned char *>(&m_str[0]); }
|
||||
std::size_t len() const { return m_len; }
|
||||
int m_ref_count;
|
||||
void inc() { m_ref_count++; }
|
||||
bool dec_and_check() { --m_ref_count; return m_ref_count == 0; }
|
||||
private:
|
||||
int m_ref_count;
|
||||
std::size_t m_len;
|
||||
char m_str[1];
|
||||
};
|
||||
|
||||
|
||||
template <typename F>
|
||||
struct pstring_t
|
||||
{
|
||||
|
@ -75,7 +73,8 @@ public:
|
|||
pstring_t(C (&string)[N]) : m_ptr(&m_zero) {
|
||||
static_assert(std::is_same<C, const mem_t>::value, "pstring constructor only accepts const mem_t");
|
||||
static_assert(N>0,"pstring from array of length 0");
|
||||
//static_assert(string[N-1] == 0, "pstring constructor parameter not a string literal");
|
||||
if (string[N-1] != 0)
|
||||
throw std::exception();
|
||||
init(string);
|
||||
}
|
||||
|
||||
|
@ -185,13 +184,13 @@ protected:
|
|||
private:
|
||||
void init(const mem_t *string)
|
||||
{
|
||||
m_ptr->m_ref_count++;
|
||||
m_ptr->inc();
|
||||
if (string != nullptr && *string != 0)
|
||||
pcopy(string);
|
||||
}
|
||||
void init(const pstring_t &string)
|
||||
{
|
||||
m_ptr->m_ref_count++;
|
||||
m_ptr->inc();
|
||||
pcopy(string);
|
||||
}
|
||||
|
||||
|
@ -206,7 +205,7 @@ private:
|
|||
{
|
||||
sfree(m_ptr);
|
||||
m_ptr = from.m_ptr;
|
||||
m_ptr->m_ref_count++;
|
||||
m_ptr->inc();
|
||||
}
|
||||
void pcat(const mem_t *s);
|
||||
void pcat(const pstring_t &s);
|
||||
|
@ -217,8 +216,6 @@ private:
|
|||
static pstr_t m_zero;
|
||||
};
|
||||
|
||||
template <typename F> pstr_t pstring_t<F>::m_zero(0);
|
||||
|
||||
struct pu8_traits
|
||||
{
|
||||
static const unsigned MAXCODELEN = 1; /* in memory units */
|
||||
|
|
|
@ -62,7 +62,7 @@ namespace plib
|
|||
}
|
||||
}
|
||||
|
||||
pstring_vector_t::pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl)
|
||||
pstring_vector_t::pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl)
|
||||
: std::vector<pstring>()
|
||||
{
|
||||
pstring col = "";
|
||||
|
|
|
@ -71,7 +71,7 @@ namespace plib
|
|||
public:
|
||||
pstring_vector_t() : std::vector<pstring>() { }
|
||||
pstring_vector_t(const pstring &str, const pstring &onstr, bool ignore_empty = false);
|
||||
pstring_vector_t(const pstring &str, const pstring_vector_t &onstrl);
|
||||
pstring_vector_t(const pstring &str, const std::vector<pstring> &onstrl);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -502,6 +502,7 @@ static const pstring pmf_verbose[] =
|
|||
};
|
||||
#endif
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
tool_options_t opts;
|
||||
|
|
Loading…
Reference in a new issue