43
詳詳詳詳詳詳 詳 PHP 詳詳詳 + PHP 詳詳詳詳詳詳詳詳詳詳詳詳詳詳詳詳詳詳 2012/01/28 do_aki

詳説ぺちぺち

  • Upload
    doaki

  • View
    1.004

  • Download
    1

Embed Size (px)

DESCRIPTION

 

Citation preview

Page 1: 詳説ぺちぺち

詳説ぺちぺち闇 PHP 勉強会 + PHP ソースコードリー

ディングワークショップ2012/01/28

do_aki

Page 2: 詳説ぺちぺち

do_aki ( どぅーあき )

• | 所属 | > 株式会社もしも    (ドロップシッピング・アフィリエイト ASP )

• | 仕事 | > インフラ(サーバ管理)兼   Web アプリケーション開発

• | 出現 | > 渋谷・山手線沿線• | 特性 | > PHPer

http://do-aki.net/

Page 3: 詳説ぺちぺち

あじぇんだ

• 第 1 章 ぺちぺち• 第 2 章  Scanner ( 字句解析器 )• 第 3 章  Parser ( 構文解析器 )• まとめ

Page 4: 詳説ぺちぺち

第 1 章ぺちぺち

Page 5: 詳説ぺちぺち

Japanese Programming Language

らきすた風 画像生成 (ジェネレーター) http://raki.st/

Page 6: 詳説ぺちぺち

闇鍋的P H P魔改造

2011/09/10 PHP カンファレンス 2011Presented By do_aki

Page 7: 詳説ぺちぺち

PHP の言語そのものの作りとかよく知らないし、内部構造もよく分からないけど、オレオレ PHP を

作ってみたくてトライ&エラー繰り返していたら気づいたら PHP を基にした日本語プログラミング言語ができちゃってたから発表して

みたよ!・・・というもの

Page 8: 詳説ぺちぺち

<?php function HelloPHP() { echo "Hello PHP World"; } HelloPHP(); PHP

ぺちぺち 関数 はろーぺちぺち () ここから 「 " はろー ぺちぺち わーるど " 」と表示 ; ここまで

はろーぺちぺち ();

ぺちぺち

Page 9: 詳説ぺちぺち

条件分岐

もし [ 条件 ] ならば…

 そうでないならば…

条件おわり

Page 10: 詳説ぺちぺち

繰り返し

繰り返し [ 条件 ] の間ここから

…ここまで

Page 11: 詳説ぺちぺち

変数 / 条件 / 演算子

変数 : ほげ は 0 です

1 が 2 より小さい (1<2)1 が 2 より大きい (1>2)

1 足す 2 (1+2)10 を 3 で割った余り (10%3)

Page 12: 詳説ぺちぺち

組み合わせるとぺちぺち変数 : ほげ は 1 です ;

繰り返し 変数 : ほげ が 10 以下 の間ここから もし 変数 : ほげ を 3 で割った余り が 0 に等しい ならば

「 “アホ \n" 」と表示 ; そうでないならば

「 変数 : ほげ ,"\n" 」と表示 ; 条件おわり 変数 : ほげ に 変数 : ほげ 足す 1 を代入 ;ここまで

Page 13: 詳説ぺちぺち

ぺちぺち と PHP の違い

add 98 lines & modify 22 lines

・ Zend/zend_language_scanner.l

・ Zend/zend_language_parser.y

add 65 lines & modify 1 line

Page 14: 詳説ぺちぺち

第 2 章Scanner

Page 15: 詳説ぺちぺち

<ST_IN_SCRIPTING>"function" { return T_FUNCTION;}

<ST_IN_SCRIPTING>“{“ { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{';}

zend_language_scanner.lの半分から下あたり

スキャナの状態

この文字列が来たら

このトークンを返す

Page 16: 詳説ぺちぺち

<ST_IN_SCRIPTING>“def" { return T_FUNCTION;}

<ST_IN_SCRIPTING>“{“ { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{';}

zend_language_scanner.lの半分から下あたり

function の代わりに def

なんちゃって ruby のできあがり

スキャナの状態

この文字列が来たら

このトークンを返す<?php

def hello() { echo “like ruby?”; }

Page 17: 詳説ぺちぺち

<ST_IN_SCRIPTING>"function" { return T_FUNCTION;}

<ST_IN_SCRIPTING>“{“ { yy_push_state(ST_IN_SCRIPTING TSRMLS_CC); return '{';}

ぺちぺちでは

<ST_IN_SCRIPTING>“{“|” ここから” {

<ST_IN_SCRIPTING>“function“|” 関数” {

Page 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

全部で10 の状

態を持つ

Page 19: 詳説ぺちぺち

スキャナの状態• 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

初期状態基本状態-> これ${ これ }$xxx[ これ ]“ これ”` これ `<<<“DOC” の後<<<‘DOC’ の後DOC の終わり

ほとんどはこの状態

Page 20: 詳説ぺちぺち

ぺちぺち動かず

ぺちぺちecho "petipeti!\n";

ぺちぺちecho "petipeti!\n";

OK

NG

Page 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} ???

Page 22: 詳説ぺちぺち

落とし穴• “ 変数”の扱いは少し複雑– 3 カ所 + 隠し 1 カ所 (Parser 側から

のみ参照 )

• 複雑な処理をしているところも– HEREDOC , NOWDOC– __CLASS__

• 簡単にセグる

Page 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

Page 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; }

変数名をコピーして保持

Page 25: 詳説ぺちぺち

第 2 章 Scanner まとめ• 元々あるキーワードの変更 / 追加は簡単

• スキャナの状態もほとんど意識する必要はない

• ところどころ C で無理矢理処理してる部分があるので注意

Page 26: 詳説ぺちぺち

第 2 章 Scanner

Page 27: 詳説ぺちぺち

第 3 章Parser

Page 28: 詳説ぺちぺち

Scanner によるトークンへの分解

T_OPEN_TAGT_VARIABLE ‘=‘ T_VARIABLE‘+’T_LNUMBER‘;’T_INCT_VARIABLE‘;’

<?php$x = $a +

1;++$x;

Page 29: 詳説ぺちぺち

Syntax Error

T_LNUMBER‘=’T_VARIABLE ‘;‘

1 = $a;

Perser にトークンの並びが定義されていない

Page 30: 詳説ぺちぺち

zend_language_parser.yfully_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 言語+α)

トークンの並び

Page 31: 詳説ぺちぺち

zend_language_parser.y

拡張するために新たにルールを作る

処理をどう書けばいいのか分からない  orz

BAD

Page 32: 詳説ぺちぺち

似ているルールを真似る

Page 33: 詳説ぺちぺち

T_VARIABLE‘+’T_LNUMBER

$a + 1

T_VARIABLET_JA_PLUST_LNUMBER

$a 足す 1

expr '+' expr   { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }

expr T_JA_PLUS expr   { zend_do_binary_op(ZEND_ADD, &$$, &$1, &$3 TSRMLS_CC); }

New!

Page 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 statementT_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

ぺちぺち

PHP

Page 35: 詳説ぺちぺち

落とし穴• 突然現れる ‘ $’ – Scanner で T_VARIABLE として処理され

てない! ?

• 本気でやるなら opecode / ZendAPI の知識が必須

• コンパイルしてみないと分からない

Page 36: 詳説ぺちぺち

Parser は 複雑なパズル

解きやすくするツール・方法あったら教えてほしいなー

Page 37: 詳説ぺちぺち

第 3 章 Parser

Page 38: 詳説ぺちぺち

まとめ

Page 39: 詳説ぺちぺち

Php をいじり倒す 10 の方法 (2009) http://www.slideshare.net/moriyoshi/php10

Page 40: 詳説ぺちぺち

言いたかったこと• オレオレ PHP 作るの難しくないよ!• 拡張作るのも良いけど、言語そのものに

コミットメントしてもいいんじゃないかな

• PHP を楽しむ人が増えて、 PHP がより一層面白いものになってくれたらいいな

Page 41: 詳説ぺちぺち

改造のお供に• GNU GLOBAL (

http://www.gnu.org/software/global/)– 静的にソースコードを解析するのに便利!– PHP のソースを展開したディレクトリで

– CGI 使えれば検索も可能

htags -Ffgnasv

Page 42: 詳説ぺちぺち

最後に• ぺちぺちは github においてあります• http://git.io/petipeti

Fork me

!

Page 43: 詳説ぺちぺち

ありがとうございました• 質疑応答?