3

PLY を使用して自分の言語用のパーサーを構築してきましたが、shift/reduce の競合が発生して問題が発生しています。私の言語には、構文 ala C++ テンプレートを持つジェネリック型があります。だから今、私は次のようなルールを持っています:

    expression : expression LESS expression %prec COMPARISON
    expression : template
    template : NAME
             | NAME LESS templates GREATER
    templates : template
              | templates COMMA template

ただし、解析できないことがわかりました。

a < 2

(これは明らかな理由で問題です)。デバッグ出力は次のとおりです。

PLY: PARSE DEBUG START

State  : 0
Stack  : . <Token: 'NAME' 'a'>
Action : Shift and goto state 42

State  : 42
Stack  : NAME . <Token: 'LESS' '<'>
Action : Shift and goto state 81

State  : 81
Stack  : NAME LESS . <Token: 'NUMBER' '2'>
ERROR: Error  : NAME LESS . <Token: 'NUMBER' '2'>

さらにパーサーが必要な場合は、提供できます。ありがとう。

編集:私に提案された1つの解決策は、型を独自のトークンにすることでした。私の言語は C/C++ のようなプリプロセッサ インクルード システムを使用していないため、これには少し作業が必要になりますが、それでも可能だと思いますが、文法に制限されたソリューションを希望します。

4

1 に答える 1

1

Yacc パーサーはそれほど強力ではなく、コンテキストフリーの解析を試みると、あまりにも多くのことを要求する可能性があります。ある種のトリックを使用して、yacc を状況依存の文法を解析しているように動作させることをお勧めします。または、パーサーを使用してすべての構文規則を適用しようとしないでください。


  • 型を解析しているときに Context Recognize を追加<し、フラグを設定するかメソッドを呼び出してこれをスキャナに伝え、この場合はと>に別の終端記号を返します。
  • 文法を簡素化する
    代わりに、テンプレート生成の一部に統一された式/テンプレート構文を使用し、コード内のテンプレート構文以外はすべてエラーにします。パーサーはシステムの中で最も能力の低い部分であるため、可能な場合は作業をコードにプッシュしてください。(コードに制限はありませんが、yacc には多くの制限があります。)

これらがあなたの唯一の選択肢だと言っているのではありません。状態テーブルについて頭を悩ませ、yacc が満足するまで文法を微調整するのに何日も費やしたなら、あなたは「成功」したと思いますが、それだけの価値はありません。その時点で、再帰降下パーサーを作成したことになるかもしれません。(RD はより多くのコード行であり、BNFish yacc では文法が整然と配置されているのを確認することはできませんが、少なくとも何でも解析でき、「機能していない」というパズルで行き詰まることはありません。)

Python には Ruby のTreetopに相当するものはありますか? それは問題を解決するでしょう。Bison の%glr-parser機能は、かなり BFI の方法ではありますが、このような問題を「解決」することもできます。

于 2009-11-27T18:06:10.587 に答える