Exemple #1
0
        static string pop_check(std.stack <string> stk, string expr)
        {
            if (stk.empty())
            {
                throw new pexception(new plib.pfmt("pfunction: stack underflow during infix parsing of: <{0}>").op(expr));
            }
            string res = stk.top();

            stk.pop();
            return(res);
        }
Exemple #2
0
        public void compile_infix(string expr, std.vector <string> inputs)  //void compile_infix(const pstring &expr, const inputs_container &inputs = inputs_container()) noexcept(false);
        {
            // Shunting-yard infix parsing
            std.vector <string> sep = new std.vector <string> {
                "(", ")", ",", "*", "/", "+", "-", "^", "<=", ">=", "==", "!=", "<", ">"
            };
            std.vector <string> sexpr2  = plib.pg.psplit(plib.pg.replace_all(expr, " ", ""), sep);
            std.stack <string>  opstk   = new std.stack <string>();
            std.vector <string> postfix = new std.vector <string>();
            std.vector <string> sexpr1  = new std.vector <string>();
            std.vector <string> sexpr   = new std.vector <string>();

            // FIXME: We really need to switch to ptokenizer and fix negative number
            //        handling in ptokenizer.

            // copy/paste to the int version below

            // Fix numbers exponential numbers
            for (size_t i = 0; i < sexpr2.size();)
            {
                if (i + 2 < sexpr2.size() && sexpr2[i].length() > 1)
                {
                    var r  = plib.pg.right(sexpr2[i], 1);
                    var ne = sexpr2[i + 1];
                    if (is_number(sexpr2[i]) &&
                        (r == "e" || r == "E") &&
                        (ne == "-" || ne == "+"))
                    {
                        sexpr1.push_back(sexpr2[i] + ne + sexpr2[i + 2]);
                        i += 3;
                    }
                    else
                    {
                        sexpr1.push_back(sexpr2[i++]);
                    }
                }
                else
                {
                    sexpr1.push_back(sexpr2[i++]);
                }
            }

            // Fix numbers with unary minus/plus
            for (size_t i = 0; i < sexpr1.size();)
            {
                if (sexpr1[i] == "-" && (i + 1 < sexpr1.size()) && is_number(sexpr1[i + 1]))
                {
                    if (i == 0 || !(is_number(sexpr1[i - 1]) || sexpr1[i - 1] == ")" || is_id(sexpr1[i - 1])))
                    {
                        sexpr.push_back("-" + sexpr1[i + 1]);
                        i += 2;
                    }
                    else
                    {
                        sexpr.push_back(sexpr1[i++]);
                    }
                }
                else if (sexpr1[i] == "-" && (i + 1 < sexpr1.size()) && (is_id(sexpr1[i + 1]) || sexpr1[i + 1] == "("))
                {
                    if (i == 0 || !(is_number(sexpr1[i - 1]) || sexpr1[i - 1] == ")" || is_id(sexpr1[i - 1])))
                    {
                        sexpr.emplace_back("neg");
                        sexpr.push_back(sexpr1[i + 1]);
                        i += 2;
                    }
                    else
                    {
                        sexpr.push_back(sexpr1[i++]);
                    }
                }
                else
                {
                    sexpr.push_back(sexpr1[i++]);
                }
            }

            for (size_t i = 0; i < sexpr.size(); i++)
            {
                string s = sexpr[i];
                if (s == "(")
                {
                    opstk.push(s);
                }
                else if (s == ")")
                {
                    string x = pop_check(opstk, expr);
                    while (x != "(")
                    {
                        postfix.push_back(x);
                        x = pop_check(opstk, expr);
                    }

                    if (!opstk.empty() && get_prio(opstk.top()) == 0)
                    {
                        postfix.push_back(pop_check(opstk, expr));
                    }
                }
                else if (s == ",")
                {
                    string x = pop_check(opstk, expr);
                    while (x != "(")
                    {
                        postfix.push_back(x);
                        x = pop_check(opstk, expr);
                    }

                    opstk.push(x);
                }
                else
                {
                    int prio = get_prio(s);
                    if (prio > 0)
                    {
                        if (opstk.empty())
                        {
                            opstk.push(s);
                        }
                        else
                        {
                            if (get_prio(opstk.top()) >= prio)
                            {
                                postfix.push_back(pop_check(opstk, expr));
                            }

                            opstk.push(s);
                        }
                    }
                    else if (prio == 0) // Function or variable
                    {
                        if ((i + 1 < sexpr.size()) && sexpr[i + 1] == "(")
                        {
                            opstk.push(s);
                        }
                        else
                        {
                            postfix.push_back(s);
                        }
                    }
                    else
                    {
                        postfix.push_back(s);
                    }
                }
            }

            while (!opstk.empty())
            {
                postfix.push_back(opstk.top());
                opstk.pop();
            }

            //for (auto &e : postfix)
            //  printf("\t%s\n", e.c_str());
            compile_postfix(inputs, postfix, expr);
        }