2

私は次のような構文を持っています

%(var)

%var

および (var)

私のルールは次のようなものです

optExpr:
    | '%''('CommaLoop')'
    | '%' CommaLoop

CommaLoop:
    val | CommaLoop',' val

Expr:
    MoreRules
    | '(' val ')'

問題は、それが ) に属している%(CommaLoop)かどうかを判断できないように見えることです% (val)が、( の代わりに ) に文句を言うのです。一体何ですか? 文句を言う(べきではありませんか? どうすればエラーを修正できますか?%(トークンを作成することは良い解決策ですが$(、これを行う前にエラーではない理由を確認したいと思います。

4

2 に答える 2

3

これは、LR 解析の仕組みによるものです。LR 解析は効果的にボトムアップであり、文法規則の RHS に従ってトークンをグループ化し、それらを LHS に置き換えます。パーサーが「シフト」すると、トークンがスタックに置かれますが、実際にはまだルールに一致していません。代わりに、現在の状態を介して部分的に一致したルールを追跡します。ルールの終わりに対応する状態になると、RHS のシンボルをスタックからポップし、LHS を示す単一のシンボルを押し戻すことができます。そのため、競合がある場合、パーサーが何らかのルールの最後に到達し、削減するかどうか (または削減するもの) を決定できないまで、それらは表示されません。

あなたの例では、% ( val、それがスタック上にあるものです (ここでは上部が右​​側にあります) を見た後、先読みが)の場合、 val をポップしてルールを介して削減する必要があるかどうかを判断できませんCommaLoop: val、または)をシフトする必要がある場合は、3 つのものをポップし、ルールExpr: '(' val ')'で削減できます

ここでは、 CommaLoop: Exprなどの追加のルールがあると想定しています。そうしないと、文法が実際には何にも一致せず、bison/yacc が未使用の非終端記号について文句を言うでしょう。

于 2009-12-07T22:50:00.433 に答える
0

現在、あなたの説明と文法が一致していないようです。あなたの説明では、3つのフレーズすべてに「var」があると示されていますが、文法では「%」で始まるものはカンマ区切りのリストを許可するものとして示されていますが、ないものは単一の「val」しか許可されていません。

ここでは、3 つすべてでカンマ区切りのリストを許可する必要があると仮定します。この場合、文法を次のように因数分解します。

optExpr: '%' aList

aList: CommaLoop
    | parenList

parenList: '(' CommaLoop ')'

CommaLoop: 
    | val 
    | CommaLoop ',' val

Expr: MoreRules
    | parenList

私は optExpr と Expr を変更したので、どちらも空のシーケンスと一致しません。私の推測では、最初から意図していなかったのではないでしょうか。私はこれを byacc で実行するのに十分なほど肉付けしました。警告やエラーは発生しません。

于 2009-12-02T05:56:46.493 に答える