Pereiti prie turinio

Analizatorius

Phasis pateikia savo JavaScript analizatorių kaip atskirą PHP API. Šaltinio tekstą galite analizuoti į tipizuotą AST, pereiti per jį ir eksportuoti kaip ESTree formos masyvus arba JSON, nekurdami Engine ir nieko nevykdydami.

parseSource

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

Vieno iškvietimo įvesties taškas, skirtas Phasis\Parser\Parser. Analizuoja $source ir grąžina šakninį Phasis\Ast\Program mazgą.

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 parenka gramatikos tikslą, pavadintą taip pat kaip ta pati parinktis JS analizatoriuose:

Reikšmė Tikslas
script klasikinis scenarijus. Aukščiausio lygio import/export yra sintaksės klaidos, await yra identifikatorius
module ES modulis. Veikia numanomai griežtuoju režimu, analizuojami import/export ir aukščiausio lygio await

Bet kuri kita reikšmė iškelia \InvalidArgumentException.

Jei reikia tikslesnio valdymo (iš anksto įjungti griežtąjį režimą tiesioginio eval kontekste, nuskaityti //# sourceURL direktyvą), sukurkite analizatorių tiesiogiai: new Parser($source) kartu su setModuleMode(), setStrictMode() ir parse().

Mazgai

Kiekviena AST klasė išplečia Phasis\Ast\Node ir yra Phasis\Ast\{Declaration, Expression, Pattern, Statement}. Mazgai yra paprasti tik skaitomi reikšmių objektai:

  • $node->type() grąžina mazgo tipo eilutę, t. y. klasės bazinį pavadinimą ('BinaryExpression', 'ArrowFunction', ...).
  • $node->location yra Phasis\Lexer\SourceLocation su line (nuo 1), column (nuo 0) ir offset (baito poslinkiu). Išsaugomos tik pradžios pozicijos; mazgai neturi pabaigos poslinkio.
  • Visi kiti viešieji laukai yra mazgo vaikai ir atributai ($binary->left, $binary->operator, $binary->right).

Dauguma tipų pavadinimų sutampa su ESTree. Skirtumai:

Phasis tipas ESTree tipas
ArrowFunction ArrowFunctionExpression
TaggedTemplate TaggedTemplateExpression
ClassMethod MethodDefinition
ClassProperty PropertyDefinition
AssignmentProperty Property (ObjectPattern viduje)
ExportDeclaration ExportNamedDeclaration / ExportDefaultDeclaration / ExportAllDeclaration
ImportSpecifier ImportSpecifier / ImportDefaultSpecifier / ImportNamespaceSpecifier

Kai kurios struktūros taip pat skiriasi: klasių turinys klasės mazge yra paprastas elementų masyvas (be ClassBody apvalkalo), importavimo ir eksportavimo pavadinimai, sakinių žymos bei FunctionExpression pavadinimai saugomi kaip eilutės, o ne įdėtiniai Identifier mazgai; be to, super analizuojamas kaip Identifier pavadinimu super (klasės Super mazgo nėra). Phasis\Ast\EstreeSerializer visa tai pertvarko į ESTree formą.

Sintaksės klaidos

Netaisyklinga įvestis iškelia Phasis\Exceptions\SyntaxError (paprastai jos poklasį Phasis\Parser\ParseError). Išimties pranešimo pabaigoje nurodoma pozicija, o struktūrizuotą vietą galima rasti išimtyje:

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
}

Pereiklis

Phasis\Ast\Walker pereina medį gilyn pirmiausia, vykdydamas įėjimo ir išėjimo atgalinio iškvietimo funkcijas, kaip estraverse:

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

Abi atgalinio iškvietimo funkcijos gauna (Node $node, ?Node $parent). Jei iš $enter grąžinama Walker::SKIP, mazgo vaikai praleidžiami; paties mazgo $leave vis tiek iškviečiama.

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

Pereinama tik skaitant. Mazgai yra tik skaitomi reikšmių objektai, todėl pakeisti ar modifikuoti jų negalima.

Serializatorius

Phasis\Ast\Serializer konvertuoja tipizuotą AST į masyvus arba JSON, naudodamas Phasis tipų pavadinimus ir laukų išdėstymą; analizatoriaus vidiniai spartinančiosios atmintinės laukai pašalinami:

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

Šį formatą išveda bin/phasis --ast.

EstreeSerializer

Phasis\Ast\EstreeSerializer vietoj to konvertuoja tipizuotą AST į ESTree formos masyvus: naudojami ESTree tipų pavadinimai (pagal pirmiau pateiktą skirtumų lentelę), ESTree laukų pavadinimai ir tvarka, sukuriami ClassBody / specifikatoriaus / šaltinio Literal mazgai, o kiekviename iš šaltinio išanalizuotame mazge nurodomas start baito poslinkis. end poslinkių nėra, nes mazguose saugomos tik pradžios pozicijos, o eilutės Literal mazguose nėra raw teksto.

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() pateikia deterministinę santrauką po vieną eilutę kiekvienam mazgui (tipas ir name= / value= / op= / kind= atributai, kiekvienas įdėtumo lygis įtraukiamas dviem tarpais). Formatas baitas po baito sutampa su AST santrauka, kurią pateikia acorn etalonas tests/Popular/acorn, todėl tas pats etalonas tikrina ir JS analizatoriaus kelią, ir šį PHP eksportą:

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 analizuoja failą (scenarijaus tikslas) ir išveda Serializer JSON išrašą, įtraukdamas eilutes dviem tarpais. Visą parinkčių aprašą rasite čia: CLI.