SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

PEARライブラリ活用

PHP_LexerGeneratorとPHP_ParserGeneratorを利用して
PHPで独自の言語を実装する方法

PEARライブラリ活用 (10)

構文解析器

 構文解析器は次のような手順で作成します。

  1. 構文解析器を定義するファイル(.y)を作成する。
  2. コマンドphplemon.batで構文解析器のためのクラス(.php)を生成する。

構文解析器の定義ファイルの作成

 手順1のファイル(.y)の形式は次のとおりです。PHP_ParserGeneratorはLemon ParserというC言語用の構文解析器生成プログラムをPHPに移植したものなので、.yファイルの形式についての詳細は、Lemon Parserのマニュアルを参照してください。

%declare_class { class (1)構文解析器のクラス名 }

(2)トークンのリスト

%syntax_error {  (3)エラーを表示するための手続き }

(4)プログラムの構文規則

(1)構文解析器のクラス名

 ここでは、構文解析器のクラス名はMyParserとします。

(2)トークンのリスト

 トークンのリストは先に字句解析器を生成した際と同じものを指定します。下に書いたものの優先度が高くなることに注意してください(例えば、加算(PLUS)より乗算(TIMES)の優先度が高くなります)。

(3)エラーを表示するための手続き

 エラーを表示するための手続きは「echo "SYNTAX ERROR!\n";」でいいでしょう。

(4)プログラムの構文規則

 プログラムの構文規則は次のようになります。

[リスト5] myparser.y
program ::= expr(A).{ echo "ANS.:".A."\n"; }

expr(A) ::= expr(B) PLUS expr(C). { A = B + C; }
expr(A) ::= expr(B) MINUS expr(C). { A = B - C; }
expr(A) ::= expr(B) TIMES expr(C). { A = B * C; }
expr(A) ::= expr(B) DIVIDE expr(C). {
    if (C != 0) A = B / C;
    else echo "DIVIDE BY ZERO!\n";
}
expr(A) ::= LPAREN expr(B) RPAREN. { A = B; }
expr(A) ::= NUMERAL(B). { A = B; }

 これらの構文規則は、次のようなことを意味しています。

  • プログラム(program)は式(expr)である
  • 「expr(A) ::= expr(B) PLUS expr(C). { A = B + C; }」は、「表現(B) PLUS 表現(C)という構文があったとき、実際に行われる処理はB+Cである」ことを表している。他も同様(LPARENは'('、RPARENは')'を表す(後で対応付ける)

 実際に行われる処理をPHPで書くため、C言語を利用する場合に比べて早くプロトタイプを作れることが期待されます。

 構文規則の組によって言語を定義するというのは、言語処理においてよく行われることで、厳密な理論的背景があります。参考文献(2)のようなコンパイラの教科書を参照してください。

構文解析器クラスの生成

 構文解析器のためのファイル(.y)ができたら、コマンドphplemon.batを使って構文解析器のクラスを生成します。

phplemon.bat myparser.y

 これによってmyparser.phpというファイルが生成されます。このファイルで定義されるクラスMyParserは、次のような定数を持ちます。

  • MyParser::PLUS
  • MyParser::MINUS
  • MyParser::TIMES
  • MyParser::DIVIDE
  • MyParser::NUMERAL
  • MyParser::LPAREN
  • MyParser::RPAREN

 作成した構文解析器で、「15/5」を構文解析してみましょう。この文字列は「15, /, 5」に分解することがでますが、これらは順にMyParser::NUMERAL、MyParser::DIVIDE、MyParser::NUMERALに相当します。これらトークンの種類と値を構文解析器に与えて処理します(DIVIDEの値は不要ですが、そのような場合には値を0としておきます)。入力の終わりにdoParse(0,0)が必要です。

[リスト6] test_parser.php
require_once "myparser.php";
$parser = new MyParser();
$parser->doParse(MyParser::NUMERAL,15);
$parser->doParse(MyParser::DIVIDE,0);
$parser->doParse(MyParser::NUMERAL,5);
$parser->doParse(0, 0);

 実行結果は次のようになります。

php test_parser.php
ANS.:3

次のページ
字句解析器と構文解析器

この記事は参考になりましたか?

PEARライブラリ活用連載記事一覧

もっと読む

この記事の著者

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

WINGSプロジェクト 矢吹 太朗(ヤブキ タロウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/3319 2008/12/17 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー