我试图实现一个
输入:

~1^(2~&3)|1 69 11111 -12

输出:
[whatever NOT 69 XOR (11111 NAND -12) OR 69 equals]

所有按位运算符具有相同的优先级,从左到右求值我正在构造的算法基本上是
Get number n1 (or evaluation of expression in parenthesis)
Set result = n1
Get operator o1
Get number n2 (or evaluation of expression in parenthesis)
Set result = result op n2
Get operator o2
Get number n3 (or evaluation of expression in paranthesis)
Set result = result o2 n3
Etcetera

我还没有完全完成,但我至少应该能够评估
((1)) 69

会导致
69

我已经测试过了
(1) 69

结果
69

这意味着我只需要找出嵌套括号的问题所在。
我的代码的相关部分,很好的注释,是…在这里忍受我。。。
    private static long? EvalInner ( string eqtn, Tuple<int,int> eqtnBnds, Dictionary<int,long> eqtnArgs)
    {
        //     eqtn: Equation to be parsed
        // eqtnBnds: Bounds that define sub-equation being evaluated.
        // eqtnargs: Equation arguments

        // Parses and returns the evaluation of the equation eqtn in the bounds [eqtnBands.Item1, eqtnBnds.Item2)

        // Handle case of empty sub-equation:
        if (eqtnBnds.Item1 == eqtnBnds.Item2) throw new Exception(String.Format("Encountered empty equation at index {0}", eqtnBnds.Item1));


        long? result = null;
        char? lastop = null; // last operator found
        bool negateNextNum = false;
        PARSEMODE CURMODE = PARSEMODE.NUM; // beginning of equation should be a number since the form of the equation is
                                           // <NUM><OPER><NUM><OPER>...<OPER><NUM>
        int curidx = eqtnBnds.Item1, offend = eqtnBnds.Item2;
        while ( curidx < offend )
        {
            switch ( CURMODE )
            {
                case PARSEMODE.NUM: // Expecting character at current index to be the beginning of a
                {
                    if ( eqtn[curidx] >= '0' && eqtn[curidx] <= '9' ) // beginning of the int corresponding to the argument index
                    {
                        int begidx = curidx;
                        // Increment curidx to one after the last digit or the end of the subequation
                        while ( ++curidx < offend && eqtn[curidx] >= '0' && eqtn[curidx] <= '9' );
                        // Try to get an integer representation of the argument. If an error is encountered in that parsing,
                        // throw an error. If the argument is one within the range of arguments given in the command line,
                        // get its value and update result accordingly. If not, throw an error.
                        int argnum;
                        if ( Int32.TryParse(eqtn.Substring(begidx, curidx - begidx), out argnum) )
                        {
                            if (eqtnArgs.ContainsKey(argnum))
                            {
                                result = (result != null ? BinOpEval(result, lastop, eqtnArgs[argnum]) : eqtnArgs[argnum]);
                                if (negateNextNum)
                                {
                                    result = ~result;
                                    negateNextNum = false;
                                }
                            }
                            else
                                throw new Exception(String.Format("Argument {0} found in the equation beginning at index {1} is out-of-bounds",
                                                                   argnum,
                                                                   begidx)
                                                    );
                        }
                        else
                        {
                            throw new Exception(String.Format("Trouble parsing argument number that begins at index {0}",
                                                               begidx)
                                                );
                        }
                        CURMODE = PARSEMODE.OPER;
                    }
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }
                        if ( netparens != 0 ) // didn't find closing parenthesis
                            throw new Exception(String.Format("Couldn't find closing paranthesis for opening paranthesis at index {0}",
                                                               begidx)
                                                );
                        long? presult = null; // to be the result of the evaluated subequation between the set of parenthesis
                        try { presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs); }
                        catch ( Exception e ) { throw e; }
                        result = (result != null ? BinOpEval(result,lastop,presult) : presult);
                        if (negateNextNum)
                        {
                            result = ~result;
                            negateNextNum = false;
                        }
                        // Upon leaving this else-if block, curidx should be 1 after the closing paranthesis
                        // Expect operate to following closing paranthesis
                        CURMODE = PARSEMODE.OPER; // expecting operator after parens
                    }
                    else if ( eqtn[curidx] == Calculator.NOT ) // NOT symbol preceding number
                    {
                        negateNextNum = !negateNextNum;
                        ++curidx;
                        // CURMODE stays as num
                    }
                    else // unexpected character where beginning of number expected
                    {
                        throw new Exception(String.Format("Expected beginning of number at index {0}, instead got {1}",
                                                            curidx,
                                                            eqtn[curidx])
                                            );
                    }
                    break;
                }

                case PARSEMODE.OPER:
                {
                     // ...

我想弄清楚为什么
((1)) 69

正在打印错误
Error: Encountered empty equation at index 2

让我来看看我的逻辑:
首先是curidx = 0eqtn[curidx] = '('CURMODE = PARSEMODE.NUM。那会让我们进入街区
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                          // ...
                    }

在街区的尽头
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }

之后begidx0并且curidx5(右括号后的索引)。因此,++begidx1并且curidx - begidx(在++begidx之后评估)是4因此,打电话后
EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs); }

我们最后回到街区
                    else if ( eqtn[curidx] == Calculator.OPENPAREN ) // beginning of subequation in paranthesis
                    {
                        int begidx = curidx, netparens = 1;
                        while ( ++curidx < offend && netparens != 0 )
                        {
                            if      ( eqtn[curidx] == Calculator.OPENPAREN  )  ++netparens;
                            else if ( eqtn[curidx] == Calculator.CLOSEPAREN )  --netparens;
                        }

在上述begidx = 1curidx = 4之后(索引在右括号之后)。然后++begidx = 2以后curidx - begidx = 2当我们重新进入EvalInner时,我们有eqtn[curidx] = '1',导致我们进入这个区块
                    if ( eqtn[curidx] >= '0' && eqtn[curidx] <= '9' ) // beginning of the int corresponding to the argument index
                    {
                       // ...
                    }

很明显,在这之后,我们用桨划过了1,将它与参数69关联起来,并通过调用堆栈返回到输出。
我哪里做错了?

最佳答案

元组的第二个元素是子方程的长度还是它的上界?

presult = EvalInner(eqtn,new Tuple<int, int>(++begidx, curidx - begidx),eqtnArgs);

简单地使用两个明确的命名参数可能会更有帮助,但是根据您在递归调用之前的使用情况,它看起来好像是上界,但是您传递的是一个长度。
也许这是唯一的问题?不确定。

07-26 06:28