CodeZine(コードジン)

特集ページ一覧

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

PEARライブラリ活用 (10)

  • LINEで送る
  • このエントリーをはてなブックマークに追加
2008/12/17 14:00
目次

字句解析器

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

  1. 字句解析器を定義するファイル(.plex)を作成する。
  2. plexファイルをもとに、PHP_LexerGeneratorで字句解析器のためのクラス(.php)を生成する。

 plexファイルは次のような構造になっています(詳細はパッケージに含まれているサンプル「TestLexer.plex」やPHP_LexerGeneratorのドキュメントを参照してください)。

<?php
class (1)クラス名
{
    (2)lexerが利用する変数のリスト
    (3)コンストラクタ

/*!lex2php
(4)lexerが利用する変数に関する指示のリスト
(5)トークンの表現のリスト
*/

/*!lex2php
(6)トークンに対する処理
*/
};
?>

 (1)は任意です。ここではMyLexerとします。Lexer自体に特殊な処理をさせるのでなければ、(2)から(4)はサンプル「TestLexer.plex」のままで構いません。次のようになります。

 

<?php
class MyLexer
{
    private $data;
    private $N;
    public $token;
    public $value;
    private $line;
    private $state = 1;

    function __construct($data) {
        $this->data = $data;
        $this->N = 0;
        $this->line = 1;
    }

/*!lex2php
%input $this->data
%counter $this->N
%token $this->token
%value $this->value
%line $this->line

 トークンの表現のリスト(5)は次のようになります。トークン表現のリストは、文字列リテラルあるいは正規表現で指定します。正規表現は、@か/で挟む形式で書きます。

[リスト1] mylexer.plex
PLUS = "+"
MINUS = "-"
TIMES = "*"
DIVIDE = "/"
NUMERAL = /[0-9]*\.[0-9]+|[0-9]+/
LPAREN = "("
RPAREN = ")"
WHITESPACE = /[ \t\n]+/

 例えば、+という文字には特別な意味を持たせたいので、PLUSという名前を付けておきます(名前は任意ですが、分かりやすいものをつけてください)。MINUSやTIMES、DIVIDE、LPAREN、,RPARENも同様です。数値(NUMERAL)はもう少し複雑です。「数字の列.数字の列」あるいは「数字の列」(小数点なし)を数値として扱いたいので、上記のような正規表現になります。空白(WHITESPACE)も同様です。

 トークンに対する処理(6)は次のようになります。この段階では、空白(とタブ)の時に何もしないということ以外、特に指定することはありません(後で修正します)。「+」が加算を意味するというようなことは後述する構文解析器のほうで指定します。

[リスト2] mylexer.plex
PLUS {}
MINUS {}
TIMES {}
DIVIDE {}
NUMERAL {}
LPAREN {}
RPAREN {}
WHITESPACE { return false; }

 LexerGeneratorによってplexファイルから字句解析器のクラスを生成します。

[リスト3] test_lexer.php
require_once "PHP/LexerGenerator.php";
new PHP_LexerGenerator('mylexer.plex');

 上のようなコードを実行するとmylexer.phpが生成されます。このファイルで定義されるクラス(ここではMyLexer)には、次のような属性とメソッドがあります。

MyLexerクラスのメンバ
メソッド 概要
MyLexer($str) コンストラクタ。引数は字句解析する文字列。
yylex() 字句解析をして、トークンを一つ取り出すメソッド。
token 字句解析によって切り出したトークンの種類(番号)。
value 切り出したトークン。

 解析したい文字列を与えてインスタンスを生成し、メソッドyylex()でトークンを取り出します。

[リスト4] test_lexer.php
require_once "mylexer.php";
$lexer=new MyLexer('10 + 2.1 * ( 3 + 1 )');//字句解析する文字列を与えてオブジェクトを生成する

while ($lexer->yylex()) {
    echo "[token:{$lexer->token}, value:{$lexer->value}]\n";
}

 実行結果は次のようになります。属性tokenが、先に定義したトークンの順番を表しています。例えば最初(1番目)に定義したのは+でした。

php test_lexer.php
(略)
[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:)]

  • LINEで送る
  • このエントリーをはてなブックマークに追加

バックナンバー

連載:PEARライブラリ活用

もっと読む

著者プロフィール

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

    静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for ASP/ASP.NET。執筆コミュニティ「WINGSプロジェクト」代表。 主な著書に「入門シリーズ(サーバサイドAjax/XM...

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

    <WINGSプロジェクトについて> 有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。2018年11月時点での登録メンバは55名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂...

あなたにオススメ

All contents copyright © 2005-2021 Shoeisha Co., Ltd. All rights reserved. ver.1.5