正しくない点がいくつかあります。
1
WS
トークンをチャネルに配置HIDDEN
したため、パーサー ルールで使用できなくなります。したがって、ルールWS
内のすべてのトークンが正しくありません。body
2
_(最新の編集により左再帰の問題が削除されましたが、申し訳ありませんが、他の質問には左再帰ルール ( expr
) があるため、この情報をここに残しておきます)_
ANTLR はLL パーサージェネレーターであるため、左再帰文法を作成できます。以下は再帰のままです。
expr
: term term operator
;
term
: INT
| ID
| expr
;
term
ルール内の最初のものは、ルール自体expr
に一致する可能性があるためです。expr
他の LL パーサーと同様に、ANTLR で生成されたパーサーは左再帰に対応できません。
3
WS
問題を修正すると、body
ルールによって次のエラー メッセージが生成されます。
(1/7) 複数の選択肢を使用して、「INT」などの入力を決定に一致させることができます
これは、パーサーがINT
トークンがどのルールに属しているかを「見る」ことができないことを意味します。これは、すべてのbody
選択肢が 0 回以上繰り返される可能性があり、expr
andnested
も繰り返されるという事実によるものです。そして、それらはすべて に一致する可能性がありINT
、これは ANTLR が不満を言っていることです。を削除すると、次*
のようになります。
body
: nested
| var
| get
;
// ...
expr
: term (term operator)
;
nested
: expr (expr operator)
;
エラーは消えます (ただし、それでも入力が適切に解析されるわけではありません!)。
これはまだ曖昧に聞こえるかもしれませんが、説明するのは簡単ではありません (または、これらすべてに慣れていない場合は理解できます)。
4
expr
内部の再帰を適切に説明するには、 #2expr
で説明したように、左再帰を避ける必要があります。次のようにできます。
expr
: term (expr operator | term operator)*
;
これはまだあいまいですが、それは LL 文法を使用して後置式を記述する場合であり、AFAIK では避けられません。これを解決するにoptions { ... }
は、文法のセクション内でグローバル バックトラッキングを有効にします。
options {
language=Python;
output=AST;
backtrack=true;
}
デモ
再帰式を解析する方法の小さなデモは次のようになります。
grammar star;
options {
language=Python;
output=AST;
backtrack=true;
}
parse
: expr EOF -> expr
;
expr
: (term -> term) ( expr2 operator -> ^(operator $expr expr2)
| term operator -> ^(operator term term)
)*
;
expr2
: expr
;
term
: INT
| ID
;
operator
: ('*' | '+' | '/' | '%' | '-')
;
ID
: ('a'..'z' | 'A'..'Z') ('a..z' | '0'..'9' | 'A'..'Z')*
;
INT
: '0'..'9'+
;
WS
: (' ' | '\n' | '\t' | '\r') {$channel=HIDDEN;}
;
テスト スクリプト:
#!/usr/bin/env python
import antlr3
from antlr3 import *
from antlr3.tree import *
from starLexer import *
from starParser import *
def print_level_order(tree, indent):
print '{0}{1}'.format(' '*indent, tree.text)
for child in tree.getChildren():
print_level_order(child, indent+1)
input = "5 1 2 + 4 * + 3 -"
char_stream = antlr3.ANTLRStringStream(input)
lexer = starLexer(char_stream)
tokens = antlr3.CommonTokenStream(lexer)
parser = starParser(tokens)
tree = parser.parse().tree
print_level_order(tree, 0)
次の出力が生成されます。
-
+
5
*
+
1
2
4
3
これは、次の AST に対応します。
