nikkie-ftnextの日記

イベントレポートや読書メモを発信

めもり〜☆さんの「二郎系ラーメンのコールで学ぶ AST 解析」を見て、pyparsingではどうなるか触り出し #phpcon_odawara

はじめに

叛逆のニジガサキ、これは、令和のボーボボ!(確信) nikkieです。

私は抽象構文木がけっこう好き1なのですが、PHPカンファレンス小田原2024の発表アーカイブをきっかけに、pyparsingライブラリを触り出しました。

目次

「二郎系ラーメンのコールで学ぶ AST 解析」by めもり〜☆

きっかけは、あすみ様2アドベントカレンダー
PHPカンファレンス小田原20243トークを1本ずつ視聴して記事にされています。

あすみ様アドカレ記事をきっかけにアーカイブを見て4、私もPythonで「ニンニクマシマシ野菜マシマシカラメ」をパースしてみたいと思ったのでした。

よろしくpyparsing

名前だけ知っていたpyparsingをこの機に触ります。
試しにLLM(Gemini)にサンプルコードを書いてもらい、これを手がかりとしてドキュメントに当たりながら手を動かしていきました。

  • Python 3.12.6
  • pyparsing 3.2.0

「野菜マシマシ」

from pyparsing import one_of

topping = one_of("ニンニク 野菜 カラ")
amount = one_of("マシマシ マシ メ")
jiro_item = topping("topping") + amount("amount")
print(jiro_item.parse_string("野菜マシマシ"))
% python script.py
['野菜', 'マシマシ']

「ニンニクマシ野菜マシマシカラメ」

from pyparsing import ZeroOrMore, one_of

topping = one_of("ニンニク 野菜 カラ")
amount = one_of("マシマシ マシ メ")
jiro_item = topping("topping") + amount("amount")
jiro_expr = jiro_item + ZeroOrMore(jiro_item)

order = "ニンニクマシ野菜マシマシカラメ"
parsed = jiro_item.search_string(order)
for p in parsed:
    print(p.topping, p.amount)
% python script.py
ニンニク マシ
野菜 マシマシ
カラ メ

pyparsingで作る二郎系ラーメン

% uv run script.py
Ramen(toppings=[Topping(item='ニンニク', amount=1), Topping(item='野菜', amount=2), Topping(item='カラ', amount=1)])

終わりに

PHPカンファレンス小田原2024のめもり〜☆さんのトークにインスパイアされ、pyparsingを使って二郎系ラーメンのコールをパースしてみました。
私がまず浮かぶ方法は正規表現だったのですが、こんな方法があるんですね〜5
なお、pyparsing自体は初見で知らないことが多いので、もっとうまく書ける余地はある気がしています。

触ってみてpyparsingは文法を定義している感がありました。
例:https://pyparsing-docs.readthedocs.io/en/latest/pyparsing.html#pyparsing.indentedBlock
今回定義したのは、二郎系ラーメンのコールの文法だったのです!

最後に、めもりーさん、あすみさん、刺激的なアウトプットをありがとうございます!

P.S. 発売おめでとうございます!

技術書界のきららキャラット!(きららはちょうぜつ本なので)


  1. 具象構文(見た目)から入りました。 リンタを自作など抽象構文木と戯れています
  2. PHPカンファレンス小田原2024の委員長です。直近ではぺぱ合戦(おめでとうございます!)
  3. 私がまとめていたのでした
  4. めもりーさんによる発表後記
  5. tree-sitterの名も思い出しました