Re: 逆ポーランド記法とpreg_match_all

第166回 PHP勉強会@東京」をオンラインで視聴することができました。ありがとうございます。

@asumikam さんの 「逆ポーランド記法とpreg_match_all」が興味深かったです。

ということで、試してみたリポジトリです。

 

使い方

<?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を呼び出すコードを書いている時の「妙な罪悪感」が凄い。
  • このリポジトリは「この方法の方が良いですよ」という意味では全くなく、考えたことについて手を動かしてみた結果です。

実際には、いい感じの(信頼できる)ライブラリを使うのが安全ですね。

 

追記(2024-07-20)

ASTと言えばの inocoさんが、PHP-Parser を使った「安全な?eval電卓」を作ってくれました。

https://twitter.com/3namn/status/1814290986723606875

「あー、その手があったかー」と思わせる、面白くてしかも自分が一から実装してみたものより、機能追加等が簡単そうで、流石でした。

 

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です


reCaptcha の認証期間が終了しました。ページを再読み込みしてください。

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください