2026-04-06: ASTの設計をしている
やったこと
Naraku
ASTの設計をしている。
毎度悩むのだが、文字クラスのASTの設計が難しい。
Rubyの文字クラスの構文は細かな部分 (- をどこに書けるかなど) を除いてBNF風に書くとこんな感じ。
char-class ::= "[" "^"? char-class-intersection "]"
char-class-intersecion ::= char-class-union ("&&" char-class-union)*
char-class-union ::= char-class-item*
char-class-item ::= one of
# 文字 or 範囲
char ("-" char)?
# 文字タイプのエスケープシーケンス
"\" [wWdDsShH]
# POSIX文字クラス
"[" (":" "^"? | "^:") posix-char-class-name ":]"
# ネストした文字クラス
"[" "^"? char-class-intersection "]"
気持ち悪いのは ^ が && よりも優先度が低いこと。
つまり /[^a-b&&b-c]/ は /[^[[a-b]&&[b-c]]]/ のように解釈されるので、結果的に /[^b]/ となる。
まあそういう仕様だと割り切るしかないか。
やはりエスケープシーケンスを事前にRuby側で解釈するのは悪だと思う。
今回見つけた事案は次のような感じ:
m = /(?<\u0061>a)\g<\x61>/.match("aa")
p m['\x61'] # => "a"
事前に \u0061 が \x61 として扱われるので、これは上手く動作してしまうことになる。
Onigmo側では処理されないので、例えば /(?<a>foo)\g<\u0061>/ のようになっても上手く動かないので注意。
あとPrismはキャプチャの位置のエスケープシーケンスを通常の文字に展開してしまっているようで 、Prismで /(?<\x61>a)\g<\x61>/ =~ "a" とするとローカル変数に a が宣言されるっぽい。
この辺りの変な挙動の違いが生まれる原因はRuby側で処理していることにあるので。やはり正規表現エンジン側で色々処理しないといけないのではないかと思う。
ぽこポケ
相変わらずクラウド島。
画面に出てないやつが増えてきている気がするので、暗転の入る家を作ってそちらに住まわせた方がいいのではないかと思っている。
あとレアポケメタルが足りない。困った。