akasaka_34の日記

ネトウヨと呼ばれた男の日記。しかし頻度から言えば週報ぐらい。

Haskellの構文解析

Haskellの構文解析のやり方を探してウェブ上を右往左往していると
良さげなページを見つけた。
オフサイドルールの処理 - soutaroブログ
そして公式情報はこれらしい。
Haskell 98 Syntax
Haskell 98 Syntax(日本語)
空白込みで字句解析して、レイアウトしなおして、構文解析するのか。
ちゃらちゃらっと実装してみようかなと思ったら
parse-error(t)という妙な関数が出てきた。
次のトークンがtだったらエラーになる場合はparse-error(t)が真とのこと。

「つまり、構文解析が成功するかどうか知らないとレイアウトできないの?
でもレイアウトしてからじゃないと構文解析できねえじゃん!?」

件の「良さげなページ」でも問題にされている。
オフサイドルールの処理 - parse-error(t)って結局なんやったん? - soutaroブログ

これでかなり悩んだけど、しばらくして気がついた。
たぶん、構文解析器に渡されるのはトークンのリストではなく、
トークンのツリーなんだ。
たとえばソースが"do a == b == c"なら

を渡された構文解析器が
「do a == b == ...って、ありえねえよ」
と言って上のブランチを選ぶ。

コンセプト上は巨大なツリーが生じるわけだけど
遅延評価するから、実際にツリー全体が生成されるわけじゃない。
上の例で言えば"}"が入らない場合の"=="より後は計算されない。