1

yacc で条件付きコンパイルを行う方法。ifdef を使用して C で行うのと同様です。
条件に基づいてルールを作成したい。yaccで可能ですか?例。条件ルール A に基づいて、次のように定義されます。

ruleA : A | B, /* For condition 1 */  
ruleA : C      /* If condition 1 is not satisfied */  
4

3 に答える 3

2

btyaccには、C プリプロセッサと同様に、定義されたフラグに基づく条件付きコンパイルがあります。あなたは言うことができます:

%ifdef VERSION_A
ruleA: A | B ;
%endif
%ifdef VERSION_B
ruleA: C ;
%endif

次に、-DVERSION_Aまたは-DVERSION_Bコマンド ライン引数を使用して、いずれかのバージョンを取得します。それはかなり原始的です( ごとに単一のフラグしかテスト%ifdefできず、 をネストできず、 も%ifdefありません%else)、単純なことには十分です。

于 2012-11-01T21:26:43.020 に答える
0

私の提案は、条件付きフラグをターミナル シンボルとして公開することです。これをモード ターミナルと呼ぶことができます。(つまり、技術的には、これはコンパイル時ではなく実行時の条件です。)

解析に違いが生じるたびに、モード ターミナルを返す必要があります。余分なものを受け取ると、文法はそれを無視できます。モード端子は「条件1」の場合のみ、「条件1でない」の場合のみ、または両方の場合で別のものを返すことができます。つまり、各モードに 1 つずつ、2 つのトークン C1 と C2 があるとします。

既存の文法を解析している場合、これはうまくいかないかもしれませんが、文法とパーサーを一緒に設計している場合、すべての問題は解決可能です。

次に、次のようになります。

ruleA : C1 A | C1 B | C2 C ;
于 2012-11-01T20:09:09.260 に答える
0

Yacc 文法を適切なプリプロセッサで前処理できない場合は、アクションに基づくソリューションを使用できます。

ruleA : A { if  (condition1) { process OK; } else YYERROR; }
      | B { if  (condition1) { process OK; } else YYERROR; }
      | C { if (!condition1) { process OK; } else YYERROR; }
      ;

YYERROR アクションは、Yacc の通常のエラー処理メカニズムをトリガーします。これは、Yacc に関する限り、文法が動作中の両方のルール セットで「機能する」必要があることを意味します。これがシフト/リデュース (またはリデュース/リデュース) の競合のために複雑になる場合は、前処理が最適です。結果の文法はより小さくなり、より焦点が絞られます。

于 2012-11-01T05:21:28.177 に答える