
# 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](https://github.com/estree/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](https://phasis.inline0.dev/et/docs/cli).
