1

ANTLR 3.4でPHP5パーサーを作成しました。これはほぼ準備ができていますが、PHPのトリッキーな機能の1つを処理できません。私の問題は、代入演算子の優先順位にあります。PHPのマニュアルにあるように、割り当ての優先順位はリストのほぼ最後にありますand、、およびのみがリストの後ろxorにあります。or,

しかし、このマニュアルページには次のような注記があります。

他のほとんど=の演算子よりも優先順位は低くなりますが、PHPでは次のような式を使用できます。if (!$a = foo())この場合、の戻り値foo()はになり$aます。

メモの小さな例は私のパーサーにとって問題ではありません。これは、割り当てルールの特殊なケースとして処理できます。

しかし、もっと複雑なコードがあります。例:

if ($a && $b = func()) {}

私のパーサーはここで失敗します。これは、パーサーが最初に認識$a && $bし、残りの条件を処理できないためです。これは、&&がよりも優先順位が高いためです=。の右側に角かっこを入れた場合&&

if ($a && ($b = func())) {}

このようにして、パーサーは構造をよく認識します。

演算子は、ANTLRブックが推奨する方法で構築されています。最初のステップで基本的な表現があり、演算子の各レベルが次々に来ています。

この優先順位のジャンプを処理する方法はありますか?

4

1 に答える 1

0

代入として見るのではなく、代入式という名前を付けましょう。この代入式を単項式の「下」に配置します(単項式よりも優先順位が高くなります)。

grammar T;

options {
  output=AST;
}

tokens {
  BLOCK;
  FUNC_CALL;
  EXPR_LIST;
}

parse
 : stat* EOF!
 ;

stat
 : assignment ';'!
 | if_stat
 ;

assignment
 : Var '='^ expr
 ;

if_stat
 : If '(' expr ')' block -> ^(If expr block)
 ;

block
 : '{' stat* '}' -> ^(BLOCK stat*)
 ;

expr
 : or_expr
 ;

or_expr
 : and_expr ('||'^ and_expr)*
 ;

and_expr
 : unary_expr ('&&'^ unary_expr)*
 ;

unary_expr
 : '!'^ assign_expr
 | '-'^ assign_expr
 | assign_expr
 ;

assign_expr
 : Var ('='^ atom)*
 | atom
 ;

atom
 : Num
 | func_call
 ;

func_call
 : Id '(' expr_list ')' -> ^(FUNC_CALL Id expr_list)
 ;

expr_list
 : (expr (',' expr)*)? -> ^(EXPR_LIST expr*)
 ;

If    : 'if';
Num   : '0'..'9'+;
Var   : '$' Id;
Id    : ('a'..'z')+;
Space : (' ' | '\t' | '\r' | '\n')+ {skip();};

ソースを解析する場合:

if (!$a = foo()) { $a = 1 && 2; }
if ($a && $b = func()) { $b = 2 && 3; }
if ($a = baz() && $b) { $c = 3 && 4; }

次のASTが構築されます。

ここに画像の説明を入力してください

于 2012-06-28T14:19:22.317 に答える