
# Analyseur syntaxique

Phasis expose son analyseur JavaScript sous la forme d’un PHP API autonome. Vous pouvez analyser du code source pour obtenir un AST typé, le parcourir et l’exporter sous forme de tableaux compatibles avec ESTree ou de JSON, sans construire de `Engine` ni rien exécuter.

## parseSource

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

Le point d’entrée qui effectue l’opération en un seul appel sur `Phasis\Parser\Parser`. Analyse `$source` et renvoie le nœud racine `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` sélectionne l’objectif grammatical, nommé d’après l’option équivalente dans les analyseurs JS :

| Valeur | Objectif |
|---|---|
| `script` | Script classique. Les `import`/`export` au niveau supérieur sont des erreurs de syntaxe ; `await` est un identifiant |
| `module` | Module ES. Strict implicitement ; `import`/`export` et `await` au niveau supérieur sont analysés |

Toute autre valeur déclenche `\InvalidArgumentException`.

Pour un contrôle plus fin (activer le mode strict à l’avance pour un contexte d’évaluation directe, lire le pragma `//# sourceURL`), construisez directement l’analyseur : `new Parser($source)` ainsi que `setModuleMode()`, `setStrictMode()` et `parse()`.

## Nœuds

Chaque classe AST étend `Phasis\Ast\Node` et se trouve sous `Phasis\Ast\{Declaration, Expression, Pattern, Statement}`. Les nœuds sont de simples objets valeur en lecture seule :

- `$node->type()` renvoie la chaîne de type du nœud, qui correspond au nom de base de sa classe (`'BinaryExpression'`, `'ArrowFunction'`, ...).
- `$node->location` est un `Phasis\Lexer\SourceLocation` avec `line` (à partir de 1), `column` (à partir de 0) et `offset` (décalage en octets). Seules les positions de début sont stockées ; les nœuds ne comportent pas de décalage de fin.
- Tous les autres champs publics sont les enfants et attributs du nœud (`$binary->left`, `$binary->operator`, `$binary->right`).

La plupart des noms de type correspondent à ceux d’[ESTree](https://github.com/estree/estree). Voici les différences :

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

Quelques formes diffèrent également : les corps de classe sont un simple tableau d’éléments sur le nœud de classe (sans wrapper `ClassBody`) ; les noms d’import/export, les étiquettes d’instruction et les noms `FunctionExpression` sont stockés sous forme de chaînes plutôt que de nœuds `Identifier` imbriqués ; et `super` est analysé comme un `Identifier` nommé `super` (il n’existe pas de classe de nœud `Super`). `Phasis\Ast\EstreeSerializer` remodèle tout cela selon le format ESTree.

## Erreurs de syntaxe

Une entrée invalide déclenche `Phasis\Exceptions\SyntaxError` (généralement sa sous-classe `Phasis\Parser\ParseError`). Le message d’exception se termine par la position, et l’exception contient l’emplacement structuré :

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

## Parcoureur

`Phasis\Ast\Walker` parcourt un arbre en profondeur, avec des rappels à l’entrée et à la sortie, selon le modèle d’estraverse :

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

Les deux rappels reçoivent `(Node $node, ?Node $parent)`. Renvoyer `Walker::SKIP` depuis `$enter` ignore les enfants du nœud ; le rappel `$leave` du nœud lui-même est néanmoins exécuté.

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

Le parcours est en lecture seule. Les nœuds sont des objets valeur en lecture seule ; il n’est donc pas possible de les remplacer ni de les modifier.

## Sérialiseur

`Phasis\Ast\Serializer` convertit l’AST typé en tableaux ou en JSON en utilisant les noms de type et la structure des champs de Phasis, après suppression des champs de cache internes à l’analyseur :

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

C’est le format affiché par `bin/phasis --ast`.

## EstreeSerializer

`Phasis\Ast\EstreeSerializer` convertit plutôt l’AST typé en tableaux au format ESTree : noms de type ESTree (selon le tableau des différences ci-dessus), noms et ordre des champs ESTree, nœuds `ClassBody` / spécificateur / source-`Literal` synthétisés, et décalage en octets `start` pour chaque nœud analysé depuis le code source. Il n’y a pas de décalages `end`, car les nœuds ne stockent que les positions de début ; les nœuds de chaîne `Literal` ne contiennent pas de texte `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()` produit un résumé déterministe avec une ligne par nœud (type et attributs `name=` / `value=` / `op=` / `kind=`, indentation de deux espaces par niveau). Le format est identique octet pour octet au résumé AST produit par la fixture acorn dans `tests/Popular/acorn` ; le même oracle sert donc à vérifier le parcours d’analyse JS et cet 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` analyse un fichier (objectif Script) et affiche le dump `Serializer` JSON avec une indentation de deux espaces. Consultez [CLI](https://phasis.inline0.dev/fr/docs/cli) pour la référence complète des options.
