2012-03-22 8 views
2

数学表現を解析するためのANTLR文法と、それらを評価するためのもう1つの文法を作成しました。私がASTを構築し、実際にそれを評価するために再解析することがあまりにも多すぎる場合、私は文法をリファクタリングして、その用語を表現する「Term」オブジェクトの階層を生成したいと考えました操作。ルートTermオブジェクトは、単純に具体的な結果に評価することができます。文法を処理するときにAntlrが無限ループになるのはなぜですか?

私はかなりの文法を書き直さなければならず、最後に最後のエラーメッセージを取り除く必要がありました。残念ながら、ANTLRは無限ループに陥っているようです。

ここで誰かが問題を解決するのに手伝ってもらえますか?文法はかなり面白いはずだと思うので、投稿しています。 (それは私がgoogleで見つけたgarmmarに基づいている、私は認めなければならないが、私はそれを私の必要性のスイートにかなり変えた)。

grammar SecurityRulesNew; 

options { 
language = Java; 
    output=AST; 
    backtrack = true; 
    ASTLabelType=CommonTree; 
    k=2; 
} 

tokens { 
    POS; 
    NEG; 
    CALL; 
} 

@header {package de.cware.cweb.services.evaluator.parser;} 
@lexer::header{package de.cware.cweb.services.evaluator.parser;} 

formula returns [Term term] 
: a=expression EOF { $term = a; } 
; 
expression returns [Term term] 
: a=boolExpr { $term = a; } 
; 
boolExpr returns [Term term] 
: a=sumExpr { $term = a; } 
| a=sumExpr AND b=boolExpr { $term = new AndTerm(a, b); } 
| a=sumExpr OR b=boolExpr { $term = new OrTerm(a, b); } 
| a=sumExpr LT b=boolExpr { $term = new LessThanTerm(a, b); } 
| a=sumExpr LTEQ b=boolExpr { $term = new LessThanOrEqualTerm(a, b); } 
| a=sumExpr GT b=boolExpr { $term = new GreaterThanTerm(a, b); } 
| a=sumExpr GTEQ b=boolExpr { $term = new GreaterThanTermOrEqual(a, b); } 
| a=sumExpr EQ b=boolExpr { $term = new EqualsTerm(a, b); } 
| a=sumExpr NOTEQ b=boolExpr { $term = new NotEqualsTerm(a, b); } 
; 
sumExpr returns [Term term] 
: a=productExpr { $term = a; } 
| a=productExpr SUB b=sumExpr { $term = new SubTerm(a, b); } 
| a=productExpr ADD b=sumExpr { $term = new AddTerm(a, b); } 
; 
productExpr returns [Term term] 
: a=expExpr { $term = a; } 
| a=expExpr DIV productExpr { $term = new DivTerm(a, b); } 
| a=expExpr MULT productExpr { $term = new MultTerm(a, b); } 
; 
expExpr returns [Term term] 
: a=unaryOperation { $term = a; } 
| a=unaryOperation EXP expExpr { $term = new ExpTerm(a, b); } 
; 
unaryOperation returns [Term term] 
: a=operand { $term = a; } 
| NOT a=operand { $term = new NotTerm(a); } 
| SUB a=operand { $term = new NegateTerm(a); } 
; 
operand returns [Term term] 
: l=literal { $term = l; } 
| f=functionExpr { $term = f; } 
| v=VARIABLE { $term = new VariableTerm(v); } 
| LPAREN e=expression RPAREN { $term = e; } 
; 
functionExpr returns [Term term] 
: f=FUNCNAME LPAREN! RPAREN! { $term = new CallFunctionTerm(f, null); } 
| f=FUNCNAME LPAREN! a=arguments RPAREN! { $term = new CallFunctionTerm(f, a); } 
; 
arguments returns [List<Term> terms] 
: a=expression 
    { 
     $terms = new ArrayList<Term>(); 
     $terms.add(a); 
    } 
| a=expression COMMA b=arguments 
    { 
     $terms = new ArrayList<Term>(); 
     $terms.add(a); 
     $terms.addAll(b); 
    } 
; 
literal returns [Term term] 
: n=NUMBER { $term = new NumberLiteral(n); } 
| s=STRING { $term = new StringLiteral(s); } 
| t=TRUE { $term = new TrueLiteral(t); } 
| f=FALSE { $term = new FalseLiteral(f); } 
; 

STRING 
: 
'\"' 
    (options {greedy=false;} 
    : ESCAPE_SEQUENCE 
    | ~'\\' 
    )* 
'\"' 
| 
'\'' 
    (options {greedy=false;} 
    : ESCAPE_SEQUENCE 
    | ~'\\' 
    )* 
'\'' 
; 
WHITESPACE 
: (' ' | '\n' | '\t' | '\r')+ {skip();}; 
TRUE 
: ('t'|'T')('r'|'R')('u'|'U')('e'|'E') 
; 
FALSE 
: ('f'|'F')('a'|'A')('l'|'L')('s'|'S')('e'|'E') 
; 

NOTEQ   : '!='; 
LTEQ   : '<='; 
GTEQ   : '>='; 
AND    : '&&'; 
OR    : '||'; 
NOT    : '!'; 
EQ    : '='; 
LT    : '<'; 
GT    : '>'; 

EXP    : '^'; 
MULT   : '*'; 
DIV    : '/'; 
ADD    : '+'; 
SUB    : '-'; 

LPAREN   : '('; 
RPAREN   : ')'; 
COMMA   : ','; 
PERCENT   : '%'; 

VARIABLE 
: '[' ~('[' | ']')+ ']' 
; 
FUNCNAME 
: (LETTER)+ 
; 
NUMBER 
: (DIGIT)+ ('.' (DIGIT)+)? 
; 

fragment 
LETTER 
: ('a'..'z') | ('A'..'Z') 
; 
fragment 
DIGIT 
: ('0'..'9') 
; 
fragment 
ESCAPE_SEQUENCE 
: '\\' 't' 
| '\\' 'n' 
| '\\' '\"' 
| '\\' '\'' 
| '\\' '\\' 
; 

お願いします。

クリス

+0

あなたがすべてでそれをデバッグしようとしたことがあり:-)右のトラックに私を得た...あなたの説明のために再度:ここでは、現在のバージョンが来ますか? –

+0

グローバルバックトラックを有効にして定数kを定義しているのはなぜですか? –

+0

ええと...私は古いバージョンがあったので、kパラメータに帽子をかける。私はそのような複雑な(少なくとも私のための)文法にはかなり新しいことを認めなければならない。私は残した、何が害を及ぼさなかったか:-) –

答えて

1

あなたの文法は信じられないほど曖昧なので、ANTLRは、パーサを作成する問題があります。どうやら3.3+がそれにチョークANTLRが、(3.3+より少ない時間で)ANTLR 3.2は、次のエラー生成:単純な式パーサについて

error(10): internal error: org.antlr.tool.Grammar.createLookaheadDFA(Grammar.java:1279): could not even do k=1 for decision 1; reason: timed out (>1000ms)

を、あなたは本当にbacktrack=trueを使用しないでください。

文法があいまいであることに加えて、多くの埋め込みコードにはエラーがあります。

はのは、あなたのformulaルールを見てみましょう:

formula returns [Term term] 
: a=expression EOF { $term = $a; } 
; 

また、ルールの戻り値の型を明示的に定義する必要があります。 { $term = a; }aは、その前に$を持っている必要があります。

formula returns [Term term] 
: a=expression EOF { $term = $a; } 
; 

が、その後$aが全体の「もの」expressionリターンを指します。あなたはそれからTermこのexpressionを作成したいANTLRを "伝える"必要があります。これは次のように行うことができます。

formula returns [Term term] 
: a=expression EOF { $term = $a.term; } 
; 
expression returns [Term term] 
: a=boolExpr { $term = $a.term; } 
; 

それはあなたがANTLR文法(ANTLRはLRで終わるものの、ANTLR 3.xのはLLパーサジェネレータであることに注意してください)に、いくつかのLR文法を変換しているように見えるとテストなしその間に、あなたはすべてがうまくいくことを期待していました。残念ながら、そうではありません。あなたの文法に基づいて小さな実例を作るにはあまりにも間違っている:私はANTLR文法に基づいて既存の表現パーサーを見て、もう一度やり直すだろう。 & AのこれらのQを見てください:

+0

ええと...私はすでにすべて自分自身の一部を見つけた。 "$ a.term"とそれに類するものはすべて並べ替えられ、実際にコンパイルされたコードが生成されます。私は単純に多くのオプションをコメントアウトし、ビルドを破るように見える1つの断片に繋がるまで生成することに専念しました。そのバックトラック機能をオンにしました。何らかのエラーが発生したため、私はそれをオンにすることを提案しました。私は単純に更新された文法を投稿します。本当に有効なimportang言語機能は除外されます:( –

0

まず、その詳細な説明をありがとうございました。これは実際に役立ちます:-) ... "$ a.term"とそれに類するものはすべて今すぐ整理され、実際にコンパイルされたコードが生成されます(私は単にコードを解読して、全く生成されない)。私はビルドを破るように見える一つの断片に来るまで、多くのオプションをコメントし、生成に関心を持っています。そのバックトラック機能をオンにしました。何らかのエラーが発生したため、私はそれをオンにすることを提案しました。

EDIT: まあ、私が実際にバックトラックを起動することなく、エラーを取り除くために文法をリファクタリングして、今の私のパーサが本当に速く生成され、うまく仕事ですやっているようです。

grammar SecurityRulesNew; 

options { 
language = Java; 
    output=AST; 
ASTLabelType=CommonTree; 
/* backtrack = true;*/ 
} 

tokens { 
POS; 
NEG; 
CALL; 
} 

@header {package de.cware.cweb.services.evaluator.parser; 

import de.cware.cweb.services.evaluator.terms.*;} 
@lexer::header{package de.cware.cweb.services.evaluator.parser;} 

formula returns [Term term] 
: a=expression EOF { $term = $a.term; } 
; 
expression returns [Term term] 
: a=boolExpr { $term = $a.term; } 
; 
boolExpr returns [Term term] 
: a=sumExpr (AND! b=boolExpr | OR! c=boolExpr | LT! d=boolExpr | LTEQ! e=boolExpr | GT! f=boolExpr | GTEQ! g=boolExpr | EQ! h=boolExpr | NOTEQ! i=boolExpr)? { 
     if(b != null) { 
      $term = new AndTerm($a.term, $b.term); 
     } else if(c != null) { 
      $term = new OrTerm($a.term, $c.term); 
     } else if(d != null) { 
      $term = new LessThanTerm($a.term, $d.term); 
     } else if(e != null) { 
      $term = new LessThanOrEqualTerm($a.term, $e.term); 
     } else if(f != null) { 
      $term = new GreaterThanTerm($a.term, $f.term); 
     } else if(g != null) { 
      $term = new GreaterThanOrEqualTerm($a.term, $g.term); 
     } else if(h != null) { 
      $term = new EqualsTerm($a.term, $h.term); 
     } else if(i != null) { 
      $term = new NotEqualsTerm($a.term, $i.term); 
     } else { 
      $term = $a.term; 
     } 
    } 
; 
sumExpr returns [Term term] 
: a=productExpr (SUB! b=sumExpr | ADD! c=sumExpr)? 
    { 
     if(b != null) { 
      $term = new SubTerm($a.term, $b.term); 
     } else if(c != null) { 
      $term = new AddTerm($a.term, $c.term); 
     } else { 
      $term = $a.term; 
     } 
    } 
; 
productExpr returns [Term term] 
: a=expExpr (DIV! b=productExpr | MULT! c=productExpr)? 
    { 
     if(b != null) { 
      $term = new DivTerm($a.term, $b.term); 
     } else if(c != null) { 
      $term = new MultTerm($a.term, $c.term); 
     } else { 
      $term = $a.term; 
     } 
    } 
; 
expExpr returns [Term term] 
: a=unaryOperation (EXP! b=expExpr)? 
    { 
     if(b != null) { 
      $term = new ExpTerm($a.term, $b.term); 
     } else { 
      $term = $a.term; 
     } 
    } 
; 
unaryOperation returns [Term term] 
: a=operand { $term = $a.term; } 
| NOT! a=operand { $term = new NotTerm($a.term); } 
| SUB! a=operand { $term = new NegateTerm($a.term); } 
| LPAREN! e=expression RPAREN! { $term = $e.term; } 
; 
operand returns [Term term] 
: l=literal { $term = $l.term; } 
| v=VARIABLE { $term = new VariableTerm($v.text); } 
| f=functionExpr { $term = $f.term; } 
; 
functionExpr returns [Term term] 
: f=FUNCNAME LPAREN! (a=arguments)? RPAREN! { $term = new CallFunctionTerm($f.text, $a.terms); } 
; 
arguments returns [List<Term> terms] 
: a=expression (COMMA b=arguments)? 
    { 
     $terms = new ArrayList<Term>(); 
     $terms.add($a.term); 
     if(b != null) { 
      $terms.addAll($b.terms); 
     } 
    } 
; 
literal returns [Term term] 
: n=NUMBER { $term = new NumberLiteral(Double.valueOf($n.text)); } 
| s=STRING { $term = new StringLiteral($s.text.substring(1, s.getText().length() - 1)); } 
| TRUE! { $term = new TrueLiteral(); } 
| FALSE! { $term = new FalseLiteral(); } 
; 

STRING 
: 
'\"' 
    (options {greedy=false;} 
    : ESCAPE_SEQUENCE 
    | ~'\\' 
    )* 
'\"' 
| 
'\'' 
    (options {greedy=false;} 
    : ESCAPE_SEQUENCE 
    | ~'\\' 
    )* 
'\'' 
; 
WHITESPACE 
: (' ' | '\n' | '\t' | '\r')+ {skip();}; 
TRUE 
: ('t'|'T')('r'|'R')('u'|'U')('e'|'E') 
; 
FALSE 
: ('f'|'F')('a'|'A')('l'|'L')('s'|'S')('e'|'E') 
; 

NOTEQ : '!='; 
LTEQ : '<='; 
GTEQ : '>='; 
AND  : '&&'; 
OR  : '||'; 
NOT  : '!'; 
EQ  : '='; 
LT  : '<'; 
GT  : '>'; 

EXP  : '^'; 
MULT : '*'; 
DIV  : '/'; 
ADD  : '+'; 
SUB  : '-'; 

LPAREN : '('; 
RPAREN : ')'; 
COMMA : ','; 
PERCENT : '%'; 

VARIABLE 
: '[' ~('[' | ']')+ ']' 
; 
FUNCNAME 
: (LETTER)+ 
; 
NUMBER 
: (DIGIT)+ ('.' (DIGIT)+)? 
; 

fragment 
LETTER 
: ('a'..'z') | ('A'..'Z') 
; 
fragment 
DIGIT 
: ('0'..'9') 
; 
fragment 
ESCAPE_SEQUENCE 
: '\\' 't' 
| '\\' 'n' 
| '\\' '\"' 
| '\\' '\'' 
| '\\' '\\' 
; 

おかげで、それは

クリス

関連する問題