Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

詳説ぺちぺち

1,713 views

Published on

Published in: Technology
  • Be the first to comment

詳説ぺちぺち

  1. 1. 詳説ぺちぺち 闇PHP勉強会 + PHPソースコード リーディングワークショップ 2012/01/28 do_aki
  2. 2. do_aki (どぅーあき)• |所属| > 株式会社もしも (ドロップシッピング・アフィリエイトASP)• |仕事| > インフラ(サーバ管理)兼 Webアプリケーション開発• |出現| > 渋谷・山手線沿線• |特性| > PHPer http://do-aki.net/
  3. 3. あじぇんだ• 第1章 ぺちぺち• 第2章 Scanner (字句解析器)• 第3章 Parser (構文解析器)• まとめ
  4. 4. 第1章ぺちぺち
  5. 5. Japanese Programming Language らきすた風 画像生成 (ジェネレーター) http://raki.st/
  6. 6. 闇鍋的PHP魔改造 2011/09/10 PHPカンファレンス2011 Presented By do_aki
  7. 7. PHPの言語そのものの作りとかよく 知らないし、内部構造もよく分からないけど、オレオレPHPを作って みたくてトライ&エラー繰り返していたら気づいたらPHPを基にした 日本語プログラミング言語ができ ちゃってたから発表してみたよ! ・・・というもの
  8. 8. <?php function HelloPHP() { echo "Hello PHP World"; } HelloPHP(); PHPぺちぺち 関数 はろーぺちぺち() ここから 「"はろー ぺちぺち わーるど"」と表示; ここまで ぺちぺち はろーぺちぺち();
  9. 9. 条件分岐もし [条件] ならば … そうでないならば …条件おわり
  10. 10. 繰り返し繰り返し [条件] の間ここから …ここまで
  11. 11. 変数/条件/演算子変数:ほげ は 0 です1 が 2 より小さい (1<2)1 が 2 より大きい (1>2)1 足す 2 (1+2)10 を 3 で割った余り (10%3)
  12. 12. 組み合わせるとぺちぺち変数:ほげ は 1です;繰り返し 変数:ほげ が 10 以下 の間ここから もし 変数:ほげ を 3 で割った余り が 0 に等しい ならば 「 “アホn"」と表示; そうでないならば 「 変数:ほげ,"n"」と表示; 条件おわり 変数:ほげ に 変数:ほげ 足す 1 を代入;ここまで
  13. 13. ぺちぺち と PHP の違い・Zend/zend_language_scanner.l add 98 lines & modify 22 lines・Zend/zend_language_parser.y add 65 lines & modify 1 line
  14. 14. 第2章Scanner
  15. 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. 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 のでき }} あがり
  17. 17. ぺちぺちでは<ST_IN_SCRIPTING>“function“|”関数” {<ST_IN_SCRIPTING>"function" { return T_FUNCTION;}<ST_IN_SCRIPTING>“{“ { ここから” {<ST_IN_SCRIPTING>“{“|” yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return {;}
  18. 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. 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 の終わり
  20. 20. ぺちぺち動かずぺちぺち echo "petipeti!n"; OKぺちぺち NG echo "petipeti!n";
  21. 21. <INITIAL>"<?php"([ t]|{NEWLINE})<INITIAL>("<?php"|"ぺちぺち")([ t]|{NEWLINE}) {<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"){NEWLINE}? {<ST_IN_SCRIPTING>("?>"|"</script"{WHITESPACE}*">"|"ぺちぺちおしまい"){NEWLINE}? { これだけじゃ足りない orz <INITIAL>{ANY_CHAR} ???
  22. 22. 落とし穴• “変数”の扱いは少し複雑 – 3カ所 + 隠し1カ所 (Parser 側からのみ参照)• 複雑な処理をしているところも – HEREDOC , NOWDOC – __CLASS__• 簡単にセグる
  23. 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. 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. 25. 第2章 Scanner まとめ• 元々あるキーワードの変更/追加は簡単• スキャナの状態もほとんど意識する必要 はない• ところどころ Cで無理矢理処理してる部分 があるので注意
  26. 26. 第2章Scanner 完
  27. 27. 第3章Parser
  28. 28. Scanner によるトークンへの分解<?php T_OPEN_TAG T_VARIABLE $x = $a + 1; ‘=‘ ++$x; T_VARIABLE ‘+’ T_LNUMBER ‘;’ T_INC T_VARIABLE ‘;’
  29. 29. Syntax Error T_LNUMBER ‘=’1 = $a; T_VARIABLE ‘;‘Perser にトークンの並びが定義さ れていない
  30. 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言語+α) 並び
  31. 31. zend_language_parser.y 拡張するために 新たにルールを作る BAD 処理をどう書けばいいのか分 からない orz
  32. 32. 似ているルールを真似る
  33. 33. T_VARIABLE $a + 1 ‘+’ T_LNUMBERexpr + expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); } New! T_VARIABLE $a 足す 1 T_JA_PLUS T_LNUMBERexpr T_JA_PLUS expr { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }
  34. 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 PHPT_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. 35. 落とし穴• 突然現れる ‘$’ – Scanner で T_VARIABLE として処理されてな い!?• 本気でやるなら opecode / ZendAPI の知識 が必須• コンパイルしてみないと分からない
  36. 36. Parser は 複雑なパズル 解きやすくするツール・方法あったら教えてほしいなー
  37. 37. 第3章 Parser 完
  38. 38. まとめ
  39. 39. Phpをいじり倒す10の方法 (2009) http://www.slideshare.net/moriyoshi/php10
  40. 40. 言いたかったこと• オレオレPHP作るの難しくないよ!• 拡張作るのも良いけど、言語そのものに コミットメントしてもいいんじゃないか な• PHPを楽しむ人が増えて、PHP がより一層 面白いものになってくれたらいいな
  41. 41. 改造のお供に• GNU GLOBAL (http://www.gnu.org/software/global/) – 静的にソースコードを解析するのに便利! – PHP のソースを展開したディレクトリで htags -Ffgnasv – CGI 使えれば検索も可能
  42. 42. 最後に• ぺちぺちは github においてあります• http://git.io/petipeti
  43. 43. ありがとうございました• 質疑応答?

×