Dev Study
← 解説「構文解析と AST — 生成規則 1 つが関数 1 つ(再帰下降)」に戻る

サンプルコードで身につける: 構文解析と AST — 生成規則 1 つが関数 1 つ(再帰下降)

解説で学んだ概念を、3つの具体例で確認します。素朴な例から実務寄りの例へと進みます。

1再帰下降と左結合: 左再帰をループにする

AdditiveExpression の規則を関数 1 つに写した parse_additive_expression です。文法は左再帰ですが、そのまま関数にすると無限再帰になるので「左を 1 つ読み、演算子が続く限り右を読んで、これまでの左を包む」ループにします。10 - 2 - 3 を与えると (10 - 2) - 3 の木が出ては 5 になり、にしてしまうと 11 になることが分かります。

Rust

2右結合・MemberExpression・CallExpression

代入は右側を parse_assignment_expression 自身で読むので右結合になり、. と ( は PrimaryExpression の後ろに何個でも続くのでループで外側に包んでいきます。実行すると a = b = c が Assign(a = Assign(b = c))、document.getElementById(t).textContent = x が Member(Call(Member(...))) の入れ子になり、f( は途中で入力が終わって SyntaxError になります。参照実装はこの None の代わりに「何を期待したか」を持つ ParseError を返します。

Rust

3実務に写す: 料金式の電卓(優先順位は文法の段で表す)

設定ファイルに書かれた料金の計算式を読んで評価するです。Additive → Multiplicative → Primary の 3 段にするだけで * / が + - より先に結合し、期待と違う文字や入力の終わりに出会ったら「何を期待したか」を持つエラーを返します(参照実装の ParseError と同じ形)。実行すると price * qty + price * qty * tax_rate が 3960、閉じ括弧の無い式と余った閉じ括弧がそれぞれ SyntaxError になります。

Rust

図やコードに出てくる用語(タップで説明)