
# Parser

Phasis menyediakan parser JavaScript sebagai PHP API mandiri. Anda dapat mem-parse teks sumber menjadi AST bertipe, menelusurinya, lalu mengekspornya sebagai array berbentuk ESTree atau JSON tanpa membuat `Engine` atau menjalankan apa pun.

## parseSource

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

Titik masuk satu pemanggilan pada `Phasis\Parser\Parser`. Mem-parse `$source` dan mengembalikan node akar `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` memilih tujuan tata bahasa, dengan nama yang sama seperti opsi pada parser JS:

| Nilai | Tujuan |
|---|---|
| `script` | Script klasik. `import`/`export` tingkat teratas adalah kesalahan sintaks, `await` adalah identifier |
| `module` | Modul ES. Secara implisit strict, `import`/`export` dan `await` tingkat teratas dapat di-parse |

Nilai lainnya akan memunculkan `\InvalidArgumentException`.

Untuk kontrol yang lebih terperinci (menetapkan mode strict terlebih dahulu untuk konteks direct-eval, membaca pragma `//# sourceURL`), buat parser secara langsung: `new Parser($source)` beserta `setModuleMode()`, `setStrictMode()`, dan `parse()`.

## Node

Setiap kelas AST memperluas `Phasis\Ast\Node` dan berada di bawah `Phasis\Ast\{Declaration, Expression, Pattern, Statement}`. Node adalah objek nilai readonly biasa:

- `$node->type()` mengembalikan string tipe node, yaitu nama dasar kelas (`'BinaryExpression'`, `'ArrowFunction'`, ...).
- `$node->location` adalah `Phasis\Lexer\SourceLocation` dengan `line` (mulai dari 1), `column` (mulai dari 0), dan `offset` (offset byte). Hanya posisi awal yang disimpan; node tidak memiliki offset akhir.
- Semua field publik lainnya adalah anak dan atribut node (`$binary->left`, `$binary->operator`, `$binary->right`).

Sebagian besar nama tipe sesuai dengan [ESTree](https://github.com/estree/estree). Perbedaannya:

| Tipe Phasis | Tipe ESTree |
|---|---|
| `ArrowFunction` | `ArrowFunctionExpression` |
| `TaggedTemplate` | `TaggedTemplateExpression` |
| `ClassMethod` | `MethodDefinition` |
| `ClassProperty` | `PropertyDefinition` |
| `AssignmentProperty` | `Property` (di dalam `ObjectPattern`) |
| `ExportDeclaration` | `ExportNamedDeclaration` / `ExportDefaultDeclaration` / `ExportAllDeclaration` |
| `ImportSpecifier` | `ImportSpecifier` / `ImportDefaultSpecifier` / `ImportNamespaceSpecifier` |

Beberapa bentuk juga berbeda: isi kelas berupa array elemen biasa pada node kelas (tanpa wrapper `ClassBody`), nama import/export, label pernyataan, dan nama `FunctionExpression` disimpan sebagai string, bukan node `Identifier` bertingkat, dan `super` di-parse sebagai `Identifier` bernama `super` (tidak ada kelas node `Super`). `Phasis\Ast\EstreeSerializer` mengubah semuanya ke bentuk ESTree.

## Kesalahan sintaks

Input yang tidak valid memunculkan `Phasis\Exceptions\SyntaxError` (biasanya subkelasnya, `Phasis\Parser\ParseError`). Pesan exception diakhiri dengan posisi, dan lokasi terstruktur tersedia pada exception:

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

## Penelusur

`Phasis\Ast\Walker` menelusuri pohon secara depth-first dengan callback masuk/keluar, mengikuti gaya estraverse:

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

Kedua callback menerima `(Node $node, ?Node $parent)`. Mengembalikan `Walker::SKIP` dari `$enter` memangkas anak-anak node; callback `$leave` milik node itu sendiri tetap dijalankan.

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

Penelusuran hanya-baca. Node adalah objek nilai readonly, jadi tidak ada dukungan untuk mengganti atau mengubahnya.

## Serializer

`Phasis\Ast\Serializer` mengonversi AST bertipe menjadi array atau JSON menggunakan nama tipe dan tata letak field Phasis, dengan field cache internal parser dihapus:

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

Inilah format yang dicetak oleh `bin/phasis --ast`.

## EstreeSerializer

`Phasis\Ast\EstreeSerializer` mengonversi AST bertipe menjadi array berbentuk ESTree: nama tipe ESTree (sesuai tabel perbedaan di atas), nama dan urutan field ESTree, node `ClassBody` / specifier / source-`Literal` yang disintesis, serta offset byte `start` pada setiap node yang diurai dari sumber. Tidak ada offset `end` karena node hanya menyimpan posisi awal, dan node string `Literal` tidak membawa teks `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()` menghasilkan ringkasan deterministik satu baris per node (tipe ditambah atribut `name=` / `value=` / `op=` / `kind=`, indentasi dua spasi per tingkat kedalaman). Formatnya identik byte demi byte dengan ringkasan AST yang dihasilkan fixture acorn di `tests/Popular/acorn`, sehingga oracle yang sama memeriksa jalur parser JS dan ekspor PHP ini:

```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` mengurai file (tujuan skrip) dan mencetak dump `Serializer` JSON dengan indentasi dua spasi. Lihat [CLIreferensi lengkap semua flag](https://phasis.inline0.dev/id/docs/cli).
