3

PLY を使用して C パーサーを作成していますが、最近問題が発生しました。このコード:

typedef int my_type;
my_type x;

my_type は、以前は型として使用されていた型として定義されているため、正しい C コードです。型と単純な識別子を区別するためにレクサーが使用するパーサーの型シンボル テーブルに入力することで、これを処理します。

ただし、型宣言規則は SEMI (';' トークン) で終了しますが、PLYmy_typeは最初の行で終了したと判断する前に、2 行目からトークンをシフトします。このため、型シンボル テーブルの更新をレクサーに渡す機会がなく、レクサーは my_type を型ではなく識別子として認識します。

修正のアイデアはありますか?

完全なコードは次の場所にあります: http://code.google.com/p/pycparser/source/browse/trunk/src/c_parser.py これより小さな例を作成する方法がわかりません。

編集:

問題が解決しました。以下の私の解決策を参照してください。

4

3 に答える 3

3

レクサーでそのレベルの分析を行っている理由がわかりません。

入力ストリームを字句トークン (数値、改行、キーワードなど) に分離するには、おそらく字句解析を使用する必要があります。typedef などのテーブル ルックアップを含む、そのレベルの分析を行う必要があるのは解析フェーズです。

これが、私が常に lexx と yacc (私の選択したツール) の間で役割を分担してきた方法です。

于 2008-09-20T12:47:23.487 に答える
2

Dave Beazley (PLY の作成者) の助けを借りて、私の問題は解決されました。

アイデアは、特別なサブルールを使用して、その中でアクションを実行することです。私の場合、declarationルールを次のように分割します。

def p_decl_body(self, p):
    """ decl_body : declaration_specifiers init_declarator_list_opt
    """
    # <<Handle the declaration here>>        

def p_declaration(self, p):
    """ declaration : decl_body SEMI 
    """
    p[0] = p[1]

decl_bodySEMI がシフトインされた後、トークンの前に常に削減されるため、私のアクションは正しいタイミングで実行されます。

于 2008-09-20T15:28:02.633 に答える
1

ID が TYPEID かどうかのチェックを c_lexer.py から c_parser.py に移動する必要があると思います。

あなたが言ったように、パーサーは1トークン先を見ているので、レクサーでその決定を下すことはできません。

代わりに、パーサーを変更して ID をチェックし、それらが宣言内の TYPEID であるかどうかを確認し、そうでない場合はエラーを生成します。

Pax Diablo が優れた回答で述べたように、レクサー/トークナイザーの仕事は、トークンについてそのような決定を下すことではありません。それがパーサーの仕事です。

于 2008-09-20T12:31:30.733 に答える