Mais conteúdo relacionado
詳説ぺちぺち
- 2. do_aki (どぅーあき)
• |所属| > 株式会社もしも
(ドロップシッピング・アフィリエイトASP)
• |仕事| > インフラ(サーバ管理)兼
Webアプリケーション開発
• |出現| > 渋谷・山手線沿線
• |特性| > PHPer
http://do-aki.net/
- 3. あじぇんだ
• 第1章 ぺちぺち
• 第2章 Scanner (字句解析器)
• 第3章 Parser (構文解析器)
• まとめ
- 8. <?php
function HelloPHP() {
echo "Hello PHP World";
}
HelloPHP(); PHP
ぺちぺち
関数 はろーぺちぺち() ここから
「"はろー ぺちぺち わーるど"」と表示;
ここまで
ぺちぺち
はろーぺちぺち();
- 11. 変数/条件/演算子
変数:ほげ は 0 です
1 が 2 より小さい (1<2)
1 が 2 より大きい (1>2)
1 足す 2 (1+2)
10 を 3 で割った余り (10%3)
- 12. 組み合わせると
ぺちぺち
変数:ほげ は 1です;
繰り返し 変数:ほげ が 10 以下 の間
ここから
もし 変数:ほげ を 3 で割った余り が 0 に等しい
ならば
「 “アホn"」と表示;
そうでないならば
「 変数:ほげ,"n"」と表示;
条件おわり
変数:ほげ に 変数:ほげ 足す 1 を代入;
ここまで
- 13. ぺちぺち と PHP の違い
・Zend/zend_language_scanner.l
add 98 lines & modify 22 lines
・Zend/zend_language_parser.y
add 65 lines & modify 1 line
- 15. スキャナの状態
zend_language_scanner.l
の半分から下あたり
<ST_IN_SCRIPTING>"function" {
return T_FUNCTION;
} この文字列
このトークンを
返す が来たら
<ST_IN_SCRIPTING>“{“ {
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return '{';
}
- 16. スキャナの状態
zend_language_scanner.l
の半分から下あたり
<ST_IN_SCRIPTING>“def" {
return T_FUNCTION;
} この文字列
このトークンを
<?php返す が来たら
<ST_IN_SCRIPTING>“{“ { の代わりに def
function
def hello() {
echo “like ruby?”;
yy_push_state(ST_IN_SCRIPTING TSRMLS_CC);
return '{'; なんちゃって ruby のでき
}
} あがり
- 18. スキャナの状態
• INITIAL
• ST_IN_SCRIPTING
• ST_LOOKING_FOR_PROPERTY
• ST_LOOKING_FOR_VARNAME
• ST_VAR_OFFSET
• ST_DOUBLE_QUOTES
• ST_BACKQUOTE
• ST_HEREDOC
• ST_NOWDOC
• ST_END_HEREDOC
- 19. ほとんどはこの状態
スキャナの状態
• INITIAL 初期状態
• ST_IN_SCRIPTING 基本状態
• ST_LOOKING_FOR_PROPERTY ->これ
• ST_LOOKING_FOR_VARNAME ${ これ}
• ST_VAR_OFFSET $xxx[これ]
• ST_DOUBLE_QUOTES “これ”
• ST_BACKQUOTE `これ`
• ST_HEREDOC <<<“DOC” の後
• ST_NOWDOC <<<‘DOC’ の後
• ST_END_HEREDOC DOC の終わり
- 22. 落とし穴
• “変数”の扱いは少し複雑
– 3カ所 + 隠し1カ所 (Parser 側からのみ参照)
• 複雑な処理をしているところも
– HEREDOC , NOWDOC
– __CLASS__
• 簡単にセグる
- 23. <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES
,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>
"$"{LABEL} {
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES
,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>
(“$“|”変数:”){LABEL} {
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
}
return T_VARIABLE;
NG
- 24. <ST_IN_SCRIPTING,ST_DOUBLE_QUOTES
,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>
"$"{LABEL} {
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
zendlval->type = IS_STRING;
return T_VARIABLE;
} 変数名をコ
ピーして保持
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES
,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>
”変数:” {LABEL} {
zend_copy_value(zendlval, (yytext+7), (yyleng-7));
zendlval->type = IS_STRING;
return T_VARIABLE;
}
- 25. 第2章 Scanner まとめ
• 元々あるキーワードの変更/追加は簡単
• スキャナの状態もほとんど意識する必要
はない
• ところどころ Cで無理矢理処理してる部分
があるので注意
- 29. Syntax Error
T_LNUMBER
‘=’
1 = $a; T_VARIABLE
‘;‘
Perser にトークンの並びが定義さ
れていない
- 30. zend_language_parser.y
ルール名
fully_qualified_class_name:
namespace_name { $$ = $1; }
| T_NAMESPACE T_NS_SEPARATOR namespace_name {
$$.op_type = IS_CONST;
ZVAL_EMPTY_STRING(&$$.u.constant);
zend_do_build_namespace_name(&$$, &$$, &$3 TSRMLS_CC); }
| T_NS_SEPARATOR namespace_name {
char *tmp = estrndup(Z_STRVAL($2.u.constant),
…(省略) }
;
トークンの 処理(C言語+α)
並び
- 33. T_VARIABLE
$a + 1 ‘+’
T_LNUMBER
expr '+' expr { zend_do_binary_op(ZEND_ADD, &$$, &
$1, &$3 TSRMLS_CC); }
New!
T_VARIABLE
$a 足す 1 T_JA_PLUS
T_LNUMBER
expr T_JA_PLUS expr { zend_do_binary_op(ZEND_A
DD, &$$, &$1, &$3 TSRMLS_CC); }
- 34. IF 文
T_IF '(' expr ')' { zend_do_if_cond(&$3, &$4); }
statement { zend_do_if_after_statement(&$4, 1); }
elseif_list else_single { zend_do_if_end(); }
else_single:
/* empty */
| T_ELSE statement
PHP
T_JA_IF expr T_NARABA { zend_do_if_cond(&$2, &$3); }
inner_statement_list { zend_do_if_after_statement(&$3, 1); }
ja_else_single T_OWARI { zend_do_if_end(); }
ja_else_single:
/* empty */ ぺちぺち
| T_JA_ELSE inner_statement_list
- 35. 落とし穴
• 突然現れる ‘$’
– Scanner で T_VARIABLE として処理されてな
い!?
• 本気でやるなら opecode / ZendAPI の知識
が必須
• コンパイルしてみないと分からない
- 41. 改造のお供に
• GNU GLOBAL
(http://www.gnu.org/software/global/)
– 静的にソースコードを解析するのに便利!
– PHP のソースを展開したディレクトリで
htags -Ffgnasv
– CGI 使えれば検索も可能