
# 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

```php
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`.

```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` 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->location` er en `Phasis\Lexer\SourceLocation` med `line` (1-baseret), `column` (0-baseret) og `offset` (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](https://github.com/estree/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:

```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
}
```

## Gennemløber

`Phasis\Ast\Walker` gennemløber et træ i dybden med enter-/leave-callbacks, efter samme mønster som estraverse:

```php
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.

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

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:

```php
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.

```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()` 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:

```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](https://phasis.inline0.dev/da/docs/cli) for den fulde oversigt over flag.
