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}? { // { $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についての本をかったので、届くの待ち中です。