目次
プロカルク2000
1 つには何が入っていますか?
トークナイザー
パーサー
評価者
コードを見せてください?
以上です
演算子の優先順位
続きを読む

1 時間の表現言語

Jan 21, 2025 am 08:16 AM

The One Hour Expression Language

このブログ投稿は、元の形式で表示するのが最適です。

この投稿は、1 時間の式言語 というタイトルのプレゼンテーションを要約し、概念とコードの両方をレビューします。1

式言語2は、このコンテキストでは、式 (バイトのシーケンス、おそらく UTF-8 文字) を評価します。3 例は次のとおりです。

  • 1 1
  • //article[@title="foobar"]//image
  • .items[].foo|select(.bar = "foo")
  • a.comments > 1 and a.category not in ["misc"]

式言語 (または DSL4) の例は次のとおりです:

  • JQ
  • Kibana クエリ言語
  • XPath 言語
  • Symfony 式言語

なぜ独自の表現言語を構築するのでしょうか? なぜだめですか? 忙しすぎますか? 心配しないで!数か月、数週間、さらには数日も必要ありません。 One Hour Expression Language を使用して 1 時間で 1 つ作成しましょう!5

プロカルク2000

私たちは、2000 年以降に向けた次世代の非科学算術計算機である ProCalc2000 式言語を構築します。

1 11 2 などの式を評価し、1 3 2 / 2 などの除算問題を処理できます。

ゴジラ ゴジラは浮動小数点数による割り算を嫌います。

言語は数字 (例: 1、2) と演算子 (、、-、) で構成されます。 演算子の優先順位 (付録 I を参照) や除算は*サポートされません。

そのシンプルさにもかかわらず、変数、関数、パイプ演算子、サフィックス、文字列の連結、さらには (ゴジラの希望に反して) 除算などの機能を追加するための基盤を提供します。

1 つには何が入っていますか?

バイト シーケンスを評価するには多くの方法がありますが、ここではトークナイザー、パーサー、およびエバリュエーターを使用します。

<code>              +-----------+  tokens  +--------+  ast  +-----------+ 
EXPRESSION ==>| Tokenizer |--------->| Parser |------>| Evaluator | => VALUE
              +-----------+          +--------+       +-----------+</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

トークナイザー

レクサーまたはスキャナーとも呼ばれます。このクラスは、文字列をトークンと呼ばれる分類されたチャンクに分割します。

class Tokenizer
{
    public function tokenize(string $expression): Tokens
    {
        // ...
    }
}
ログイン後にコピー
ログイン後にコピー

たとえば、1 2 3 は 5 つのトークンを生成します。

<code>Token(Integer, 1)
Token(Plus)
Token(Integer, 2)
Token(Plus)
Token(Integer, 3)</code>
ログイン後にコピー
ログイン後にコピー

トークナイザーは左から右にスキャンして、興味深いチャンク (正の整数、 、 - 、および * 演算子) を識別します。空白は無視されます。他の文字を使用するとエラーが発生します。 トークンのタイプは、整数、プラス、マイナス、乗算です。

ゴジラ Godzilla はトークナイザーとスタック マシンを提案しますが、Godzilla が気にするのでパーサーと評価器を使用します。

トークナイザーは式の有効性をチェックしません。チャンクを分類するだけです。6 トークンはパーサーに渡されます。

パーサー

パーサーはトークンを解釈し、抽象構文ツリー (AST) に変換します。

<code>              +-----------+  tokens  +--------+  ast  +-----------+ 
EXPRESSION ==>| Tokenizer |--------->| Parser |------>| Evaluator | => VALUE
              +-----------+          +--------+       +-----------+</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー

トークン リストが与えられると、パーサーは AST (ツリーのルート ノード) を返します。 各ノードは評価可能な式です。ノード タイプは BinaryOp と Integer です。

二項演算には 2 つのオペランドがあります (たとえば、foo or barBinaryOp(Variable('foo'), 'or', Variable('bar')) である可能性があります)。

単項演算にはオペランドが 1 つあります (例: -1)。

三項演算には 3 つのオペランドがあります (例: foo ? bar : baz)。

1 1 / 5 は、演算子として を持つ BinaryOp で、一方のオペランドは 1 で、もう一方のオペランドは別の BinaryOp (1 / 5) です。

class Tokenizer
{
    public function tokenize(string $expression): Tokens
    {
        // ...
    }
}
ログイン後にコピー
ログイン後にコピー

評価者

エバリュエーターはノードを受け入れ、値 (ここでは整数) を返します。 木歩き通訳です

<code>Token(Integer, 1)
Token(Plus)
Token(Integer, 2)
Token(Plus)
Token(Integer, 3)</code>
ログイン後にコピー
ログイン後にコピー

コードを見せてください?

このコードは PHPSW ミートアップで誕生し、単体テストによって推進されました (ここでは省略)。リポジトリを参照してください。

ゴジラ ゴジラはこのコードに怒って、リファクタリングを提案するでしょう。

トークナイザー

まず、Token 列挙型とオプションの値を持つ TokenType クラス:

class Parser
{
    public function parse(Tokens $tokens): Node
    {
        // ...
    }
}
ログイン後にコピー
<code>                        +-------------+
                        | Binary Op + | 



<p>In PHP:</p>

```php
$ast = new BinaryOp(
    left:     new Integer(1),
    operator: '+',
    right:    new BinaryOp(
        left:     new Integer(1),
        operator: '/',
        right:    new Integer(5),
    )
);</code>
ログイン後にコピー

トークンは次のようになります:

class Evaluator
{
    public function evaluate(Node $node): int
    {
        // ...
    }
}
ログイン後にコピー

Tokenizer クラスは次の作業を行います:7

class Token
{
    public function __construct(
        public TokenType $type,
        public ?string $value = null
    ) {}
}
ログイン後にコピー

Tokens コレクション:

enum TokenType
{
    case Plus;
    case Minus;
    case Multiply;
    case Integer;
}
ログイン後にコピー
ゴジラ Godzilla は、配列と `array_shift`、またはトークン化と解析を同時に行うためのジェネレーターを好みます。

パーサー

[
    new Token(TokenType::Integer, 50),
    new Token(TokenType::Plus),
    // ...
]
ログイン後にコピー

ここに、演算子の優先順位、サフィックス解析、パイプ演算子が追加されます。 たとえば、サフィックス解析では、「5 マイル」のような表現を処理します。

評価者

class Tokenizer
{
    public function tokenize(string $expression): Tokens 
    {
        $offset = 0;
        $tokens = [];
        while (isset($expression[$offset])) {
            $char = $expression[$offset++];
            if (is_numeric($char)) {
                while (is_numeric($expression[$offset] ?? null)) {
                    $char .= $expression[$offset++];
                }
                $tokens[] = new Token(TokenType::Integer, $char);
                continue;
            }
            $token = match ($char) {
                '+' => new Token(TokenType::Plus),
                '-' => new Token(TokenType::Minus),
                '*' => new Token(TokenType::Multiply),
                ' ' => null,
                default => throw new RuntimeException(sprintf(
                    'Invalid operator: "%s"', $char
                )),
            };
            if ($token === null) {
                continue;
            }
            $tokens[] = $token;
        }
        return new Tokens($tokens);
    }
}
ログイン後にコピー

以上です

このコードは、テストを含めてライブコーディングされました。 完全なコードはリポジトリで入手できます。

演算子の優先順位

1 * 3 4(1 * 3) 4 = 7 である必要がありますが、解析方法により、言語はそれを 1 * (3 4) = 7 として評価します。8 Pratt パーサーはこれを修正します。

<code>              +-----------+  tokens  +--------+  ast  +-----------+ 
EXPRESSION ==>| Tokenizer |--------->| Parser |------>| Evaluator | => VALUE
              +-----------+          +--------+       +-----------+</code>
ログイン後にコピー
ログイン後にコピー
ログイン後にコピー
ゴジラ ゴジラは再帰性を理解しています。

続きを読む

  • Crafting Interpreters: 書籍 (無料 Web 版付き) by Robert Nystrom
  • 式の解析が簡単に: Robert Nystrom によるブログ投稿
  • スタック マシン RPN 計算機: Igor Wiedler による 2014 年の投稿
  • ドクトリンレクサー
  • PHPStan Phpdoc パーサー9

  1. コードは反復ごとに変更されます。
  2. より具体的には、式言語インタープリタ。
  3. PHP では文字列と呼ばれることがよくあります。
  4. ドメイン固有の言語
  5. 特許は存在しません。
  6. トークナイザーは構文の強調表示に役立ちます。
  7. preg_ メソッドの方がパフォーマンスが高い可能性があります。
  8. 異なる答えが期待されていた場合のみ、間違っています。
  9. ツリートラバーサルは、Doctrine のクエリビルダーを通じて発見されました。

以上が1 時間の表現言語の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

このウェブサイトの声明
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。

ホットAIツール

Undresser.AI Undress

Undresser.AI Undress

リアルなヌード写真を作成する AI 搭載アプリ

AI Clothes Remover

AI Clothes Remover

写真から衣服を削除するオンライン AI ツール。

Undress AI Tool

Undress AI Tool

脱衣画像を無料で

Clothoff.io

Clothoff.io

AI衣類リムーバー

Video Face Swap

Video Face Swap

完全無料の AI 顔交換ツールを使用して、あらゆるビデオの顔を簡単に交換できます。

ホットツール

メモ帳++7.3.1

メモ帳++7.3.1

使いやすく無料のコードエディター

SublimeText3 中国語版

SublimeText3 中国語版

中国語版、とても使いやすい

ゼンドスタジオ 13.0.1

ゼンドスタジオ 13.0.1

強力な PHP 統合開発環境

ドリームウィーバー CS6

ドリームウィーバー CS6

ビジュアル Web 開発ツール

SublimeText3 Mac版

SublimeText3 Mac版

神レベルのコード編集ソフト(SublimeText3)

PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? PHPでの安全なパスワードハッシュ(例:Password_hash、password_verify)を説明します。 MD5またはSHA1を使用してみませんか? Apr 17, 2025 am 12:06 AM

PHPでは、Password_hashとpassword_verify関数を使用して安全なパスワードハッシュを実装する必要があり、MD5またはSHA1を使用しないでください。 1)password_hashセキュリティを強化するために、塩値を含むハッシュを生成します。 2)password_verifyハッシュ値を比較して、パスワードを確認し、セキュリティを確保します。 3)MD5とSHA1は脆弱であり、塩の値が不足しており、最新のパスワードセキュリティには適していません。

スカラータイプ、リターンタイプ、ユニオンタイプ、ヌル可能なタイプなど、PHPタイプのヒントはどのように機能しますか? スカラータイプ、リターンタイプ、ユニオンタイプ、ヌル可能なタイプなど、PHPタイプのヒントはどのように機能しますか? Apr 17, 2025 am 12:25 AM

PHPタイプは、コードの品質と読みやすさを向上させるためのプロンプトがあります。 1)スカラータイプのヒント:php7.0であるため、基本データ型は、int、floatなどの関数パラメーターで指定できます。 3)ユニオンタイプのプロンプト:PHP8.0であるため、関数パラメーターまたは戻り値で複数のタイプを指定することができます。 4)Nullable Typeプロンプト:null値を含めることができ、null値を返す可能性のある機能を処理できます。

PHPおよびPython:さまざまなパラダイムが説明されています PHPおよびPython:さまざまなパラダイムが説明されています Apr 18, 2025 am 12:26 AM

PHPは主に手順プログラミングですが、オブジェクト指向プログラミング(OOP)もサポートしています。 Pythonは、OOP、機能、手続き上のプログラミングなど、さまざまなパラダイムをサポートしています。 PHPはWeb開発に適しており、Pythonはデータ分析や機械学習などのさまざまなアプリケーションに適しています。

PHPおよびPython:コードの例と比較 PHPおよびPython:コードの例と比較 Apr 15, 2025 am 12:07 AM

PHPとPythonには独自の利点と短所があり、選択はプロジェクトのニーズと個人的な好みに依存します。 1.PHPは、大規模なWebアプリケーションの迅速な開発とメンテナンスに適しています。 2。Pythonは、データサイエンスと機械学習の分野を支配しています。

PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO) PHPでのSQL注入をどのように防止しますか? (準備された声明、PDO) Apr 15, 2025 am 12:15 AM

PHPで前処理ステートメントとPDOを使用すると、SQL注入攻撃を効果的に防ぐことができます。 1)PDOを使用してデータベースに接続し、エラーモードを設定します。 2)準備方法を使用して前処理ステートメントを作成し、プレースホルダーを使用してデータを渡し、メソッドを実行します。 3)結果のクエリを処理し、コードのセキュリティとパフォーマンスを確保します。

PHP:データベースとサーバー側のロジックの処理 PHP:データベースとサーバー側のロジックの処理 Apr 15, 2025 am 12:15 AM

PHPはMySQLIおよびPDO拡張機能を使用して、データベース操作とサーバー側のロジック処理で対話し、セッション管理などの関数を介してサーバー側のロジックを処理します。 1)MySQLIまたはPDOを使用してデータベースに接続し、SQLクエリを実行します。 2)セッション管理およびその他の機能を通じて、HTTPリクエストとユーザーステータスを処理します。 3)トランザクションを使用して、データベース操作の原子性を確保します。 4)SQLインジェクションを防ぎ、例外処理とデバッグの閉鎖接続を使用します。 5)インデックスとキャッシュを通じてパフォーマンスを最適化し、読みやすいコードを書き、エラー処理を実行します。

PHPの目的:動的なWebサイトの構築 PHPの目的:動的なWebサイトの構築 Apr 15, 2025 am 12:18 AM

PHPは動的なWebサイトを構築するために使用され、そのコア関数には次のものが含まれます。1。データベースに接続することにより、動的コンテンツを生成し、リアルタイムでWebページを生成します。 2。ユーザーのインタラクションを処理し、提出をフォームし、入力を確認し、操作に応答します。 3.セッションとユーザー認証を管理して、パーソナライズされたエクスペリエンスを提供します。 4.パフォーマンスを最適化し、ベストプラクティスに従って、ウェブサイトの効率とセキュリティを改善します。

PHPとPythonの選択:ガイド PHPとPythonの選択:ガイド Apr 18, 2025 am 12:24 AM

PHPはWeb開発と迅速なプロトタイピングに適しており、Pythonはデータサイエンスと機械学習に適しています。 1.PHPは、単純な構文と迅速な開発に適した動的なWeb開発に使用されます。 2。Pythonには簡潔な構文があり、複数のフィールドに適しており、強力なライブラリエコシステムがあります。

See all articles