Liigu sisu juurde

Parser

Phasis pakub oma JavaScript parserit iseseisva PHP API-ina. Saad parsida lähtekoodi teksti tüübistatud AST-iks, läbida selle ja eksportida ESTree-kujuliste massiividena või JSON-na, ilma et peaksid looma Engine või midagi käivitama.

parseSource

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

Ühe kõnega sisenemispunkt objektis Phasis\Parser\Parser. Parsib $source ja tagastab juursõlme 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 valib grammatika eesmärgi, mille nimi vastab sama valiku nimele JS parserites:

Väärtus Eesmärk
script klassikaline Script. Tipptaseme import/export süntaksivead, await on identifikaator
module ES Module. Kaudselt range režiimiga; parsitakse import/export ja tipptaseme await

Mis tahes muu väärtus tekitab erindi \InvalidArgumentException.

Täpsemaks juhtimiseks (range režiimi eelseadistamiseks direct-eval-konteksti jaoks, pragma //# sourceURL lugemiseks) loo parser otse: new Parser($source), millele lisa setModuleMode(), setStrictMode() ja parse().

Sõlmed

Iga AST-klass laiendab klassi Phasis\Ast\Node ja asub nimeruumi Phasis\Ast\{Declaration, Expression, Pattern, Statement} all. Sõlmed on lihtsad kirjutuskaitstud väärtusobjektid:

  • $node->type() tagastab sõlme tüübistringi, mis on klassi baasinimi ('BinaryExpression', 'ArrowFunction', ...).
  • $node->location on Phasis\Lexer\SourceLocation, millel on line (alates 1-st), column (alates 0-st) ja offset (baidioffset). Salvestatakse ainult alguspositsioonid; sõlmedel puudub lõpu nihe.
  • Kõik muud avalikud väljad on sõlme alamsõlmed ja atribuudid ($binary->left, $binary->operator, $binary->right).

Enamik tüübinimesid vastab ESTree-le. Erinevused:

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

Mõned kujundid erinevad samuti: klassi kehad on klassisõlmes lihtsad elemendimassiivid (ilma ClassBody ümbriseta), impordi/ekspordi nimed, lausesildid ja FunctionExpression nimed salvestatakse stringidena, mitte pesastatud Identifier sõlmedena ning super parsitakse nimega super Identifier-na (sõlmeklassi Super pole). Phasis\Ast\EstreeSerializer muudab selle kõik ESTree-kujule.

Süntaksivead

Vigane sisend tekitab erindi Phasis\Exceptions\SyntaxError (tavaliselt selle alamklassi Phasis\Parser\ParseError). Erindi sõnum lõpeb positsiooniga ja struktureeritud asukoht on erindil saadaval:

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
}

Läbikäija

Phasis\Ast\Walker läbib puud sügavuti, kutsudes esile sisenemise ja väljumise tagasihelistused, estraverse'i eeskujul:

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

Mõlemad tagasihelistused saavad argumendiks (Node $node, ?Node $parent). Kui $enter tagastab Walker::SKIP, jäetakse sõlme alamsõlmed vahele, kuid sõlme enda $leave käivitatakse siiski.

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

Läbikäik on kirjutuskaitstud. Sõlmed on kirjutuskaitstud väärtusobjektid, seega asendamine ega muutmine pole toetatud.

Jadavorming

Phasis\Ast\Serializer teisendab tüübistatud AST-i massiivideks või JSON-ks, kasutades Phasis tüüb nimesid ja väljade paigutust ning eemaldades parseri sisemised vahemäluväljad:

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

See on vorming, milles bin/phasis --ast väljastab tulemuse.

EstreeSerializer

Phasis\Ast\EstreeSerializer teisendab tüübistatud AST-i hoopis ESTree-kujulisteks massiivideks: ESTree tüübinimed (vastavalt ülaltoodud erinevuste tabelile), ESTree väljade nimed ja järjestus, genereeritud ClassBody / specifier / source-Literal sõlmed ning lähtekoodist parsitud iga sõlme start baidioffset. Lõpu nihkeid end ei ole, sest sõlmed salvestavad ainult alguspositsioone; stringist Literal sõlmed ei sisalda teksti 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() väljastab deterministliku kokkuvõtte, kus igal sõlmel on oma rida (tüüp ning atribuudid name= / value= / op= / kind=, iga pesastustaseme taane on kaks tühikut). Vorming on baidi kaupa identne acorn-fixture'i AST-kokkuvõttega, mille tests/Popular/acorn loob; sama kontrollandmestik hindab seega nii parseri rada JS kui ka seda eksporti PHP:

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 parsib faili (Script-eesmärgiga) ja väljastab Serializer JSON-dumpi kahetühikulise taandega. Kõigi lippude kirjeldust vt CLI.