10

演算子なしの関数適用 (Ocaml や Haskell など) と、2 項演算子と単項演算子の通常の組み合わせをサポートする ocamlyacc (通常の yacc とほぼ同じ) で文法を解析しようとしています。減算と否定の両方に使用できる「-」演算子との削減/削減の競合が発生しています。ここに私が使用している文法のサンプルがあります:

%token <int> INT
%token <string> ID
%token MINUS

%start expr
%type <expr> expr

%nonassoc INT ID
%left MINUS
%left APPLY

%%

expr: INT
    { ExprInt $1 }
| ID
    { ExprId $1 }
| expr MINUS expr
    { ExprSub($1, $3) }
| MINUS expr
    { ExprNeg $2 }
| expr expr %prec APPLY
    { ExprApply($1, $2) };

問題は、"a - b" のような式を取得した場合、パーサーはこれを "a (-b)" (b の否定、その後に適用) と縮小するか、"a - b" (減算)。減算削減は正しいです。そのルールを優先して競合を解決するにはどうすればよいですか?

4

2 に答える 2

8

残念ながら、私が思いつく唯一の答えは、文法を複雑にすることです。

  1. exprに分割simple_exprexpr_with_prefix
  2. allow onlysimple_exprまたは(expr_with_prefix)APPLY で

最初のステップは、reduce/reduce の競合を shift/reduce の競合に変えますが、括弧はそれを解決します。

「ab c」でも同じ問題が発生します。それa(b(c))ですか(a(b))(c)? また、文法で中断しapplied_expressionて必要とする必要があります。(applied_expression)

これでうまくいくと思いますが、よくわかりません:

expr := INT
      | parenthesized_expr
      | expr MINUS expr

parenthesized_expr := ( expr )
                    | ( applied_expr )
                    | ( expr_with_prefix )

applied_expr := expr expr

expr_with_prefix := MINUS expr
于 2008-08-23T20:49:00.047 に答える
0

まあ、この最も簡単な答えは、それを無視して、デフォルトのreduce/reduce解像度で処理させることです。つまり、文法で最初に現れるルールを減らします。この場合、それはexpr MINUS exprを優先して削減することを意味MINUS exprします。これはまさにあなたが望むものです。を見た後a-b、それを単項マイナスとして解析してから適用するのではなく、バイナリ マイナスとして解析する必要があります。

于 2011-10-06T18:06:54.203 に答える