Antlr 基于递归下降的计算器堆栈溢出

Antlr 基于递归下降的计算器堆栈溢出,antlr,recursive-descent,Antlr,Recursive Descent,TL;医生: 我的计算器语法依赖递归下降将括号组嵌套在彼此内部,但嵌套的括号太多(大约20个)会导致堆栈溢出。我怎样才能解决这个问题?有没有办法使问题更简单 长格式: 就在不久前,我的头深深地陷入了小规模的嵌入式系统中,没有半个大脑的人会遇到堆栈溢出。现在,由于一项更抽象的任务,我谦卑地来到这里寻求建议 激励项目是一个Android计算器。当前的计算器在很多方面都明显不足,但我今天没有带我的肥皂盒,所以我将直接讨论我遇到的问题:堆栈溢出 特别是,当用户创建太多嵌套括号组时,包括函数等。这是因为我

TL;医生:

我的计算器语法依赖递归下降将括号组嵌套在彼此内部,但嵌套的括号太多(大约20个)会导致堆栈溢出。我怎样才能解决这个问题?有没有办法使问题更简单

长格式:

就在不久前,我的头深深地陷入了小规模的嵌入式系统中,没有半个大脑的人会遇到堆栈溢出。现在,由于一项更抽象的任务,我谦卑地来到这里寻求建议

激励项目是一个Android计算器。当前的计算器在很多方面都明显不足,但我今天没有带我的肥皂盒,所以我将直接讨论我遇到的问题:堆栈溢出

特别是,当用户创建太多嵌套括号组时,包括函数等。这是因为我的计算器依赖于
ANTLR
语法,这意味着它使用递归下降。这使得它可以方便地通过PEMDA连续运行,从而可以轻松地计算嵌套函数和括号。但是我发现,根据手机的不同,按下parens按钮20次左右会导致崩溃,这是由调用堆栈(大约100个函数调用)导致的堆栈溢出造成的,这是递归下降方法的自然结果

我知道,平面比嵌套好,但它所经历的4个级别(函数)是完全必要的,另外两个级别使我的生活在对数上更容易。即使删除这些级别也不能解决问题:用户仍然能够在几分钟内导致系统崩溃。出现“太多参数!”错误消息是不好的(这是其他计算器会做的事情)。此外,我还使用AST输出格式化输入字符串,使其与rill非常相似,因此预计算parens组会使整个系统有点过于复杂

因此,问题:

即使问这个问题似乎也很愚蠢,但是:有没有一种方法可以在ANTLR中实现一种语法,这种语法可以在不破坏调用堆栈的情况下解析和解释复杂的深层嵌套表达式

语法:

grammar doubleCalc;

options {
    language = Java;
    output = AST;
//  k=2;
}

// Calculation function.
prog returns [double value]
    :   e=addsub EOF {$value = $e.value;}
    ;

addsub returns [double value]
    :   e=muldiv {$value = $e.value;}
        (   PLUS^ e=muldiv {$value += $e.value;}
        |   MINUS^ e=muldiv {$value -= $e.value;}
        )*
    ;

muldiv returns [double value]
    :   e=power {$value = $e.value;} 
        (   MUL^ e=power {$value *= $e.value;}
        |   DIV^ e=power {$value /= $e.value;}
        )*
    ; 

power returns [double value]
    :   e = negate {$value = $e.value;} 
        (   POW^ f=power {$value = java.lang.Math.pow($value, $f.value);}   
        )?
    ; 

negate returns [double value]
    :   (   MINUS^ neg = atom {$value = -$neg.value;}
        |   neg = atom {$value = $neg.value;}
        )
    ;

atom returns [double value]
    :   LOG10^ '(' e=addsub ')' {$value = java.lang.Math.log10($e.value);} 
    |   LOG8^ '(' e=addsub ')' {$value = java.lang.Math.log10($e.value)/java.lang.Math.log10(8.0);} 
    |   LOG2^ '(' e=addsub ')' {$value = java.lang.Math.log10($e.value)/java.lang.Math.log10(2.0);} 
    |   LN^ '(' e=addsub ')' {$value = java.lang.Math.log($e.value);} 
    |   ASIN^ '(' e=addsub ')' {$value = Math.asin(Math.PI*(($e.value/Math.PI) \% 1));}//com.brogramming.HoloCalc.Trig.asin($e.value);} 
    |   ACOS^ '(' e=addsub ')' {$value = Math.acos(Math.PI*(($e.value/Math.PI) \% 1));}
    |   ATAN^ '(' e=addsub ')' {$value = Math.atan(Math.PI*(($e.value/Math.PI) \% 1));}
    |   SIN^ '(' e=addsub ')' {$value = Math.sin(Math.PI*(($e.value/Math.PI) \% 1));} 
    |   COS^ '(' e=addsub ')' {$value = Math.cos(Math.PI*(($e.value/Math.PI) \% 1));} 
    |   TAN^ '(' e=addsub ')' {$value = Math.tan(Math.PI*(($e.value/Math.PI) \% 1));}
    |   ASIND^ '(' e=addsub ')' {$value = Math.asin(Math.PI*(($e.value/180f) \% 1));}//com.brogramming.HoloCalc.Trig.asin($e.value);} 
    |   ACOSD^ '(' e=addsub ')' {$value = Math.acos(Math.PI*(($e.value/180f) \% 1));}
    |   ATAND^ '(' e=addsub ')' {$value = Math.atan(Math.PI*(($e.value/180f) \% 1));}
    |   SIND^ '(' e=addsub ')' {$value = Math.sin(Math.PI*(($e.value/180f) \% 1));} 
    |   COSD^ '(' e=addsub ')' {$value = Math.cos(Math.PI*(($e.value/180f) \% 1));} 
    |   TAND^ '(' e=addsub ')' {$value = Math.tan(Math.PI*(($e.value/180f) \% 1));}
    |   SQRT^ '(' e=addsub ')' {$value = (double) java.lang.Math.pow($e.value, 0.5);} 
    |   CBRT^ '(' e=addsub ')' {$value = (double) java.lang.Math.pow($e.value, 1.0/3.0);} 
    |   ABS^ '(' e=addsub ')' {$value = (double) java.lang.Math.abs($e.value);}
    // Numbers
    |   n = number {$value = $n.value;}
    |   '(' e=addsub ')' {$value = $e.value;}
    ;

number returns [double value]
    :   PI {$value = java.lang.Math.PI;}
    |   EXP {$value = java.lang.Math.E;}
    |   INT {$value = (double) Double.parseDouble($INT.text.replaceAll(",", ""));}
    |   DOUBLE {$value = Double.parseDouble($DOUBLE.text.replaceAll(",", ""));}
    ;

LN  :    'ln';
LOG10   :   'log10';
LOG8    :   'log8';
LOG2    :   'log2';
SIN :   'sin';
COS :   'cos';
TAN :   'tan';
ASIN    :   'asin';
ACOS    :   'acos';
ATAN    :   'atan';
SINH    :   'sinh';
COSH    :   'cosh';
TANH    :   'tanh';
ASINH   :   'asinh';
ACOSH   :   'acosh';
ATANH   :   'atanh';
SIND    :   'sind';
COSD    :   'cosd';
TAND    :   'tand';
ASIND   :   'asind';
ACOSD   :   'acosd';
ATAND   :   'atand';
SINHD   :   'sinhd';
COSHD   :   'coshd';
TANHD   :   'tanhd';
ASINHD  :   'asinhd';
ACOSHD  :   'acoshd';
ATANHD  :   'atanhd';
PI  :   'pi';
IM  :   'i';
EXP :   'e';
ABS :   'abs';
FACT    :   'fact';
SQRE    :   'sqre';
CUBE    :   'cube';
SQRT    :   'sqrt';
CBRT    :   'cbrt';
POW : '^';
PLUS : '+';
MINUS : '-';
MUL : ('*');
DIV : '/';
BANG    :   '!';
DOUBLE: ('0'..'9' | ',')+ '.'('0'..'9')* ;
INT :   ('0'..'9' | ',')+ ;
NEWLINE:'\r'? '\n' ;
PERCENT
    :   '%';
EOF :   '<EOF>' {$channel=HIDDEN;};
语法双计算器;
选择权{
语言=Java;
输出=AST;
//k=2;
}
//计算功能。
程序返回[双值]
:e=addsub EOF{$value=$e.value;}
;
addsub返回[双值]
:e=muldiv{$value=$e.value;}
(加^e=muldiv{$value+=e.value;}
|减^e=muldiv{$value-=$e.value;}
)*
;
muldiv返回[双值]
:e=power{$value=$e.value;}
(MUL^e=power{$value*=$e.value;}
|DIV^e=power{$value/=$e.value;}
)*
; 
电源返回[双值]
:e=否定{$value=$e.value;}
(POW^f=power{$value=java.lang.Math.POW($value,$f.value);}
)?
; 
否定返回[双值]
:(减^neg=atom{$value=-$neg.value;}
|neg=atom{$value=$neg.value;}
)
;
atom返回[双值]
:LOG10^'('e=addsub'){$value=java.lang.Math.LOG10($e.value);}
|LOG8^'('e=addsub'){$value=java.lang.Math.log10($e.value)/java.lang.Math.log10(8.0);}
|LOG2^'('e=addsub'){$value=java.lang.Math.log10($e.value)/java.lang.Math.log10(2.0);}
|LN^'('e=addsub'){$value=java.lang.Math.log($e.value);}
|ASIN^'('e=addsub'){$value=Math.ASIN(Math.PI*($e.value/Math.PI)\%1));}//com.brogramming.HoloCalc.Trig.ASIN($e.value);}
|ACOS^'('e=addsub'){$value=Math.ACOS(Math.PI*($e.value/Math.PI)\%1));}
|ATAN^'('e=addsub'){$value=Math.ATAN(Math.PI*($e.value/Math.PI)\%1));}
|SIN^'('e=addsub'){$value=Math.SIN(Math.PI*($e.value/Math.PI)\%1));}
|COS^'('e=addsub')”{$value=Math.COS(Math.PI*($e.value/Math.PI)\%1));}
|TAN^'('e=addsub'){$value=Math.TAN(Math.PI*($e.value/Math.PI)\%1));}
|ASIND^'('e=addsub'){$value=Math.asin(Math.PI*($e.value/180f)\%1));}//com.brogramming.HoloCalc.Trig.asin($e.value);}
|ACOSD^'('e=addsub'){$value=Math.acos(Math.PI*($e.value/180f)\%1));}
|ATAND ^'('e=addsub'){$value=Math.atan(Math.PI*($e.value/180f)\%1));}
|SIND^'('e=addsub'){$value=Math.sin(Math.PI*($e.value/180f)\%1));}
|COSD^'('e=addsub')”{$value=Math.cos(Math.PI*($e.value/180f)\%1));}
|TAND^'('e=addsub'){$value=Math.tan(Math.PI*($e.value/180f)\%1));}
|SQRT^'('e=addsub'){$value=(double)java.lang.Math.pow($e.value,0.5);}
|CBRT^'('e=addsub'){$value=(double)java.lang.Math.pow($e.value,1.0/3.0);}
|ABS^'('e=addsub'){$value=(double)java.lang.Math.ABS($e.value);}
//数字
|n=数字{$value=$n.value;}
|“('e=addsub')”{$value=$e.value;}
;
数字返回[双值]
:PI{$value=java.lang.Math.PI;}
|EXP{$value=java.lang.Math.E;}
|INT{$value=(double)double.parseDouble($INT.text.replaceAll(“,”,“);}
|DOUBLE{$value=DOUBLE.parseDouble($DOUBLE.text.replaceAll(“,”,“);}
;
LN:‘LN’;
LOG10:‘LOG10’;
LOG8:‘LOG8’;
LOG2:‘LOG2’;
罪:“罪”;
COS:‘COS’;
谭:"谭",;
阿辛:‘阿辛’;
ACOS:“ACOS”;
阿坦:“阿坦”;
信:信;
COSH:‘COSH’;
谭:‘谭’;
阿辛:‘阿辛’;
阿科什:“阿科什”;
阿塔恩:“阿塔恩”;
辛德:“辛德”;
COSD:‘COSD’;
坦德:“坦德”;
阿辛德:“阿辛德”;
ACOSD:‘ACOSD’;
阿坦德:“阿坦德”;
SINHD:‘SINHD’;
COSHD:‘COSHD’;
TANHD:‘TANHD’;
阿辛德:“阿辛德”;
ACOSHD:‘ACOSHD’;
阿坦德:“阿坦德”;
PI:‘PI’;
IM:‘我’;
EXP:'e';
ABS:‘ABS’;
事实:“事实”;
SQRE:“SQRE”;
立方体:“立方体”;
SQRT:‘SQRT’;
CBRT:‘CBRT’;
战俘:“^”;