さわって慣れるPHP Parser - IdentifierとNameとFullyQualified
さわって慣れるPHP Parserの続編です。
簡単なコードを解析してみることでPHP Parserに慣れ、ノードの理解を深めることを目指しています。今回はIdentifier, Name, FullyQualifiedという3つのノードの注目します。
さっそくPHP Parserをインストールします。
$ composer require --dev nikic/php-parser
解析対象のコード(Thoth.php)をしたためます。(PHPとしての適切さは度外視し、ノードを観察するためだけのコードです。)
<?php
Boingo::foresee();
\Boingo::foresee();
Oingo\Boingo::foresee();
\Oingo\Boingo::foresee();
解析します。
$ vendor/bin/php-parse Thoth.php
====> File Thoth.php:
==> Node dump:
array(
0: Stmt_Expression(
expr: Expr_StaticCall(
class: Name(
parts: array(
0: Boingo
)
)
name: Identifier(
name: foresee
)
args: array(
)
)
)
1: Stmt_Expression(
expr: Expr_StaticCall(
class: Name_FullyQualified(
parts: array(
0: Boingo
)
)
name: Identifier(
name: foresee
)
args: array(
)
)
)
2: Stmt_Expression(
expr: Expr_StaticCall(
class: Name(
parts: array(
0: Oingo
1: Boingo
)
)
name: Identifier(
name: foresee
)
args: array(
)
)
)
3: Stmt_Expression(
expr: Expr_StaticCall(
class: Name_FullyQualified(
parts: array(
0: Oingo
1: Boingo
)
)
name: Identifier(
name: foresee
)
args: array(
)
)
)
)
色々でてますがサラリと流して、Expr_StaticCallに注目します。
--var-dumpモードで実行するとStaticCallクラスだと分かります。
StaticCallクラスのgetSubNodeNames()を確認します。
public function getSubNodeNames() : array {
return ['class', 'name', 'args'];
}
プロパティも確認します。
class StaticCall extends CallLike
{
/** @var Node\Name|Expr Class name */
public $class;
/** @var Identifier|Expr Method name */
public $name;
/** @var array<Arg|VariadicPlaceholder> Arguments */
public $args;
Boingo::foresee();においてBoingoが$class、foreseeが$name 、もしあればforesee()の引数が$argsで、Boingoの型はNameかExpr、foreseeの型はIdentifierかExprだとわかります。Exprになりえるのは例えば変数のケースがあるからです。
変数のケースというのは、一例をあげると、以下のようにclassの部分が変数になっているケースです。
<?php
$boingo::foresee();
$ vendor/bin/php-parse ThothVariable.php
====> File ThothVariable.php:
==> Node dump:
array(
0: Stmt_Expression(
expr: Expr_StaticCall(
class: Expr_Variable(
name: boingo
)
name: Identifier(
name: foresee
)
args: array(
)
)
)
)
Expr_StaticCallのclassがExpr_Variableになりました。
Exprは式を表すノードで、Variableは変数を表すノードです。そして変数は式です。
さてNameとIdentifierに注目します。Identifierの定義を見てみます。
Represents a non-namespaced name. Namespaced names are represented using Name nodes.
とあります。
メソッド名は名前空間付きで表記されるものではない一方でクラス名は名前空間付きで表記されますし、観察結果とも整合的です。
さて、冒頭の解析結果にはExpr_StaticCallが4つありました。これらの相違点にも注目してみます。
class: Name(
parts: array(
0: Boingo
)
)
class: Name_FullyQualified(
parts: array(
0: Boingo
)
)
class: Name(
parts: array(
0: Oingo
1: Boingo
)
)
class: Name_FullyQualified(
parts: array(
0: Oingo
1: Boingo
)
)
先頭に\をつけるとFullyQualified、つけないとNameになるようです。また、名前空間は配列で表現されるようです。
Fully Qualifiedは日本語でいうと完全修飾名で、PHPマニュアルも参考になります。
FullyQualifiedの定義を見てみます。
FullyQualifiedはNameを拡張したものということも分かりました。
Discussion