Pāriet uz saturu

Parser

Phasis nodrošina savu JavaScript parsētāju kā atsevišķu PHP API. Varat parsēt avota tekstu tipizētā AST, apstaigāt to un eksportēt kā ESTree formas masīvus vai JSON, neveidojot Engine un neko neizpildot.

parseSource

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

Vienas funkcijas ieejas punkts objektā Phasis\Parser\Parser. Parsē $source un atgriež saknes mezglu Phasis\Ast\Program.

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 izvēlas gramatikas mērķi, kas nosaukts tāpat kā attiecīgā opcija JS parsētājos:

Vērtība Mērķis
script klasisks Script. Augšējā līmeņa import/export ir sintakses kļūdas, await ir identifikators
module ES modulis. Netieši stingrais režīms; tiek parsēti import/export un augšējā līmeņa await

Jebkura cita vērtība izraisa \InvalidArgumentException.

Precīzākai kontrolei (stingrā režīma iepriekšējai iestatīšanai tiešas eval izsaukuma kontekstā, //# sourceURL pragmas nolasīšanai) izveidojiet parsētāju tieši: new Parser($source) kopā ar setModuleMode(), setStrictMode() un parse().

Mezgli

Katra AST klase paplašina Phasis\Ast\Node un atrodas zem Phasis\Ast\{Declaration, Expression, Pattern, Statement}. Mezgli ir vienkārši tikai lasāmi vērtību objekti:

  • $node->type() atgriež mezgla tipa virkni, kas ir klases nosaukums bez telpas nosaukuma ('BinaryExpression', 'ArrowFunction', ...).
  • $node->location ir Phasis\Lexer\SourceLocation ar line (sākot no 1), column (sākot no 0) un offset (baitu nobīdi). Tiek saglabātas tikai sākuma pozīcijas; mezgliem nav beigu nobīdes.
  • Visi pārējie publiskie lauki ir mezgla bērni un atribūti ($binary->left, $binary->operator, $binary->right).

Vairums tipu nosaukumu atbilst ESTree. Atšķirības:

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

Atšķiras arī dažas struktūras: klases mezgla klases pamatdaļa ir vienkāršs elementu masīvs (bez ClassBody ietvara); importēšanas/eksportēšanas nosaukumi, priekšrakstu etiķetes un FunctionExpression nosaukumi tiek glabāti kā virknes, nevis ligzdoti Identifier mezgli; savukārt super tiek parsēts kā Identifier ar nosaukumu super (nav Super mezgla klases). Phasis\Ast\EstreeSerializer pārveido to visu ESTree formā.

Sintakses kļūdas

Nederīga ievade izraisa Phasis\Exceptions\SyntaxError (parasti tās apakšklasi Phasis\Parser\ParseError). Izņēmuma ziņojums beidzas ar pozīciju, un strukturētā atrašanās vieta ir pieejama izņēmuma objektā:

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
}

Apstaigātājs

Phasis\Ast\Walker apstaigā koku dziļumā vispirms, izmantojot ieejas un izejas atzvanus, līdzīgi kā estraverse:

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

Abi atzvani saņem (Node $node, ?Node $parent). Ja $enter atgriež Walker::SKIP, mezgla bērni netiek apstaigāti; paša mezgla $leave joprojām tiek izsaukts.

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

Apstaigāšana ir tikai lasāma. Mezgli ir tikai lasāmi vērtību objekti, tāpēc tos nevar aizstāt vai mainīt.

Serializētājs

Phasis\Ast\Serializer pārveido tipizēto AST par masīviem vai JSON, izmantojot Phasis tipu nosaukumus un lauku izkārtojumu, un noņem parsētāja iekšējās kešatmiņas laukus:

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

Šo formātu izvada bin/phasis --ast.

EstreeSerializer

Phasis\Ast\EstreeSerializer tipizēto AST pārveido par ESTree formas masīviem: ar ESTree tipu nosaukumiem (atbilstoši iepriekšējai atšķirību tabulai), ESTree lauku nosaukumiem un secību, izveidotiem ClassBody / specifikatora / avota-Literal mezgliem un start baitu nobīdi katram no avota parsētam mezglam. end nobīžu nav, jo mezglos tiek glabātas tikai sākuma pozīcijas, un virkņu Literal mezglos nav teksta raw.

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() izvada deterministisku kopsavilkumu vienā rindā katram mezglam (tips un atribūti name= / value= / op= / kind=, divu atstarpju atkāpe katram dziļuma līmenim). Formāts baitu līmenī ir identisks AST kopsavilkumam, ko izveido acorn testa dati tests/Popular/acorn, tāpēc tas pats etalons pārbauda gan parsētāja ceļu JS, gan šo PHP eksportu:

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 parsē failu (script mērķī) un izvada Serializer JSON izdruku ar divu atstarpju atkāpi. Pilnu karodziņu aprakstu skatiet CLI.