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 == ...って、ありえねえよ」
と言って上のブランチを選ぶ。
コンセプト上は巨大なツリーが生じるわけだけど
遅延評価するから、実際にツリー全体が生成されるわけじゃない。
上の例で言えば"}"が入らない場合の"=="より後は計算されない。