Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Let's Take a Peek at PHP Parser 5.x!
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
inouehi
March 16, 2025
Programming
0
280
Let's Take a Peek at PHP Parser 5.x!
『5系になったPHP Parserをのぞいてみよう!』
PHPerKaigi 2025
2025-03-23 15:20〜 Track A
https://phperkaigi.jp/2025/
inouehi
March 16, 2025
Tweet
Share
More Decks by inouehi
See All by inouehi
2025 Reflections on Working with Natural Language
inouehi
0
100
Exploring Engineering in Workflow Development
inouehi
0
60
Using AI Tools Around Software Development
inouehi
0
1.5k
Learning Kotlin with detekt
inouehi
1
800
Learning numeric-like string based on RFC
inouehi
0
120
What We Can Learn From OSS
inouehi
0
1.2k
Learning PHP and Static Analysis with PHP Parser
inouehi
2
840
Understanding Ast By Looking
inouehi
0
2.3k
Improve Our Development Habits by Measuring Productivity and Maintainability
inouehi
1
1.6k
Other Decks in Programming
See All in Programming
Fragmented Architectures
denyspoltorak
0
130
AIエージェント、”どう作るか”で差は出るか? / AI Agents: Does the "How" Make a Difference?
rkaga
4
1.9k
16年目のピクシブ百科事典を支える最新の技術基盤 / The Modern Tech Stack Powering Pixiv Encyclopedia in its 16th Year
ahuglajbclajep
5
920
Oxlintはいいぞ
yug1224
5
960
AIで開発はどれくらい加速したのか?AIエージェントによるコード生成を、現場の評価と研究開発の評価の両面からdeep diveしてみる
daisuketakeda
1
890
KIKI_MBSD Cybersecurity Challenges 2025
ikema
0
1.2k
AI Agent Tool のためのバックエンドアーキテクチャを考える #encraft
izumin5210
6
1.7k
インターン生でもAuth0で認証基盤刷新が出来るのか
taku271
0
180
実は歴史的なアップデートだと思う AWS Interconnect - multicloud
maroon1st
0
350
PostgreSQLで手軽にDuckDBを使う!DuckDB&pg_duckdb入門/osc25hi-duckdb
takahashiikki
0
260
メルカリのリーダビリティチームが取り組む、AI時代のスケーラブルな品質文化
cloverrose
2
490
HTTPプロトコル正しく理解していますか? 〜かわいい猫と共に学ぼう。ฅ^•ω•^ฅ ニャ〜
hekuchan
2
660
Featured
See All Featured
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
25
1.7k
State of Search Keynote: SEO is Dead Long Live SEO
ryanjones
0
99
Stewardship and Sustainability of Urban and Community Forests
pwiseman
0
100
Balancing Empowerment & Direction
lara
5
850
Agile Leadership in an Agile Organization
kimpetersen
PRO
0
72
Joys of Absence: A Defence of Solitary Play
codingconduct
1
280
Designing Dashboards & Data Visualisations in Web Apps
destraynor
231
54k
Designing for Performance
lara
610
70k
Faster Mobile Websites
deanohume
310
31k
The Pragmatic Product Professional
lauravandoore
37
7.1k
Game over? The fight for quality and originality in the time of robots
wayneb77
1
84
Docker and Python
trallard
47
3.7k
Transcript
5系になったPHP Parser をのぞいてみよう! 2025/03/23 PHPerKaigi 2025 LT
About Me • Hiroki Inoue • Software Engineer • Engineering
Manager @ Smartround Inc. 2
トーク概要 このトークでは、PHP Parserで定義されているノードの全体像を整理します。 コードと、ノードないしASTの対応関係を見つめ、理解に迫ります。 年に1度、5分だけ、1年分の感謝を込めてPHP Parserだけを見つめASTに想いを馳せる。そんな時間に したいと思います。 3 https://fortee.jp/phperkaigi-2025/proposal/a792f343-21f2-47fb-9e45-243a77dd57af
誰向けのトーク? 4
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 5
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 6
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 7
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 8
誰向けのトーク? • 静的解析ツールを理解するヒントを得たい方 • PHPStanやRector等のカスタムルールを作成したい方 • 静的解析の恩恵を受けている方 9
つまり あなた 10
伝えたいこと 11
伝えたいこと • PHP Parserの働きを理解するためのヒント 12
伝えたいこと • PHP Parserの働きを理解するためのヒント • ノードの全体像 13
伝えたいこと • PHP Parserの働きを理解するためのヒント • ノードの全体像 • ノードとコードの対応関係 14
それと 15
尊敬 16
感謝 17
愛 18
ありがとうPHP Parser My utmost appreciation and heartfelt thanks for PHP
Parser 19
ありがとうnikic-san and nikic-san 20
俺たちは PHP Parser から 恩恵を受けまくっている 21
PHPStan 22 https://phpstan.org/blog/find-bugs-in-your-code-without-writing-tests#on-the-shoulders-of-giants
Rector 23 https://getrector.com/documentation/how-rector-works#content-21-prepare-phase
Psalm 24 https://psalm.dev/docs/contributing/philosophy/
php-class-diagram 25 https://github.com/smeghead/php-class-diagram
ノードをのぞいてみよう 26
前提 PHP Parser v5.3.1 に基づいて発表資料を作成します。 27
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 28 https://github.com/nikic/PHP-Parser/blob/master/doc/0_Introduction.markdown#what-output-does-it-produce
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 29 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) ) <?php echo 'The', 'World';
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 30 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) )
ノードとは “The parser produces an Abstract Syntax Tree (AST) also
known as a node tree.” 31 array( 0: Stmt_Echo( exprs: array( 0: Scalar_String( value: The ) 1: Scalar_String( value: World ) ) ) ) ノード
参考 • 『木を見て!森を見て!目で見てわかるAST(抽象構文木)』[1] • 『PHP Parserで学ぶPHP』[2] 32 1. https://speakerdeck.com/inouehi/understanding-ast-by-looking 2.
https://speakerdeck.com/inouehi/php-parserdexue-buphp
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 33 ./Node ├── Expr │ ├── AssignOp
│ │ ├── BitwiseAnd.php │ │ ├── BitwiseOr.php │ │ ├── BitwiseXor.php │ │ ├── Coalesce.php │ │ ├── Concat.php │ │ ├── Div.php │ │ ├── Minus.php │ │ ├── Mod.php │ │ ├── Mul.php │ │ ├── Plus.php │ │ ├── Pow.php │ │ ├── ShiftLeft.php
ノードの全体像 34 │ │ └── ShiftRight.php │ ├── BinaryOp │
│ ├── BitwiseAnd.php │ │ ├── BitwiseOr.php │ │ ├── BitwiseXor.php │ │ ├── BooleanAnd.php │ │ ├── BooleanOr.php │ │ ├── Coalesce.php │ │ ├── Concat.php │ │ ├── Div.php │ │ ├── Equal.php │ │ ├── Greater.php │ │ ├── GreaterOrEqual.php │ │ ├── Identical.php │ │ ├── LogicalAnd.php │ │ ├── LogicalOr.php │ │ ├── LogicalXor.php │ │ ├── Minus.php │ │ ├── Mod.php │ │ ├── Mul.php │ │ ├── NotEqual.php │ │ ├── NotIdentical.php │ │ ├── Plus.php
ノードの全体像 35 │ │ ├── Pow.php │ │ ├── ShiftLeft.php
│ │ ├── ShiftRight.php │ │ ├── Smaller.php │ │ ├── SmallerOrEqual.php │ │ └── Spaceship.php │ ├── Cast │ │ ├── Array_.php │ │ ├── Bool_.php │ │ ├── Double.php │ │ ├── Int_.php │ │ ├── Object_.php │ │ ├── String_.php │ │ └── Unset_.php │ ├── ArrayDimFetch.php │ ├── ArrayItem.php │ ├── Array_.php │ ├── ArrowFunction.php │ ├── Assign.php │ ├── AssignOp.php │ ├── AssignRef.php │ ├── BinaryOp.php │ ├── BitwiseNot.php
ノードの全体像 36 │ ├── BooleanNot.php │ ├── CallLike.php │ ├──
Cast.php │ ├── ClassConstFetch.php │ ├── Clone_.php │ ├── Closure.php │ ├── ClosureUse.php │ ├── ConstFetch.php │ ├── Empty_.php │ ├── Error.php │ ├── ErrorSuppress.php │ ├── Eval_.php │ ├── Exit_.php │ ├── FuncCall.php │ ├── Include_.php │ ├── Instanceof_.php │ ├── Isset_.php │ ├── List_.php │ ├── Match_.php │ ├── MethodCall.php │ ├── New_.php │ ├── NullsafeMethodCall.php │ ├── NullsafePropertyFetch.php
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 37
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 • エイリアス …
10個 38
ノードの全体像 nikic/php-parser/lib/PhpParser/Node/ 配下に190個のファイルがある。 • 抽象 … 12個 • エイリアス …
10個 • 具象 … 168個 39
抽象 1. PhpParser\Node\Expr\AssignOp 2. PhpParser\Node\Expr\BinaryOp 3. PhpParser\Node\Expr\Calllike 4. PhpParser\Node\Expr\Cast 5.
PhpParser\Node\Scalar\MagicConst 6. PhpParser\Node\Stmt\ClassLike 7. PhpParser\Node\Stmt\TraitUseAdaptation 8. PhpParser\Node\ComplexType 9. PhpParser\Node\Expr 10. PhpParser\Node\Functionlike 11. PhpParser\Node\Scalar 12. PhpParser\Node\Stmt 40
エイリアス 1. PhpParser\Node\Expr\ArrayItem 2. PhpParser\Node\Expr\ClosureUse 3. PhpParser\Node\Scalar\DNumber 4. PhpParser\Node\Scalar\Encapsed 5.
PhpParser\Node\Scalar\EncapsedStringPart 6. PhpParser\Node\Scalar\LNumber 7. PhpParser\Node\Stmt\DeclareDeclare 8. PhpParser\Node\Stmt\PropertyProperty 9. PhpParser\Node\Stmt\StaticVar 10. PhpParser\Node\Stmt\UseUse 41
コードとノードの対応表 # | コード | ノード | ------------------------------------------------------------------------------------------- 1 |
$a &= $b; | Node\Expr\AssignOp\BitwiseAnd | 2 | $a |= $b; | Node\Expr\AssignOp\BitwiseOr | 3 | $a ^= $b; | Node\Expr\AssignOp\BitwiseXor | 4 | $a ??= $b; | Node\Expr\AssignOp\Coalesce | 5 | $a .= $b; | Node\Expr\AssignOp\Concat | 6 | $a /= $b; | Node\Expr\AssignOp\Div | 7 | $a -= $b; | Node\Expr\AssignOp\Minus | 8 | $a %= $b; | Node\Expr\AssignOp\Mod | 9 | $a *= $b; | Node\Expr\AssignOp\Mul | 10 | $a += $b; | Node\Expr\AssignOp\Plus | 11 | $a **= $b; | Node\Expr\AssignOp\Pow | 42
BitwiseAnd をのぞいてみる 1 | $a &= $b; | Node\Expr\AssignOp\BitwiseAnd |
43
コードとノードの対応表 12 | $a <<= $b; | Node\Expr\AssignOp\ShiftLeft | 13
| $a >>= $b; | Node\Expr\AssignOp\ShiftRight | 14 | $a & $b; | Node\Expr\BinaryOp\BitwiseAnd | 15 | $a | $b; | Node\Expr\BinaryOp\BitwiseOr | 16 | $a ^ $b; | Node\Expr\BinaryOp\BitwiseXor | 17 | $a && $b; | Node\Expr\BinaryOp\BooleanAnd | 18 | $a || $b; | Node\Expr\BinaryOp\BooleanOr | 19 | $a ?? $b; | Node\Expr\BinaryOp\Coalesce | 20 | $a . $b; | Node\Expr\BinaryOp\Concat | 21 | $a / $b; | Node\Expr\BinaryOp\Div | 22 | $a == $b; | Node\Expr\BinaryOp\Equal | 23 | $a > $b; | Node\Expr\BinaryOp\Greater | 24 | $a >= $b; | Node\Expr\BinaryOp\GreaterOrEqual | 44
コードとノードの対応表 25 | $a === $b; | Node\Expr\BinaryOp\Identical | 26
| $a and $b; | Node\Expr\BinaryOp\LogicalAnd | 27 | $a or $b; | Node\Expr\BinaryOp\LogicalOr | 28 | $a xor $b; | Node\Expr\BinaryOp\LogicalXor | 29 | $a - $b; | Node\Expr\BinaryOp\Minus | 30 | $a % $b; | Node\Expr\BinaryOp\Mod | 31 | $a * $b; | Node\Expr\BinaryOp\Mul | 32 | $a != $b; | Node\Expr\BinaryOp\NotEqual | 33 | $a !== $b; | Node\Expr\BinaryOp\NotIdentical | 34 | $a + $b; | Node\Expr\BinaryOp\Plus | 35 | $a ** $b; | Node\Expr\BinaryOp\Pow | 36 | $a << $b; | Node\Expr\BinaryOp\ShiftLeft | 37 | $a >> $b; | Node\Expr\BinaryOp\ShiftRight | 45
コードとノードの対応表 38 | $a < $b; | Node\Expr\BinaryOp\Smaller | 39
| $a <= $b; | Node\Expr\BinaryOp\SmallerOrEqual | 40 | $a <=> $b; | Node\Expr\BinaryOp\Spaceship | 41 | (array)$a; | Node\Expr\Cast\Array_ | 42 | (bool)$a; | Node\Expr\Cast\Bool_ | 43 | (float)$a; | Node\Expr\Cast\Double | 44 | (int)$a; | Node\Expr\Cast\Int_ | 45 | (object)$a; | Node\Expr\Cast\Object_ | 46 | (string)$a; | Node\Expr\Cast\String_ | 47 | (unset)$a; | Node\Expr\Cast\Unset_ | 48 | $a["b"]; | Node\Expr\ArrayDimFetch | 49 | [1, 2, 3]; | Node\Expr\Array_ | 50 | fn($a) => $a; | Node\Expr\ArrowFunction | 46
コードとノードの対応表 51 | $a = $b; | Node\Expr\Assign | 52
| $a =& $b; | Node\Expr\AssignRef | 53 | ~$a; | Node\Expr\BitwiseNot | 54 | !$a; | Node\Expr\BooleanNot | 55 | A::B; | Node\Expr\ClassConstFetch | 56 | clone $a; | Node\Expr\Clone_ | 57 | function() {}; | Node\Expr\Closure | 58 | null; | Node\Expr\ConstFetch | 59 | empty($a); | Node\Expr\Empty_ | 60 | $a->; | Node\Expr\Error | 61 | @$a; | Node\Expr\ErrorSuppress | 62 | eval($a); | Node\Expr\Eval_ | 63 | exit; | Node\Expr\Exit_ | 47
コードとノードの対応表 64 | a(); | Node\Expr\FuncCall | 65 | include
"a.php"; | Node\Expr\Include_ | 66 | $a instanceof A; | Node\Expr\Instanceof_ | 67 | isset($a); | Node\Expr\Isset_ | 68 | list($a, $b) = $array; | Node\Expr\List_ | 69 | match($a) { 1 => 2 }; | Node\Expr\Match_ | 70 | $a->b(); | Node\Expr\MethodCall | 71 | new A(); | Node\Expr\New_ | 72 | $a?->b(); | Node\Expr\NullsafeMethodCall | 73 | $a?->b; | Node\Expr\NullsafePropertyFetch | 74 | $a--; | Node\Expr\PostDec | 75 | $a++; | Node\Expr\PostInc | 76 | --$a; | Node\Expr\PreDec | 48
コードとノードの対応表 77 | ++$a; | Node\Expr\PreInc | 78 | print($a);
| Node\Expr\Print_ | 79 | $a->b; | Node\Expr\PropertyFetch | 80 | `a`; | Node\Expr\ShellExec | 81 | A::b(); | Node\Expr\StaticCall | 82 | A::$b; | Node\Expr\StaticPropertyFetch | 83 | $a ? $b : $c; | Node\Expr\Ternary | 84 | throw new Exception(); | Node\Expr\Throw_ | 85 | -$a; | Node\Expr\UnaryMinus | 86 | +$a; | Node\Expr\UnaryPlus | 87 | $a; | Node\Expr\Variable | 88 | yield from $a; | Node\Expr\YieldFrom | 89 | yield $a; | Node\Expr\Yield_ | 49
コードとノードの対応表 90 | \A; | Node\Name\FullyQualified | 91 | namespace\A;
| Node\Name\Relative | 92 | __CLASS__; | Node\Scalar\MagicConst\Class_ | 93 | __DIR__; | Node\Scalar\MagicConst\Dir | 94 | __FILE__; | Node\Scalar\MagicConst\File | 95 | __FUNCTION__; | Node\Scalar\MagicConst\Function_ | 96 | __LINE__; | Node\Scalar\MagicConst\Line | 97 | __METHOD__; | Node\Scalar\MagicConst\Method | 98 | __NAMESPACE__; | Node\Scalar\MagicConst\Namespace_ | 99 | __PROPERTY__; | Node\Scalar\MagicConst\Property | 100 | __TRAIT__; | Node\Scalar\MagicConst\Trait_ | 101 | 1.23; | Node\Scalar\Float_ | 102 | 123; | Node\Scalar\Int_ | 50
コードとノードの対応表 103 | "$a is not b."; | Node\Scalar\InterpolatedString |
104 | "a"; | Node\Scalar\String_ | 105 | class A { use B { a as c; } } | Node\Stmt\TraitUseAdaptation\Alias | 106 | class A { use B, C { C::d insteadof B; }} | Node\Stmt\TraitUseAdaptation\Precedence | 107 | { $a; $b; } | Node\Stmt\Block | 108 | break; | Node\Stmt\Break_ | 109 | switch($a) { case 1: break; } | Node\Stmt\Case_ | 110 | try {} catch (Exception $e) {} | Node\Stmt\Catch_ | 111 | class A { public const A = 1; } | Node\Stmt\ClassConst | 112 | class A { public function a() {} } | Node\Stmt\ClassMethod | 113 | class A {} | Node\Stmt\Class_ | 114 | const A = 1; | Node\Stmt\Const_ | 115 | continue; | Node\Stmt\Continue_ | 51
コードとノードの対応表 116 | declare(strict_types=1); | Node\Stmt\Declare_ | 117 | do
{} while ($a); | Node\Stmt\Do_ | 118 | echo "a"; | Node\Stmt\Echo_ | 119 | if ($a) {} elseif ($b) {} | Node\Stmt\ElseIf_ | 120 | if ($a) {} else {} | Node\Stmt\Else_ | 121 | enum A { case B; } | Node\Stmt\EnumCase | 122 | enum A {} | Node\Stmt\Enum_ | 123 | $a; | Node\Stmt\Expression | 124 | try {} finally {} | Node\Stmt\Finally_ | 125 | for (;;) {}; | Node\Stmt\For_ | 126 | foreach ($a as $b) {}; | Node\Stmt\Foreach_ | 127 | function a() {} | Node\Stmt\Function_ | 128 | global $a; | Node\Stmt\Global_ | 52
コードとノードの対応表 129 | goto a; a: | Node\Stmt\Goto_ | 130
| use A\{B, C}; | Node\Stmt\GroupUse | 131 | __halt_compiler(); | Node\Stmt\HaltCompiler | 132 | if ($a) {}; | Node\Stmt\If_ | 133 | ?>a | Node\Stmt\InlineHTML | 134 | interface A {} | Node\Stmt\Interface_ | 135 | a: | Node\Stmt\Label | 136 | namespace A; | Node\Stmt\Namespace_ | 137 | // | Node\Stmt\Nop | 138 | class A { public $a; } | Node\Stmt\Property | 139 | return; | Node\Stmt\Return_ | 140 | static $a; | Node\Stmt\Static_ | 141 | switch ($a) {}; | Node\Stmt\Switch_ | 53
コードとノードの対応表 142 | class A { use B; } |
Node\Stmt\TraitUse | 143 | trait A {} | Node\Stmt\Trait_ | 144 | try {} catch (E $e) {} | Node\Stmt\TryCatch | 145 | unset($a); | Node\Stmt\Unset_ | 146 | use A\B; | Node\Stmt\Use_ | 147 | while ($a) {}; | Node\Stmt\While_ | 148 | a($b); | Node\Arg | 149 | ["a"]; | Node\ArrayItem | 150 | #[A]class B{} | Node\Attribute | 151 | #[A, B]class B{} | Node\AttributeGroup | 152 | function() use ($a) {}; | Node\ClosureUse | 153 | const A = 1, B = 2; | Node\Const_ | 154 | declare(strict_types=1); | Node\DeclareItem | 54
コードとノードの対応表 155 | function a(int $b) {} | Node\Identifier |
156 | `a`; | Node\InterpolatedStringPart | 157 | function a(int&string $b) {} | Node\IntersectionType | 158 | match ($a) { 1 => 2 }; | Node\MatchArm | 159 | A; | Node\Name | 160 | function a(?int $b) {} | Node\NullableType | 161 | function a($b) {} | Node\Param | 162 | class A { public $b { get => $this->b; }} | Node\PropertyHook | 163 | class A { public $a, $c; } | Node\PropertyItem | 164 | static $a = 1; | Node\StaticVar | 165 | function a(int|string $b) {} | Node\UnionType | 166 | use A\{B}; | Node\UseItem | 167 | class A { public string $b; } | Node\VarLikeIdentifier | 55
コードとノードの対応表 168 | a(...); | Node\VariadicPlaceholder | 56
ちなみに 57
v4.14.0 とv5.3.1 の違いは 58
たくさんあるよ 詳しくはCHANGELOG[1]をみてね ただしノードに注目すると違いはほぼ PropertyHook が追加されたことだけ あといくつかのノードがリネームされたこと 59 1. https://github.com/nikic/PHP-Parser/blob/master/CHANGELOG.md
PropertyHook 60 https://www.php.net/manual/ja/language.oop5.property-hooks.php
PropertyHook 61 https://www.youtube.com/watch?v=N1UrFJElkow
PropertyHook 62 array( 0: Stmt_Class( attrGroups: array( ) flags: 0
name: Identifier( name: The ) extends: null implements: array( ) stmts: array( 0: Stmt_Property( attrGroups: array( ) flags: PUBLIC (1) type: Identifier( name: string ) props: array( 0: PropertyItem( name: VarLikeIdentifier( name: hand ) default: null ) ) hooks: array( 0: PropertyHook( attrGroups: array( ) flags: 0 byRef: false name: Identifier( name: get ) params: array( ) body: Expr_PropertyFetch( var: Expr_Variable( name: this ) name: Identifier( name: hand ) ) ) ) ) ) ) ) class The { public string $hand { get => $this->hand; } }
PropertyHook 63 3つのノードに注目。 • PhpParser\Node\Stmt\Class_ ノード • PhpParser\Node\Stmt\Property ノード •
PhpParser\Node\PropertyHook ノード
PropertyHook 64 class The { public string $world; public function
throwRoadRoller(){} } 文(statement)
PropertyHook 65 class The { public string $world; public function
throwRoadRoller(){} } 文(statement) Class_ノードは statementの配列を 保持する
PropertyHook 66 class The { public string $world; public function
throwRoadRoller(){} } 文(statement) Class_ノードは statementの配列を 保持する ちなみに ClassLikeが それを提供する
PropertyHook 67 class The { public string $world; public function
throwRoadRoller(){} } Stmt\ClassMethod Stmt\Property
PropertyHook 68 class The { public string $world; public function
throwRoadRoller(){} } Stmt\Property 従来のプロパティを 表す部分と
PropertyHook 69 class The { public string $world; public function
throwRoadRoller(){} } Stmt\Property 従来のプロパティを 表す部分と プロパティフックを 表す部分がある
PropertyHook 70 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) Stmt\Property
PropertyHook 71 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) 従来のプロパティを 表す部分 Stmt\Property
PropertyHook 72 0: Stmt_Property( attrGroups: array() flags: PUBLIC (1) type:
Identifier( name: string ) props: array( 0: PropertyItem() ) hooks: array( 0: PropertyHook() ) ) 従来のプロパティを 表す部分 プロパティフックを 表す部分 Stmt\Property
PropertyHook 73 class The { public string $hand { get
=> $this->hand; } }
PropertyHook 74 hooks: array( 0: PropertyHook( attrGroups: array() flags: 0
byRef: false name: Identifier( name: get ) params: array() body: Expr_PropertyFetch( var: Expr_Variable( name: this ) name: Identifier( name: hand ) ) ) )
PropertyHook 75 class The { public string $hand { get
=> $this->hand; } } コード ノード
PropertyHook 76
PropertyHook 77
以上 ノードの全体像と ノードとコードの対応関係 をみてきました 78
一度落ち着こう 79
まだあわてるような時間じゃない 80
このLTに込めた想い 私達はPHP Parserから大きな恩恵を受けています。 しかし、その事を気に留めることはほとんどないのではないでしょうか。 年に1度、5分だけ、1年分の感謝を込めてPHP Parserだけを見つめASTに想いを馳せる。 そんな時間にしたいと思います。 81 https://fortee.jp/phperkaigi-2025/proposal/a792f343-21f2-47fb-9e45-243a77dd57af
ありがとうPHP Parser Again, I wish to express my deep respect
and gratitude to PHP Parser 82
ありがとうnikic-san and nikic-san 83
84 ご清 盛聴ありがとうございました