İçeriğe geç

Ayrıştırıcı

Phasis, kendi JavaScript ayrıştırıcısını bağımsız bir PHP API olarak sunar. Kaynak metni türlenmiş bir AST'ye ayrıştırabilir, üzerinde dolaşabilir ve bir Engine oluşturmadan veya herhangi bir kod çalıştırmadan ESTree biçimli diziler ya da JSON olarak dışa aktarabilirsiniz.

parseSource

PHP
public static function parseSource(string $source, string $sourceType = 'script'): Program

Phasis\Parser\Parser üzerindeki tek çağrılı giriş noktası. $source'ı ayrıştırır ve kök Phasis\Ast\Program düğümünü döndürür.

PHP
use Phasis\Parser\Parser;

$program = Parser::parseSource('const x = [1, 2].map(n => n * 2);');
$module = Parser::parseSource('import { x } from "./x.js"; export default x;', 'module');

$sourceType, dilbilgisi hedefini seçer; adlandırma JS ayrıştırıcılarındaki aynı seçenekle aynıdır:

Değer Hedef
script klasik Script. En üst düzeydeki import/export sözdizimi hatasıdır; await bir tanımlayıcıdır
module ES Module. Örtük katı kip; import/export ve en üst düzeydeki await ayrıştırılır

Diğer her değer \InvalidArgumentException fırlatır.

Daha ayrıntılı denetim için (doğrudan eval bağlamında katı kipi önceden etkinleştirmek, //# sourceURL pragma'sını okumak), ayrıştırıcıyı doğrudan oluşturun: new Parser($source) ile setModuleMode(), setStrictMode() ve parse().

Düğümler

Her AST sınıfı Phasis\Ast\Node sınıfını genişletir ve Phasis\Ast\{Declaration, Expression, Pattern, Statement} altında yer alır. Düğümler, salt okunur basit değer nesneleridir:

  • $node->type(), düğümün sınıf temel adı olan tür dizgesini döndürür ('BinaryExpression', 'ArrowFunction', ...).
  • $node->location, Phasis\Lexer\SourceLocation olup line (1 tabanlı), column (0 tabanlı) ve offset (bayt ofseti) içerir. Yalnızca başlangıç konumları saklanır; düğümlerde bitiş ofseti yoktur.
  • Diğer tüm herkese açık alanlar düğümün alt öğeleri ve öznitelikleridir ($binary->left, $binary->operator, $binary->right).

Tür adlarının çoğu ESTree ile eşleşir. Farklılıklar:

Phasis türü ESTree türü
ArrowFunction ArrowFunctionExpression
TaggedTemplate TaggedTemplateExpression
ClassMethod MethodDefinition
ClassProperty PropertyDefinition
AssignmentProperty Property (ObjectPattern içinde)
ExportDeclaration ExportNamedDeclaration / ExportDefaultDeclaration / ExportAllDeclaration
ImportSpecifier ImportSpecifier / ImportDefaultSpecifier / ImportNamespaceSpecifier

Bazı yapılar da farklıdır: sınıf gövdeleri, sınıf düğümünde düz bir öğe dizisidir (ClassBody sarmalayıcısı yoktur); içe/dışa aktarma adları, ifade etiketleri ve FunctionExpression adları iç içe Identifier düğümleri yerine dizgeler olarak saklanır; super ise super adlı bir Identifier olarak ayrıştırılır (Super düğüm sınıfı yoktur). Phasis\Ast\EstreeSerializer tüm bunları ESTree biçimine dönüştürür.

Sözdizimi hataları

Geçersiz girdi Phasis\Exceptions\SyntaxError fırlatır (genellikle alt sınıfı olan Phasis\Parser\ParseError). İstisna iletisi konumla biter; yapılandırılmış konum bilgisine istisna üzerinden erişilebilir:

PHP
use Phasis\Exceptions\SyntaxError;
use Phasis\Parser\Parser;

try {
    Parser::parseSource("const a = 1;\nconst b = ;");
} catch (SyntaxError $e) {
    echo $e->getMessage();          // Unexpected token (got ; ";") at line 2, column 10
    echo $e->location->line;        // 2
    echo $e->location->column;      // 10
    echo $e->location->offset;      // 23
}

Dolaşıcı

Phasis\Ast\Walker, estraverse tarzında, giriş/çıkış geri çağrılarıyla ağaçta derinlik öncelikli dolaşır:

PHP
public static function walk(Node $node, callable $enter, ?callable $leave = null): void

Her iki geri çağrı da (Node $node, ?Node $parent) alır. $enter içinden Walker::SKIP döndürmek, düğümün alt öğelerini atlar; düğümün kendi $leave geri çağrısı yine de çalışır.

PHP
use Phasis\Ast\Expression\Identifier;
use Phasis\Ast\Node;
use Phasis\Ast\Walker;

$names = [];
Walker::walk($program, function (Node $node) use (&$names) {
    if ($node instanceof Identifier) {
        $names[] = $node->name;
    }
    if ($node instanceof \Phasis\Ast\Expression\ArrowFunction) {
        return Walker::SKIP;
    }
});

Dolaşım salt okunurdur. Düğümler, salt okunur değer nesneleridir; bu nedenle değiştirme/değişiklik desteği yoktur.

Serileştirici

Phasis\Ast\Serializer, türlenmiş AST'yi Phasis tür adlarını ve alan düzenini kullanarak dizilere veya JSON biçimine dönüştürür; ayrıştırıcıya özgü önbellek alanları çıkarılır:

PHP
public static function toArray(Node $node): array
public static function toJson(Node $node, bool $pretty = false): string

Bu, bin/phasis --ast'ın yazdırdığı biçimdir.

EstreeSerializer

Phasis\Ast\EstreeSerializer, türlenmiş AST'yi bunun yerine ESTree biçimli dizilere dönüştürür: ESTree tür adları (yukarıdaki farklılık tablosuna göre), ESTree alan adları ve sıralaması, oluşturulmuş ClassBody / belirtici / kaynak-Literal düğümleri ve kaynaktan ayrıştırılan her düğüm için bir start bayt ofseti. Düğümler yalnızca başlangıç konumlarını sakladığından end ofsetleri yoktur; dizge Literal düğümleri de raw metni içermez.

PHP
public static function toArray(Node $node): array
public static function toJson(Node $node, bool $pretty = false): string
public static function summarize(Node $node): string

summarize(), her düğüm için tür ile name= / value= / op= / kind= özniteliklerini içeren, deterministik ve her satırda bir özet üretir; her derinlik düzeyinde iki boşluk girinti kullanır. Biçim, tests/Popular/acorn içindeki acorn fikstürünün ürettiği AST özetiyle bayt düzeyinde aynıdır; böylece aynı doğrulayıcı hem JS ayrıştırıcı yolunu hem de bu PHP dışa aktarımını değerlendirir:

PHP
use Phasis\Ast\EstreeSerializer;
use Phasis\Parser\Parser;

echo EstreeSerializer::summarize(Parser::parseSource('let x = a + 1;'));
// Program
//   VariableDeclaration kind=let
//     VariableDeclarator
//       Identifier name=x
//       BinaryExpression op=+
//         Identifier name=a
//         Literal value=1

CLI

bin/phasis --ast script.js bir dosyayı (script hedefiyle) ayrıştırır ve Serializer JSON dökümünü iki boşluk girintiyle yazdırır. Tüm bayrakların açıklaması için CLI bölümüne bakın.