このブログの更新は Twitterアカウント @m_hiyama で通知されます。
Follow @m_hiyama

メールでのご連絡は hiyama{at}chimaira{dot}org まで。

はじめてのメールはスパムと判定されることがあります。最初は、信頼されているドメインから差し障りのない文面を送っていただけると、スパムと判定されにくいと思います。

参照用 記事

構文解析のオハナシ:補遺

構文解析のオハナシは、変なことを書いてしまったですね。これ以上追記をするとゴチャゴチャし混乱しそうだから、このエントリーに補足と注意をまとめます。

構文規則の曖昧性と演算子の優先順位

ことの発端は、演算子を含む式を「式 ::= 式 '+' 式」のように“なにげなく”定義すると、曖昧な構文規則(文法)になるよ、ってことね。再帰下降法のパーザーを前提にするんなら、優先順位の高さに応じて式の構成を階層化するってこと(これが、aiue3=ショー君のメモ)。例えば:


[優先順位 低] 式 ::= 加数 ('+' 式)*
[優先順位 中] 加数 ::= 因数 ('*' 加数)*
[優先順位 高] 因数 ::= 数 | '-' 因数 | '(' 式 ')'

優先順位ごとに構文規則があり、それぞれ、'+', '*', '-'(単項) という演算子が導入されています。これを、最初に僕が間違ったように「加数 ::= 因数 ('*' 加数)* | '-' 加数」とかすると、'*'と'-'の優先順位がハッキリせずに曖昧性が解消されません。

なお、「演算子順位文法に基づくパーザージェネレータの実例を知らない」と書きましたが、老舗定番ジェネレータyacc(解析アルゴリズムはLR、C言語ベース)でも、%left, %right という指令で演算子優先順位を指定できるようです。

手書きサンプル・パーザー

だいたいうまく動くようです。見直してみると、可読性もそれほどヒドイわけでもないし。

実はアサーションが間違っていました(本末転倒じゃ)、オプション -ea (enable assertions) を付けずに実行していたので気が付きませんでした。これだけは直しました。

コンパイル/実行すると次のような感じ:


C>javac ArithExp.java
C>java -cp . -ea ArithExp
3+-5*--3*5+2

3+-5*--3*5+2 ==>
+(
3,
+(
*(
-(
5
),
*(
-(
-(
3
)
),
5
)
),
2
)
)