1 時間の表現言語
このブログ投稿は、元の形式で表示するのが最適です。
この投稿は、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 1
や 1 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 bar
はBinaryOp(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
- コードは反復ごとに変更されます。
- より具体的には、式言語インタープリタ。
- PHP では文字列と呼ばれることがよくあります。
- ドメイン固有の言語
- 特許は存在しません。
- トークナイザーは構文の強調表示に役立ちます。
-
preg_
メソッドの方がパフォーマンスが高い可能性があります。 - 異なる答えが期待されていた場合のみ、間違っています。
- ツリートラバーサルは、Doctrine のクエリビルダーを通じて発見されました。
以上が1 時間の表現言語の詳細内容です。詳細については、PHP 中国語 Web サイトの他の関連記事を参照してください。

ホットAIツール

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

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

Undress AI Tool
脱衣画像を無料で

Clothoff.io
AI衣類リムーバー

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

人気の記事

ホットツール

メモ帳++7.3.1
使いやすく無料のコードエディター

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

ゼンドスタジオ 13.0.1
強力な PHP 統合開発環境

ドリームウィーバー CS6
ビジュアル Web 開発ツール

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

ホットトピック











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

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

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

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

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

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

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

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