
# Parser

Phasis sprístupňuje svoj parser JavaScript ako samostatný PHP API. Zdrojový text môžete analyzovať na typovaný AST, prechádzať ním a exportovať ho ako polia v tvare ESTree alebo JSON bez vytvárania `Engine` či vykonávania čohokoľvek.

## parseSource

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

Vstupný bod na jedno volanie pre `Phasis\Parser\Parser`. Analyzuje `$source` a vráti koreňový uzol `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` vyberá gramatický cieľ pomenovaný rovnako ako príslušná možnosť v parseroch JS:

| Hodnota | Cieľ |
|---|---|
| `script` | klasický skript. Toplevel `import`/`export` sú syntaktické chyby, `await` je identifikátor |
| `module` | modul ES. Implicitne používa prísny režim, `import`/`export` a najvyššia úroveň `await` sa analyzujú |

Každá iná hodnota vyvolá `\InvalidArgumentException`.

Ak potrebujete podrobnejšie nastavenie (napríklad vopred zapnúť prísny režim pre kontext priameho eval alebo načítať pragmu `//# sourceURL`), vytvorte parser priamo: `new Parser($source)` spolu s `setModuleMode()`, `setStrictMode()` a `parse()`.

## Uzly

Každá trieda AST rozširuje `Phasis\Ast\Node` a nachádza sa pod `Phasis\Ast\{Declaration, Expression, Pattern, Statement}`. Uzly sú obyčajné objekty s hodnotami iba na čítanie:

- `$node->type()` vracia reťazec typu uzla, čo je základný názov triedy (`'BinaryExpression'`, `'ArrowFunction'`, ...).
- `$node->location` je `Phasis\Lexer\SourceLocation` s `line` (číslovanie od 1), `column` (číslovanie od 0) a `offset` (posun v bajtoch). Ukladajú sa iba počiatočné pozície; uzly nemajú koncovú pozíciu.
- Všetky ostatné verejné polia obsahujú potomkov a atribúty uzla (`$binary->left`, `$binary->operator`, `$binary->right`).

Väčšina názvov typov zodpovedá [ESTree](https://github.com/estree/estree). Odchýlky:

| Typ Phasis | Typ ESTree |
|---|---|
| `ArrowFunction` | `ArrowFunctionExpression` |
| `TaggedTemplate` | `TaggedTemplateExpression` |
| `ClassMethod` | `MethodDefinition` |
| `ClassProperty` | `PropertyDefinition` |
| `AssignmentProperty` | `Property` (vnútri `ObjectPattern`) |
| `ExportDeclaration` | `ExportNamedDeclaration` / `ExportDefaultDeclaration` / `ExportAllDeclaration` |
| `ImportSpecifier` | `ImportSpecifier` / `ImportDefaultSpecifier` / `ImportNamespaceSpecifier` |

Niekoľko tvarov sa tiež líši: telá tried sú priamo v poli prvkov uzla triedy (bez obalu `ClassBody`), názvy importov a exportov, štítky príkazov a názvy `FunctionExpression` sa ukladajú ako reťazce namiesto vnorených uzlov `Identifier` a `super` sa analyzuje ako pomenovaný `Identifier` s názvom `super` (neexistuje trieda uzla `Super`). `Phasis\Ast\EstreeSerializer` toto všetko prevedie do podoby ESTree.

## Syntaktické chyby

Neplatný vstup vyvolá `Phasis\Exceptions\SyntaxError` (zvyčajne jeho podtriedu `Phasis\Parser\ParseError`). Správa výnimky končí pozíciou a štruktúrované údaje o umiestnení sú dostupné vo výnimke:

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

## Prechádzač

`Phasis\Ast\Walker` prechádza strom do hĺbky a pri vstupe do uzla aj pri jeho opustení volá spätné volania, podobne ako estraverse:

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

Obe spätné volania dostávajú `(Node $node, ?Node $parent)`. Ak `$enter` vráti `Walker::SKIP`, potomkovia uzla sa preskočia; spätné volanie pre samotný uzol `$leave` sa napriek tomu vykoná.

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

Prechádzanie je iba na čítanie. Uzly sú objekty s hodnotami iba na čítanie, preto ich nemožno nahrádzať ani meniť.

## Serializátor

`Phasis\Ast\Serializer` konvertuje typovaný AST na polia alebo JSON s názvami typov a rozložením polí podľa Phasis; interné polia vyrovnávacej pamäte parsera sa odstránia:

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

Toto je formát, ktorý vypisuje `bin/phasis --ast`.

## EstreeSerializer

`Phasis\Ast\EstreeSerializer` namiesto toho konvertuje typovaný AST na polia v tvare ESTree: názvy typov podľa odchýlok uvedených vyššie, názvy a poradie polí podľa ESTree, syntetizované uzly `ClassBody` / špecifikátora / zdroja `Literal` a posun v bajtoch `start` pre každý uzol analyzovaný zo zdroja. Posuny `end` sa neuvádzajú, pretože uzly ukladajú iba počiatočné pozície, a reťazcové uzly `Literal` neobsahujú text `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()` vytvorí deterministický súhrn s jedným riadkom na uzol (typ a atribúty `name=` / `value=` / `op=` / `kind=`, odsadenie dvoma medzerami na každú úroveň). Formát je bajtovo identický so súhrnom AST, ktorý vytvára testovacia vzorka acorn v `tests/Popular/acorn`, takže rovnaký referenčný nástroj overuje cestu parsera JS aj tento export 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` analyzuje súbor (cieľ skriptu) a vypíše výpis `Serializer` JSON s odsadením dvoma medzerami. Úplný prehľad príznakov nájdete v [CLI](https://phasis.inline0.dev/sk/docs/cli).
