Re: 逆ポーランド記法とpreg_match_all
2024/07/19
「第166回 PHP勉強会@東京」をオンラインで視聴することができました。ありがとうございます。
@asumikam さんの 「逆ポーランド記法とpreg_match_all」が興味深かったです。
興味深いです。自分ならどうするかなーと思うと、正規表現を使わない字句解析とパースを行った物をevalするかもなー。パースまで正常に行えていれば意図ない物ではないだろうという判断。
— しめじ(smeghead) (@smeghead) July 18, 2024
ということで、試してみたリポジトリです。
使い方
<?php
public function test簡単な式(): void {
$sut = new CalcAtto();
$this->assertSame(3, $sut->calc('1+2'));
$this->assertSame(6, $sut->calc('3*2'));
$this->assertSame(5, $sut->calc('1 * 2 + 3'));
$this->assertSame(3.3333333333333335, $sut->calc('10 / 3'), '10 / 3');
}
- 字句解析(Tokenize)と構文解析(Parse)というフェーズに分けて入力を検証しました。(後に
eval
で処理するつもりだったので構文解析はたいした事はしてません) - 字句解析: 雰囲気で言うと、意味を考えずに最小単位のトークンに分割する。
- 構文解析: 雰囲気で言うと、前後のトークンを考慮して文法的な意味を考慮したチェックを行なう。
- 正規表現を使わないと書いてたのですが、簡単にするために字句解析で一部使ってます。
- 検証した入力を再度文字列に戻して、
eval
に渡しました。 - しかし、
eval
を使うコードは自分で書いてみて、更にマニュアルを読めば読む程に怖くなってくるので、やっぱり使わない方がいいですね。eval
を呼び出すコードを書いている時の「妙な罪悪感」が凄い。 - このリポジトリは「この方法の方が良いですよ」という意味では全くなく、考えたことについて手を動かしてみた結果です。
実際には、いい感じの(信頼できる)ライブラリを使うのが安全ですね。
こういうちょっとした数式っぽいものの評価を提供するならSymfony Expression Languageといういい感じのライブラリを使うといいと思います! #phpstudy https://t.co/QcdhbXh2FO
— にゃんだーすわん (@tadsan) July 18, 2024
追記(2024-07-20)
ASTと言えばの inocoさんが、PHP-Parser を使った「安全な?eval電卓」を作ってくれました。
https://twitter.com/3namn/status/1814290986723606875
「あー、その手があったかー」と思わせる、面白くてしかも自分が一から実装してみたものより、機能追加等が簡単そうで、流石でした。