Parser
Phasis stiller sin JavaScript-parser til rådighed som en selvstændig PHP API. Du kan parse kildetekst til et typet AST, gennemløbe det og eksportere det som ESTree-formede arrays eller JSON uden at oprette en Engine eller udføre noget.
parseSource
public static function parseSource(string $source, string $sourceType = 'script'): Program
Indgangspunktet med ét kald på Phasis\Parser\Parser. Parser $source og returnerer rodknuden Phasis\Ast\Program.
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 vælger grammatikmålet, opkaldt efter den samme indstilling i JS-parsers:
| Værdi | Mål |
|---|---|
script |
klassisk Script. import/export på øverste niveau er syntaksfejl, await er en identifikator |
module |
ES-modul. Implicit strict mode, import/export og await på øverste niveau parses |
Alle andre værdier udløser \InvalidArgumentException.
Hvis du har brug for finere kontrol (forudindstil strict mode til en direkte eval-kontekst, læs //# sourceURL-pragmaet), skal du konstruere parseren direkte: new Parser($source) plus setModuleMode(), setStrictMode() og parse().
Knuder
Hver AST-klasse udvider Phasis\Ast\Node og findes under Phasis\Ast\{Declaration, Expression, Pattern, Statement}. Knuderne er skrivebeskyttede værdiobjekter uden anden funktionalitet:
$node->type()returnerer knudens typ streng, som er klassens basenavn ('BinaryExpression','ArrowFunction', ...).$node->locationer enPhasis\Lexer\SourceLocationmedline(1-baseret),column(0-baseret) ogoffset(byteforskydning). Kun startpositioner gemmes; knuder har ingen slutposition.- Alle andre offentlige felter er knudens underknuder og attributter (
$binary->left,$binary->operator,$binary->right).
De fleste typenavne følger ESTree. Afvigelserne:
| Phasis-type | ESTree-type |
|---|---|
ArrowFunction |
ArrowFunctionExpression |
TaggedTemplate |
TaggedTemplateExpression |
ClassMethod |
MethodDefinition |
ClassProperty |
PropertyDefinition |
AssignmentProperty |
Property (inde i ObjectPattern) |
ExportDeclaration |
ExportNamedDeclaration / ExportDefaultDeclaration / ExportAllDeclaration |
ImportSpecifier |
ImportSpecifier / ImportDefaultSpecifier / ImportNamespaceSpecifier |
Nogle former er også forskellige: klasseblokke er et almindeligt elementarray på klassenoden (uden wrapperen ClassBody), import-/eksportnavne, sætningsetiketter og FunctionExpression-navne gemmes som strenge i stedet for indlejrede Identifier-knuder, og super parses som en Identifier med navnet super (der findes ingen Super-klasse). Phasis\Ast\EstreeSerializer omformer alt dette til ESTree-formatet.
Syntaksfejl
Ugyldigt input udløser Phasis\Exceptions\SyntaxError (normalt dens underklasse Phasis\Parser\ParseError). Undtagelsesmeddelelsen slutter med positionen, og den strukturerede placering findes på undtagelsen:
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
}
Gennemløber
Phasis\Ast\Walker gennemløber et træ i dybden med enter-/leave-callbacks, efter samme mønster som estraverse:
public static function walk(Node $node, callable $enter, ?callable $leave = null): void
Begge callbacks modtager (Node $node, ?Node $parent). Hvis $enter returnerer Walker::SKIP, springes knudens underknuder over; knudens egen $leave udføres stadig.
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;
}
});
Gennemløbet er skrivebeskyttet. Knuderne er skrivebeskyttede værdiobjekter, så de kan ikke erstattes eller ændres.
Serialisator
Phasis\Ast\Serializer konverterer det typede AST til arrays eller JSON ved hjælp af Phasis-typenavne og feltlayoutet, mens parserens interne cachefelter fjernes:
public static function toArray(Node $node): array
public static function toJson(Node $node, bool $pretty = false): string
Dette er det format, bin/phasis --ast udskriver.
EstreeSerializer
Phasis\Ast\EstreeSerializer konverterer i stedet det typede AST til arrays formet efter ESTree: ESTree-typenavne (ifølge afvigelsestabellen ovenfor), ESTree-feltnavne og -rækkefølge, syntetiserede ClassBody / specifikator- / source-Literal-noder samt en start-byteforskydning på hver node, der parses fra kildekoden. Der er ingen end-forskydninger, fordi noder kun gemmer startpositioner, og streng-Literal-noder ikke indeholder nogen raw-tekst.
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() udsender en deterministisk oversigt med én linje pr. node (type plus attributterne name= / value= / op= / kind=, indrykning på to mellemrum pr. dybdeniveau). Formatet er byteidentisk med AST-oversigten, som acorn-fixturen i tests/Popular/acorn producerer, så den samme oracle kontrollerer både parserstien for JS og denne eksport fra 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 parser en fil (script-mål) og udskriver Serializer-JSON-dumpet med indrykning på to mellemrum. Se CLI for den fulde oversigt over flag.