読者です 読者をやめる 読者になる 読者になる

phpLexのTokenizer.lexファイル構造について

作成したTokenizer.phpの差分 - maru.cc@はてな」の続き


phpLexの記述方法について、Web上を探したのですが、それらしい情報が見つかりません。
それどころか、「phpLex」でぐぐったらこのサイトが1番目に出てしまいました。わからないという内容なのに。


以下から落としてきた、Flexy用の.lexファイルと、phpLexのソースファイル自体を参考に記述内容を調査してみました。
http://cvs.php.net/viewvc.cgi/pear/HTML_Template_Flexy/Flexy/Tokenizer.lex
あと、Wikipediaのlexの項目も参考にしています。
http://ja.wikipedia.org/wiki/Lex


調べた限りの大枠です。

<?php
  <phpのヘッダやコメント等..(1)

%% <区切り..(2)
%namespace (namespace)  <なんかいろいろ宣言..(3)
%public
%class (クラス名)

%{
  <ここにクラス内のプロパティ宣言やメソッド等..(4)
%}

%line <またまた宣言..(5)
%full
%char
%state IN_SINGLEQUOTE <ここに以降で使用するらしき文字列..(6)

DIGIT   =       [0-9] <使用する文字列などの宣言かな?..(7)
LCLETTER =  [a-z]
UCLETTER =  [A-Z]

%% <区切り..(8)


  <以降宣言がわらわら..(9)

(1)phpのヘッダやコメント等

phpファイルになったときの、コメントやdefineによる定数の宣言などが書かれていました。

define('HTML_TEMPLATE_FLEXY_TOKEN_NONE',1);
define('HTML_TEMPLATE_FLEXY_TOKEN_OK',2);
define('HTML_TEMPLATE_FLEXY_TOKEN_ERROR',3);

define("YYINITIAL"     ,0);
define("IN_SINGLEQUOTE"     ,   1) ;
define("IN_TAG"     ,           2)  ;
define("IN_ATTR"     ,          3);
define("IN_ATTRVAL"     ,       4) ;
define("IN_NETDATA"     ,       5);
define("IN_ENDTAG"     ,        6);
define("IN_DOUBLEQUOTE"     ,   7);
define("IN_MD"     ,            8);
define("IN_COM"     ,           9);
define("IN_DS",                 10);
define("IN_FLEXYMETHOD"     ,   11);
define("IN_FLEXYMETHODQUOTED"  ,12);
define("IN_FLEXYMETHODQUOTED_END" ,13);
define("IN_SCRIPT",             14);
define("IN_CDATA"     ,         15);
define("IN_DSCOM",              16);
define("IN_PHP",                17);
define("IN_COMSTYLE"     ,      18);

こんな感じ。
それぞれ意味がありそうですが、後で調べます。

(2)区切り

パーセント2つで各ブロックの区切りをしているようです。

(3)なんかいろいろ宣言

namespaceやクラス名などの宣言が、先頭パーセントに続く文字列で宣言がありました。
どんな宣言があるのか、phpLexのソース内を検索してみたところ、Gen.csファイル内にそれらしい宣言がありました。

http://php-sharp.cvs.sourceforge.net/php-sharp/phpLex/Gen.cs?view=markup
340行目あたりから

/*
 * Member Variables: Lex directives.
 */
private String state_dir = "%state";
private String char_dir = "%char";
private String line_dir = "%line";
private String class_dir = "%class";
private String implements_dir = "%implements";
private String function_dir = "%function";
private String type_dir = "%type";
private String integer_dir = "%integer";
private String intwrap_dir = "%intwrap";
private String full_dir = "%full";
private String unicode_dir = "%unicode";
private String ignorecase_dir = "%ignorecase";
private String init_code_dir = "%init{";
private String init_code_end_dir = "%init}";
private String eof_code_dir = "%eof{";
private String eof_code_end_dir = "%eof}";
private String eof_value_code_dir = "%eofval{";
private String eof_value_code_end_dir = "%eofval}";
private String class_code_dir = "%{";
private String class_code_end_dir = "%}";
private String yyeof_dir = "%yyeof";
private String public_dir = "%public";
private String namespace_dir = "%namespace";
private String ignore_token = "%ignore_token";

それぞれの意味はまだ不明なものもありますが、同じく後で調べます。
とりあえず、%classは、phpファイルになった時のクラス名になるようです。

(4)ここにクラス内のプロパティ宣言やメソッド等

「%{」「%}」で囲われた範囲に書いた文字列は、生成後のクラス内にそのまま書き出されます。
先頭にスペースを入れてインデントしておかないとエラーになる場合があるようです。

(5)またまた宣言

また、パーセントで始まる宣言があります。
内容は(3)で書いたもののいくつかがあるようです。
もしかしたら、(3)にまとめて書いてもいいのかもしれませんが、(4)より下に書くことに意味があるのでしょうか?
Flexyの場合の単なる記述の違いかもしれません。

(6)ここに以降で使用するらしき文字列

%state には特別な意味があるようで、(9)以降で使用するタグ(?)のようなものの宣言みたいです。
意味や使い方はまだ不明です。

(7)使用する文字列などの宣言かな?

(9)以降で使用する文字列の宣言のようです。
眺めればなんとなく意味がわかります。

数字や文字単体の宣言と

DIGIT   =   [0-9]
LCLETTER =  [a-z]
UCLETTER =  [A-Z]

組み合わせがあるようです。

NUMBER                  = {DIGIT}+
NUMBER_TOKEN            = {DIGIT}+{NAME_CHARACTER}*

(8)区切り

(2)と同じく区切り文字です。

(9)以降宣言がわらわら

おそらく、lexの真髄だと思われる宣言部分。
FlexyのTokenlzer.lexでは以下のような宣言がありました。
抜粋

<YYINITIAL>{CRO}{NUMBER}{REFERENCE_END}?     {
    // &#123;
    $this->value = $this->createToken('Text');
    return HTML_TEMPLATE_FLEXY_TOKEN_OK;
}
<YYINITIAL>{CRO}{NAME}{REFERENCE_END}?      {
    // &#abc;
    $this->value = $this->createToken('Text');
    return HTML_TEMPLATE_FLEXY_TOKEN_OK;
}

いろいろ記述するパターンがありそうですが、まだよくわかりません。

とりあえず

ざっくり大まかな構成は、はずしてはいないと思いますが、なにぶん試行錯誤なので間違えているところもあると思います。
何か勘違いとかあれば、ぜひ指摘をお願いします。


lex/yaccについての本をかったので、届くの待ち中です。