summaryrefslogtreecommitdiffstatshomepage
path: root/src/lib/netlist
diff options
context:
space:
mode:
author couriersud <couriersud@gmx.org>2017-01-22 23:36:54 +0100
committer couriersud <couriersud@gmx.org>2017-01-25 22:17:46 +0100
commit093bda019317a5a66699b35f8b25ab73802f1f1c (patch)
treeb0e35b6f83d8cba9f7d69eda8c857cf799f1bfc1 /src/lib/netlist
parent624463dc3457e2719af007a6afee3da107af4a94 (diff)
Added infix notation parsing to the function parser. (nw)
Diffstat (limited to 'src/lib/netlist')
-rw-r--r--src/lib/netlist/devices/nlid_system.h2
-rw-r--r--src/lib/netlist/plib/pfunction.cpp110
-rw-r--r--src/lib/netlist/plib/pfunction.h22
-rw-r--r--src/lib/netlist/plib/pstring.cpp16
-rw-r--r--src/lib/netlist/plib/pstring.h29
-rw-r--r--src/lib/netlist/plib/putil.cpp2
-rw-r--r--src/lib/netlist/plib/putil.h2
-rw-r--r--src/lib/netlist/prg/nltool.cpp1
8 files changed, 153 insertions, 31 deletions
diff --git a/src/lib/netlist/devices/nlid_system.h b/src/lib/netlist/devices/nlid_system.h
index f2d893c7d28..5c29d40fd94 100644
--- a/src/lib/netlist/devices/nlid_system.h
+++ b/src/lib/netlist/devices/nlid_system.h
@@ -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:
diff --git a/src/lib/netlist/plib/pfunction.cpp b/src/lib/netlist/plib/pfunction.cpp
index c0f3e18a4f2..004d0f3be86 100644
--- a/src/lib/netlist/plib/pfunction.cpp
+++ b/src/lib/netlist/plib/pfunction.cpp
@@ -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]
diff --git a/src/lib/netlist/plib/pfunction.h b/src/lib/netlist/plib/pfunction.h
index 2ad32106569..0f4960d4e1c 100644
--- a/src/lib/netlist/plib/pfunction.h
+++ b/src/lib/netlist/plib/pfunction.h
@@ -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
};
diff --git a/src/lib/netlist/plib/pstring.cpp b/src/lib/netlist/plib/pstring.cpp
index 7d676f34c0d..1a65bb152ff 100644
--- a/src/lib/netlist/plib/pstring.cpp
+++ b/src/lib/netlist/plib/pstring.cpp
@@ -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));
}
diff --git a/src/lib/netlist/plib/pstring.h b/src/lib/netlist/plib/pstring.h
index 999bd10ce6b..059df4b6376 100644
--- a/src/lib/netlist/plib/pstring.h
+++ b/src/lib/netlist/plib/pstring.h
@@ -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 */
diff --git a/src/lib/netlist/plib/putil.cpp b/src/lib/netlist/plib/putil.cpp
index b21f945662c..7007c818384 100644
--- a/src/lib/netlist/plib/putil.cpp
+++ b/src/lib/netlist/plib/putil.cpp
@@ -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 = "";
diff --git a/src/lib/netlist/plib/putil.h b/src/lib/netlist/plib/putil.h
index 728a475dd28..e340acbd8ec 100644
--- a/src/lib/netlist/plib/putil.h
+++ b/src/lib/netlist/plib/putil.h
@@ -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);
};
}
diff --git a/src/lib/netlist/prg/nltool.cpp b/src/lib/netlist/prg/nltool.cpp
index 19b453cb069..910f9078561 100644
--- a/src/lib/netlist/prg/nltool.cpp
+++ b/src/lib/netlist/prg/nltool.cpp
@@ -502,6 +502,7 @@ static const pstring pmf_verbose[] =
};
#endif
+
int main(int argc, char *argv[])
{
tool_options_t opts;