SHOEISHA iD

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

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

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

PEARライブラリ活用

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

PEARライブラリ活用 (10)

字句解析器と構文解析器

 前節の最後の例では「15/5」を手でトークンに分けてから構文解析器にかけましたが、トークンに分ける作業は本来字句解析器の仕事です。字句解析器と構文解析器は連携して使えるようにしなければなりません。

 字句解析器の出力を構文解析器の入力として使えるようにするために、先に作成した字句解析器(MyLexer)を修正したMyLexer2を作ります。修正点は次の2点です。

  • 字句解析器の定義ファイル(plex)で「require_once "myparser.php";」として、字句解析器が構文解析器を参照できるようにする
  • 構文解析器のトークンと構文解析器のそれとを一致させる

 2番目の修正を施すと、mylexer2.plexは次のようになります。

[リスト7] mylexer2.plex
<?php
require_once "myparser.php";

class MyLexer2

(略)

/*!lex2php
PLUS { $this->token = MyParser::PLUS; }
MINUS { $this->token = MyParser::MINUS; }
TIMES { $this->token = MyParser::TIMES; }
DIVIDE { $this->token = MyParser::DIVIDE; }
NUMERAL { $this->token = MyParser::NUMERAL; }
LPAREN { $this->token = MyParser::LPAREN; }
RPAREN { $this->token = MyParser::RPAREN; }
WHITESPACE { return false; }
*/
};
?>

 字句解析器と構文解析器は次のように組み合わせて使います。

 与えられた文字列を本稿で作成した字句解析・構文解析器で処理し、結果を表示する関数doTest()を用意します。同じ文字列をPHPの関数eval()で処理した結果も並べて表示させましょう。

[リスト8] test_lexer_parser.php
//Parserの読み込み・生成
require_once "myparser.php";
$parser = new MyParser();

//Lexerの準備
require_once "PHP/LexerGenerator.php";
new PHP_LexerGenerator('mylexer2.plex');
require_once "mylexer2.php";

//与えられた文字列を処理する関数
function doTest($str) {
    echo "$str \n";
    global $parser;
    $lexer=new MyLexer2($str);
    while ($lexer->yylex()) {//字句解析の結果を構文解析器に渡す
        $parser->doParse($lexer->token, $lexer->value);
    }
    $parser->doParse(0, 0);
    
    //PHPの関数evalで結果を確認
    echo 'EVAL:';
    eval('echo '.$str.';');
    echo "\n\n";
}

//テスト
doTest('10 + 2.1 * ( 3 + 1 )');
doTest('10 + ( 2.1 / 0.5 ) * ( 3 + 1 )');
doTest('10 + ( 2.1 / ( 0.5 + 0.5 ) ) * ( 3 + 1 )');
doTest('10 + + 1');

 実行結果は次のようになり、正しく処理されていることが分かります(「10 + + 1」はここで作成した簡易電卓では処理できません。エラーが発生すべき場所で「SYNTAX ERROR!」と表示されています)。

php test_lexer_parser.php
(略)
10 + 2.1 * ( 3 + 1 )
[token:5, value:10]
[token:1, value:+]
[token:5, value:2.1]
[token:3, value:*]
[token:6, value:(]
[token:5, value:3]
[token:1, value:+]
[token:5, value:1]
[token:7, value:)]
ANS.:18.4
EVAL:18.4

10 + ( 2.1 / 0.5 ) * ( 3 + 1 )
(略)
ANS.:26.8
EVAL:26.8

10 + ( 2.1 / ( 0.5 + 0.5 ) ) * ( 3 + 1 )
(略)
ANS.:18.4
EVAL:18.4

10 + + 1
[token:5, value:10]
[token:1, value:+]
[token:1, value:+]
SYNTAX ERROR!
[token:5, value:1]
ANS.:1
EVAL:11

おわりに

 簡易電卓を作るという例を通じて、PHPで字句解析と構文解析する方法を紹介しました。ここで作成した簡易電卓は本当に簡易的なものですが、PHP上で新しい言語を実装するという技術は、さまざまなところで応用できるでしょう。より高度な電卓を作りたい場合には、参考文献(3)を参照してください。lexやyaccを用いて変数や関数の導入する方法が紹介されています(本稿で紹介したのは、この文献で紹介した電卓の、最も最初のバージョンに相当します)。

 10回にわたるこの連載では、PEARのパッケージの中から、特に基本的だと思われるものを中心に紹介してきました。紹介したパッケージの多くは開発途中のものなので、目的は同じで使い方も同じものがいくつもあって混乱したり、ドキュメントが不十分なために使い方がよく分からなかったり、他の言語の対応物に比べて機能や性能が劣っているためにがっかりすることもありましたが、それらをある程度整理して、使える形で紹介することができたのではないかと思っています。個々の解説記事をそのまま役立ててもらいたいのはもちろんですが、連載の全体が、PHPというプラットフォームを選択するかどうかを判断する一つの材料になれば幸いです。

参考文献

  1. プログラミング言語C++』 Bjarne Stroustrup著、長尾高弘 訳、アジソンウェスレイパブリッシャーズジャパン、1998年12月
  2. コンパイラ入門』 山下義行 著、サイエンス社、2008年07月
  3. UNIXプログラミング環境』 Brian W. Kernighan・Rob Pike 著、Prentice Hall Ptr、石田晴久 訳、アスキー、1985年09月

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

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
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」など、さまざまなカンファレンスを企画・運営しています。

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

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

メールバックナンバー