Java 扩展简单ANTLR语法以支持输入变量

Java 扩展简单ANTLR语法以支持输入变量,java,antlr,antlr3,Java,Antlr,Antlr3,我还在继续,现在我知道没有了。所以我自己用ANTLR3写了一个 我发现了一个非常好的例子: Exp.g: grammar Exp; eval returns [double value] : exp=additionExp {$value = $exp.value;} ; additionExp returns [double value] : m1=multiplyExp {$value = $m1.value;} (

我还在继续,现在我知道没有了。所以我自己用ANTLR3写了一个

我发现了一个非常好的例子:

Exp.g:

grammar Exp;

eval returns [double value]
    :    exp=additionExp {$value = $exp.value;}
    ;

additionExp returns [double value]
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

multiplyExp returns [double value]
    :    a1=atomExp       {$value =  $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;} 
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;
public Double evaluate(String string, Map<String, Double> input) throws RecognitionException {
    ANTLRStringStream in = new ANTLRStringStream(string);
    ExpLexer lexer = new ExpLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    return new ExpParser(tokens).eval();
}
Java代码:

grammar Exp;

eval returns [double value]
    :    exp=additionExp {$value = $exp.value;}
    ;

additionExp returns [double value]
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

multiplyExp returns [double value]
    :    a1=atomExp       {$value =  $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;} 
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;
public Double evaluate(String string, Map<String, Double> input) throws RecognitionException {
    ANTLRStringStream in = new ANTLRStringStream(string);
    ExpLexer lexer = new ExpLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    return new ExpParser(tokens).eval();
}
结果得到13分

现在,我的用例缺少的唯一一件事就是向其中注入简单的双变量,这样我就可以通过提供{“a”:12.0,“B”:14.0}作为输入映射来评估以下内容:

(A+B)/2

有什么想法吗?

您可以在解析器中创建
映射内存
,并在语法中引入
标识符

Identifier
  :  ('a'..'z' | 'A'..'Z' | '_') ('a'..'z' | 'A'..'Z' | '_' | '0'..'9')*
  ;
然后,您的
atomExp
解析器规则如下所示:

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    i=Identifier            {$value = memory.get($i.text);} // <- added!
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

祝你好运

呸,我花了时间来实现这一点,所以不妨发布它,尽管我被打败了:)

在下面的语法中,我实现了您希望执行的变量赋值格式

grammar Exp;



eval returns [double value]
scope
{
    java.util.Hashtable varMap; 
}
@init
{
    $eval::varMap = new java.util.Hashtable();
}
:    exp=additionExp {$value = $exp.value;}
    | varList
;

additionExp returns [double value]
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

multiplyExp returns [double value]
    :    a1=atomExp       {$value =  $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;} 
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    v=ID            {$value = $eval::varMap.get($v);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

varList
    :   
    OPEN_BRACE assignVar (COMMA assignVar)+ CLOSE_BRACE
    ;

assignVar
    :QUOTE var=ID n=Number QUOTE COLON { $eval::varMap.put($var, $n); }
    ;


Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;



fragment LETTER: LOWER | UPPER;
fragment LOWER: 'a'..'z';
fragment UPPER: 'A'..'Z';

OPEN_BRACE
    :   '{'
    ;

CLOSE_BRACE
    :   '}'
    ;

COLON   : ';';
COMMA   :   ',';

QUOTE   :   '"';

ID
: LETTER*;

很抱歉,达里安:)。嗯,我首先写了arturh张贴的语法,所以我有点领先+然而,我还是拒绝了!不用担心,这是促成这样做的一部分风险:)
6.283185307179586
grammar Exp;



eval returns [double value]
scope
{
    java.util.Hashtable varMap; 
}
@init
{
    $eval::varMap = new java.util.Hashtable();
}
:    exp=additionExp {$value = $exp.value;}
    | varList
;

additionExp returns [double value]
    :    m1=multiplyExp       {$value =  $m1.value;} 
         ( '+' m2=multiplyExp {$value += $m2.value;} 
         | '-' m2=multiplyExp {$value -= $m2.value;}
         )* 
    ;

multiplyExp returns [double value]
    :    a1=atomExp       {$value =  $a1.value;}
         ( '*' a2=atomExp {$value *= $a2.value;} 
         | '/' a2=atomExp {$value /= $a2.value;}
         )* 
    ;

atomExp returns [double value]
    :    n=Number                {$value = Double.parseDouble($n.text);}
    |    v=ID            {$value = $eval::varMap.get($v);}
    |    '(' exp=additionExp ')' {$value = $exp.value;}
    ;

varList
    :   
    OPEN_BRACE assignVar (COMMA assignVar)+ CLOSE_BRACE
    ;

assignVar
    :QUOTE var=ID n=Number QUOTE COLON { $eval::varMap.put($var, $n); }
    ;


Number
    :    ('0'..'9')+ ('.' ('0'..'9')+)?
    ;

WS  
    :   (' ' | '\t' | '\r'| '\n') {$channel=HIDDEN;}
    ;



fragment LETTER: LOWER | UPPER;
fragment LOWER: 'a'..'z';
fragment UPPER: 'A'..'Z';

OPEN_BRACE
    :   '{'
    ;

CLOSE_BRACE
    :   '}'
    ;

COLON   : ';';
COMMA   :   ',';

QUOTE   :   '"';

ID
: LETTER*;