2

postfix、infix、および prefix ルールを EBNF 形式の scala から ANTLR に変換しようとしていますが、infixExpression ルールの左再帰に関連するエラーが表示されます。

問題のルールは次のとおりです。

public symbolOrID
:   ID
|   Symbol
;

public postfixExpression
:   infixExpression symbolOrID? -> ^(R__PostfixExpression infixExpression symbolOrID?)
;

public infixExpression
:   prefixExpression
|   infixExpression (symbolOrID infixExpression)? -> ^(R__InfixExpression infixExpression symbolOrID? infixExpression?)
;

public prefixExpression
:   prefixCharacter? simpleExpression -> ^(R__PrefixExpression prefixCharacter? simpleExpression)
;

public prefixCharacter
:   '-' | '+' | '~' | '!' | '#'
;

public simpleExpression
:   constant
;

infixExpression ルールを次のように変更すると:

public infixExpression
:   prefixExpression (symbolOrID infixExpression)? -> ^(R__InfixExpression prefixExpression symbolOrID? infixExpression?)
;

次に、代わりに不平を言います:

warning(200): Hydra.g3:108:26: Decision can match input such as "{ID, Symbol} {'!'..'#', '+', '-', '~'} String" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
warning(200): Hydra.g3:108:26: Decision can match input such as "{ID, Symbol} {'!'..'#', '+', '-', '~'} Number" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
warning(200): Hydra.g3:108:26: Decision can match input such as "{ID, Symbol} {'!'..'#', '+', '-', '~'} Boolean" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
warning(200): Hydra.g3:108:26: Decision can match input such as "{ID, Symbol} {'!'..'#', '+', '-', '~'} Regex" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input
warning(200): Hydra.g3:108:26: Decision can match input such as "{ID, Symbol} {'!'..'#', '+', '-', '~'} Null" using multiple alternatives: 1, 2
As a result, alternative(s) 2 were disabled for that input

最後に、条件付きで AST にノードを作成して、ルールの左側の部分だけが true の場合にそのレベルを追加しないようにする方法はありますか? 例えば:

conditional_or_expression:
    conditional_and_expression  ('||' conditional_or_expression)?
;

のように、次のような階層に従う文法を作成するとしましょう。

conditional_and_expression
  conditional_or_expression
    null_coalescing_expression

解析される式が である場合a || b、現在作成される AST はこの式に対して

conditional_and_expression
  conditional_or_expression

部品だけを取得するにはどうすればよいconditional_or_expressionですか?

JavaCC では、次のようにノード アリティを設定できます。#ConditionalOrExpression(>1)

編集: 昨夜は少し遅くなりましたが、中置式が適切に変更されました!

最終編集:最終的に機能させる方法は、次のルールでした。

public symbolOrID
:   ID
|   Symbol
;

public postfixExpression
:   infixExpression (symbolOrID^)?
;

public infixExpression
:   (prefixExpression symbolOrID)=> prefixExpression symbolOrID^ infixExpression
|   prefixExpression
;

public prefixExpression
:   prefixCharacter^ simpleExpression
|   simpleExpression
;

public prefixCharacter
:   '-' | '+' | '~' | '!' | '#'
;

public simpleExpression
:   constant
;
4

2 に答える 2

1

ダークザエルスは次のように書いています。

postfix、infix、prefix ルールを EBNF 形式の scala から ANTLR に変換しようとしていますが、左再帰に関連するエラーが表示されます

コメントで言ったように、投稿したルールには左再帰はありません。

ダークザエルスは次のように書いています。

conditional_or_expression 部分だけを取得するにはどうすればよいですか?

ANTLRWorks のインタープリターまたはデバッガーを使用していると仮定しています。この場合、ツリーは次のようになります。

conditional_and_expression
            \
  conditional_or_expression

そのように表示されているだけです(ASTではなく解析ツリーが表示されます)。orExpressionyourを AST に適切に変換すると、式a || bは次のようになります。

  ||
 /  \
a    b

(つまり||、ルートおよびabノードとして)

たとえば、次の文法を取ります。

grammar T;

options {
  output=AST;
}

parse
  :  expr EOF -> expr
  ;

expr
  :  or_expr
  ;

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

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

add_expr
  :  atom (('+' | '-')^ atom)*
  ;

atom
  :  NUMBER
  |  '(' expr ')' -> expr
  ;

NUMBER : '0'..'9'+;

上記の文法から生成されたパーサーで解析する12+34と、ANTLRWorks (または Eclipse ANTLR IDE) は次の解析ツリーを表示します。

ここに画像の説明を入力

しかし、これはパーサーが作成する AST ではありません。AST は実際には次のようになります。

ここに画像の説明を入力

(つまりor_exprand_expr「レイヤー」はそこにありません)

ダークザエルスは次のように書いています。

残念ながら、これはかなり重要ですが、この言語の初期段階であるため、文法の詳細をすべて秘密にしておく必要があります。

問題ありませんが、重要な情報を差し控えると、人々はあなたの質問に適切に答えることができないことを認識しておく必要があります. 文法全体を投稿する必要はありませんが、左再帰のヘルプが必要な場合は、言及したエラーを実際に引き起こす (部分的な) 文法を投稿する必要があります。再現できなければ、存在しません!:)

于 2011-11-12T08:33:12.413 に答える
0

この生産:

infixExpr ::= PrefixExpr
            | InfixExpr id [nl] InfixExpr

のように書き換えられる.

infixExpr ::= PrefixExpr
            | PrefixExpr id [nl] InfixExpr

実際、これは単なる文法上の誤りだと思います。大丈夫だという例を示しましょう。最初の文法で何かを (部分的に) 削減してから、2 番目の文法を試してみましょう。

InfixExpr id [nl] InfixExpr                      
// Apply the second reduction to the first InfixExpr
InfixExpr id [nl] InfixExpr id [nl] InfixExpr
// Apply the first reduction to the (new) first InfixExpr
PrefixExpr id [nl] InfixExpr id [nl] InfixExpr
// Apply the first reduction to the new first InfixExpr
PrefixExpr id [nl] PrefixExpr id [nl] InfixExpr
// Apply the first reduction to the new first InfixExpr
PrefixExpr id [nl] PrefixExpr id [nl] PrefixExpr

2番目の文法でそれを減らしましょう:

PrefixExpr id [nl] InfixExpr                      
// Apply the second reduction to the first InfixExpr
PrefixExpr id [nl] PrefixExpr id [nl] InfixExpr
// Apply the first reduction to the new first InfixExpr
PrefixExpr id [nl] PrefixExpr id [nl] PrefixExpr

ご覧のとおり、どちらの場合も同等の AST で終了します。

于 2011-11-12T21:27:55.130 に答える