0

特定のクエリ言語用に bison+flex パーサーを作成していますが、C スタイルのキャスト演算子を追加する必要があります。コードの関連部分は次のとおりです。

%token <characterToken>  Identifier
%token <commandToken>    LRPAR RRPAR

%type <characterToken>   typename
%type <operationValue>   generalExp castExp variable

%%
generalExp: variable
      | LRPAR generalExp RRPAR
       { /* some code here */ }
      | castExp
      ;

castExp: LRPAR typename RRPAR generalExp
   { /* some code here */ }
   ;

variable: Identifier 
    { /* some code here*/ };
typename: Identifier;
%%

ここでの問題は、(typename)inがinとcastExp衝突し、reduce/reduce の競合が発生することです。(variable)generalExp

test.yy: conflicts: 1 reduce/reduce
test.yy:23.11-20: warning: rule useless in parser due to conflicts: typename: Identifier

考えられる解決策は、対応する lex ファイルにすべての有効な型名 (long、int、char など) をリストすることですが、使用定義型もサポートする必要があります。

UPD: 別の解決策は、bison GLR パーサーを使用することですが、パフォーマンスが低下するため、これは望ましくありません。

bison -v出力はこちら

4

3 に答える 3

2

はい、Cキャスト構文の選択が非常に不適切でした。キャストの中身が型なのか値なのかわからないと正しく解決できません。C でのいくつかのケースを次に示します。

(f)*a    // cast the value pointed to by a to type f, or multiply f by a?
(f)(a+b) // cast a+b to type f or call the function f with argument a+b?

これを処理するために私が見つけた最も簡単な方法は、レクサーがシンボル テーブルを参照できるようにすることです。これにより、タイプ名と識別子に対して異なるトークン タイプを返すことができます。(これは、C 文法がうまく機能する方法です。) レクサーとパーサーの間でシンボル テーブルを共有するのは、特にスコープ型定義を許可する場合は少し見苦しいですが、それは可能です。正しい字句解析のために、字句解析器が知る必要がある唯一のことは、シンボルが型の名前であるかどうかです。シンボルが明示的に型として宣言されていない限り、シンボルは型ではないと想定することでおそらく問題を回避できるため、すべてのシンボルを使用前に宣言することを厳密に主張する必要はありません。(たとえば、C++ では、非型のクラス メンバーを使用する前に宣言する必要はなく、それでも機能します。)

そうは言っても、可能であれば、キャストに別の構文を使用することを真剣に検討することを強くお勧めします。パーサーにとって苦痛であるだけでなく、人間の読者にとって厄介なほどあいまいになる可能性もあり (上記の例を参照)、キャストは一般的ではない (またはすべきではない) ため、省略された構文が必要になります。

C++ スタイルのキャスト -- cast<TYPE>(value)-- は、比較演算子をブラケットとしてリサイクルすることによって導入されるあいまいさの影響を受けますが、山括弧を使用する操作がキーワードの固定セットである場合は許容されます。(それ以外の場合は、レクサーが名前の種類を区別する必要がある別のコンテキストを作成します。)

個人的には、特にクエリ言語の場合、次のようなものを使用します

value as type

のように

(3 + 4) as double

これは(IMO)より読みやすく、入力が難しくなることなく解析がはるかに簡単です。

于 2014-05-09T20:01:11.293 に答える
0

最良の推測-あなたが示していない文法の他の部分は、generalExpそれらの間にトークンなしで2つの連続を許可します。したがって、 のような入力がある場合( Identifier ) expression、それはキャストまたは 2 つの連続するgeneralExpのいずれかである可能性があります。

続行する方法は、すべての競合の場合と同じです。すべての状態を示すファイルを-v取得するオプションを指定して bison を実行し、.outputどの状態がどのシンボルに対してどのような競合を起こしているかを正確に示します。それがわかれば、何ができるかを考えるチャンスがあります。

于 2014-05-09T20:00:53.587 に答える