Patrick Hulsmeijer EcmaScript 3文法を使用して、ANTLRでJavaScriptインストルメンターを構築しています。
このコード行の解析に問題があります。
function(){}();
これは、関数式の直接呼び出しです。パーサーはステートメントを関数宣言として認識し、関数本体の後に括弧が見つかると失敗します。その理由は、関数式のあいまいさを避けるために、関数宣言が最も優先して認識されるためです。
これは、文法が関数宣言を認識する方法です。
sourceElement
options
{
k = 1 ;
}
: { input.LA(1) == FUNCTION }? functionDeclaration
| statement
;
それが有効なEcmaScriptステートメントであるかどうかさえわかりません。それは...ですか?
私はそれを書く方が正しいはずだと思います:
(function(){})();
これは実際にはパーサーによって適切に処理されます。
ちなみに、これは質問の核心ではありません。なぜなら、私はインストルメントするコードを制御できないからです。
私はプロダクションから排除functionDeclaration
し、それをプロダクションに入れようとしました:sourceElement
statement
statementTail
statementTail
: variableStatement
| emptyStatement
| expressionStatement
| functionDeclaration
| ifStatement
| ...
;
ただし、ビルドエラーが発生します。
[致命的]ルール
statementTail
には、alts 3,4から到達可能な再帰的なルール呼び出しのため、LL(*)以外の決定があります。左因数分解するか、構文述語を使用するか、backtrack=true
オプションを使用して解決します。
| --->:variableStatement
variableStatement
プロダクションには子孫が含まれているためfunctionExpression
、あいまいさが生じます。パーサーは、それらがほぼ等しいため、中functionDeclaration
から選択することはできません。functionExpression
functionDeclaration
: FUNCTION name=Identifier formalParameterList functionBody
-> ^( FUNCTIONDECL $name formalParameterList functionBody )
;
functionExpression
: FUNCTION name=Identifier? formalParameterList functionBody
-> ^( FUNCTIONEXPR $name? formalParameterList functionBody )
;
注:ASTの歩行中に必要になるため、異なるツリーノード(FUNCTIONDECLとFUNCTIONEXPR)を使用して元の書き換えルールを変更しました。
このあいまいさをどのように解決できますか?