我試圖執行一個程序,就像我的算法中評估基本括號表達的缺陷在哪裏?
輸入:
~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 = 0
,eqtn[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;
}
之後begidx
是0
和curidx
的部分的端部是5
(索引一個右括號之後)。因此,++begidx
是1
和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 = 1
和curidx = 4
(索引一個右括號後)。然後++begidx = 2
和今後curidx - begidx = 2
,當我們再次進入EvalInner
我們EQT n[curidx] = '1'
,使我們進入塊
if (eqtn[curidx] >= '0' && eqtn[curidx] <= '9') // beginning of the int corresponding to the argument index
{
// ...
}
之後,很顯然,我們已經oarsed的1
,用參數69
相關的它,並通過通過調用堆棧返回到輸出。
我在哪裏出錯了?
我不清楚你的問題開始處的輸入是怎樣變成輸出的。 –
@TimBiegeleisen命令行輸入。 'eqtnArgs'是方程'eqtn'中索引到他們解析值的映射,在第一次調用'EvalInner'之前已經被解析。在我所示的例子中,'eqtnArgs'只包含'eqtnArgs [1] = 69'。 –
一般而言,您需要使用Antlr,堆棧或遞歸方法來解析包含閉包(括號)或任意深度的表達式。 –