
# Analizator sintactic

Phasis oferă analizatorul său JavaScript ca PHP API independent. Puteți analiza textul sursă într-un AST tipizat, îl puteți parcurge și exporta ca tablouri în format ESTree sau JSON fără să construiți un `Engine` și fără să executați nimic.

## parseSource

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

Punctul de intrare cu un singur apel din `Phasis\Parser\Parser`. Analizează `$source` și returnează nodul rădăcină `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` selectează obiectivul gramatical, denumit după aceeași opțiune din analizatoarele JS:

| Valoare | Obiectiv |
|---|---|
| `script` | script clasic. `import`/`export` de nivel superior sunt erori de sintaxă, `await` este un identificator |
| `module` | modul ES. Strict implicit; `import`/`export` și `await` de nivel superior sunt analizate |

Orice altă valoare aruncă `\InvalidArgumentException`.

Pentru control mai fin (activarea modului strict în prealabil pentru un context direct-eval, citirea directivei `//# sourceURL`), construiți direct analizatorul: `new Parser($source)` plus `setModuleMode()`, `setStrictMode()` și `parse()`.

## Noduri

Fiecare clasă AST extinde `Phasis\Ast\Node` și se află în `Phasis\Ast\{Declaration, Expression, Pattern, Statement}`. Nodurile sunt obiecte simple, doar pentru citire:

- `$node->type()` returnează șirul tipului nodului, care este numele de bază al clasei (`'BinaryExpression'`, `'ArrowFunction'`, ...).
- `$node->location` este un `Phasis\Lexer\SourceLocation` cu `line` (de la 1), `column` (de la 0) și `offset` (poziția în octeți). Sunt stocate doar pozițiile de început; nodurile nu conțin poziția de sfârșit.
- Toate celelalte câmpuri publice sunt copiii și atributele nodului (`$binary->left`, `$binary->operator`, `$binary->right`).

Majoritatea numelor de tip se potrivesc cu [ESTree](https://github.com/estree/estree). Abaterile:

| Tip Phasis | Tip ESTree |
|---|---|
| `ArrowFunction` | `ArrowFunctionExpression` |
| `TaggedTemplate` | `TaggedTemplateExpression` |
| `ClassMethod` | `MethodDefinition` |
| `ClassProperty` | `PropertyDefinition` |
| `AssignmentProperty` | `Property` (în interiorul lui `ObjectPattern`) |
| `ExportDeclaration` | `ExportNamedDeclaration` / `ExportDefaultDeclaration` / `ExportAllDeclaration` |
| `ImportSpecifier` | `ImportSpecifier` / `ImportDefaultSpecifier` / `ImportNamespaceSpecifier` |

Și câteva forme diferă: corpurile claselor sunt un tablou simplu de elemente pe nodul clasei (fără wrapper `ClassBody`); numele de import/export, etichetele instrucțiunilor și numele `FunctionExpression` sunt stocate ca șiruri, nu ca noduri `Identifier` imbricate; iar `super` este analizat ca `Identifier` numit `super` (nu există o clasă de nod `Super`). `Phasis\Ast\EstreeSerializer` remodelează toate acestea în formatul ESTree.

## Erori de sintaxă

O intrare nevalidă aruncă `Phasis\Exceptions\SyntaxError` (de obicei subclasa sa `Phasis\Parser\ParseError`). Mesajul excepției se termină cu poziția, iar localizarea structurată este disponibilă în excepție:

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

## Parcurgător

`Phasis\Ast\Walker` parcurge arborele în adâncime, cu apeluri inverse la intrare și la ieșire, după modelul estraverse:

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

Ambele apeluri inverse primesc `(Node $node, ?Node $parent)`. Returnarea lui `Walker::SKIP` din `$enter` omite copiii nodului; apelul invers propriu al nodului pentru `$leave` este totuși executat.

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

Parcurgerea este doar pentru citire. Nodurile sunt obiecte de valoare doar pentru citire, deci nu există funcționalitate de înlocuire sau modificare.

## Serializator

`Phasis\Ast\Serializer` convertește AST-ul tipizat în tablouri sau JSON, folosind numele de tip și structura câmpurilor Phasis, după eliminarea câmpurilor cache interne analizatorului:

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

Acesta este formatul afișat de `bin/phasis --ast`.

## EstreeSerializer

`Phasis\Ast\EstreeSerializer` convertește AST-ul tipizat în tablouri în format ESTree: nume de tip ESTree (conform tabelului de abateri de mai sus), nume și ordine a câmpurilor ESTree, noduri `ClassBody` / specifier / source-`Literal` sintetizate și o poziție în octeți `start` pentru fiecare nod analizat din sursă. Nu există poziții `end` deoarece nodurile stochează doar pozițiile de început, iar nodurile `Literal` de tip șir nu conțin textul `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()` generează un rezumat determinist, cu un singur rând per nod (tip plus atributele `name=` / `value=` / `op=` / `kind=`, indentare de două spații pentru fiecare nivel de adâncime). Formatul este identic la nivel de octet cu rezumatul AST produs de fixture-ul acorn din `tests/Popular/acorn`, astfel încât același oracle verifică atât calea analizatorului JS, cât și acest 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` analizează un fișier (obiectiv de tip script) și afișează rezultatul `Serializer` JSON, cu indentare de două spații. Consultați [CLI](https://phasis.inline0.dev/ro/docs/cli) pentru referința completă a opțiunilor.
