본문으로 건너뛰기

파서

Phasis는 독립 실행형 PHP API로 자체 JavaScript 파서를 제공합니다. 소스 텍스트를 구문 분석해 형식화된 AST로 만들고, 순회한 다음 ESTree 형태의 배열 또는 JSON로 내보낼 수 있습니다. Engine를 생성하거나 코드를 실행하지 않아도 됩니다.

parseSource

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

Phasis\Parser\Parser의 단일 호출 진입점입니다. $source를 구문 분석해 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는 문법 목표를 선택합니다. 이름은 JS 파서의 같은 옵션을 따릅니다:

값 목표
script 일반 Script. 최상위 import/export는 구문 오류이며, await는 식별자입니다
module ES Module. 암시적으로 strict 모드가 적용되며 import/export 및 최상위 await를 구문 분석합니다

그 밖의 값은 \InvalidArgumentException을 발생시킵니다.

직접 평가 컨텍스트에서 strict 모드를 미리 설정하거나 //# sourceURL pragma를 읽는 등 세밀한 제어가 필요하면 파서를 직접 생성하세요: new Parser($source)와 setModuleMode(), setStrictMode(), parse()를 사용합니다.

노드

모든 AST 클래스는 Phasis\Ast\Node를 확장하며 Phasis\Ast\{Declaration, Expression, Pattern, Statement} 아래에 있습니다. 노드는 변경할 수 없는 일반 값 객체입니다:

  • $node->type()는 노드 유형 문자열을 반환합니다. 이는 클래스의 기본 이름입니다('BinaryExpression', 'ArrowFunction' 등).
  • $node->location는 Phasis\Lexer\SourceLocation이며 line(1부터 시작), column(0부터 시작), offset(바이트 오프셋)을 포함합니다. 시작 위치만 저장되므로 노드에는 끝 오프셋이 없습니다.
  • 그 밖의 모든 공개 필드는 노드의 자식 및 속성입니다($binary->left, $binary->operator, $binary->right).

대부분의 유형 이름은 ESTree와 일치합니다. 다른 점은 다음과 같습니다:

Phasis 유형 ESTree 유형
ArrowFunction ArrowFunctionExpression
TaggedTemplate TaggedTemplateExpression
ClassMethod MethodDefinition
ClassProperty PropertyDefinition
AssignmentProperty Property (ObjectPattern 내부)
ExportDeclaration ExportNamedDeclaration / ExportDefaultDeclaration / ExportAllDeclaration
ImportSpecifier ImportSpecifier / ImportDefaultSpecifier / ImportNamespaceSpecifier

일부 구조도 다릅니다. 클래스 본문의 요소 배열은 클래스 노드에 바로 들어갑니다(ClassBody 래퍼 없음). 가져오기/내보내기 이름, 문 레이블, FunctionExpression 이름은 중첩된 Identifier 노드가 아닌 문자열로 저장됩니다. 또한 super는 Identifier라는 이름의 super로 구문 분석됩니다(Super 노드 클래스는 없음). Phasis\Ast\EstreeSerializer는 이 모든 구조를 ESTree 형식으로 변환합니다.

구문 오류

잘못된 입력은 Phasis\Exceptions\SyntaxError을 발생시킵니다(대개 하위 클래스인 Phasis\Parser\ParseError). 예외 메시지 끝에 위치가 표시되며, 예외에서 구조화된 위치 정보를 확인할 수 있습니다:

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
}

워커

Phasis\Ast\Walker는 estraverse 방식의 진입/종료 콜백을 사용해 트리를 깊이 우선으로 순회합니다:

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

두 콜백 모두 (Node $node, ?Node $parent)을 받습니다. $enter에서 Walker::SKIP을 반환하면 노드의 자식 순회를 건너뜁니다. 노드 자체의 $leave은 계속 호출됩니다.

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

순회는 읽기 전용입니다. 노드는 변경할 수 없는 값 객체이므로 교체하거나 수정할 수 없습니다.

직렬화기

Phasis\Ast\Serializer는 형식화된 AST를 배열 또는 JSON로 변환합니다. Phasis 유형 이름과 필드 배치를 사용하며 파서 내부 캐시 필드는 제거합니다:

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

이 형식은 bin/phasis --ast가 출력하는 형식입니다.

EstreeSerializer

Phasis\Ast\EstreeSerializer는 형식화된 AST를 대신 ESTree 형태의 배열로 변환합니다. 위의 차이 표에 따른 ESTree 유형 이름, ESTree 필드 이름과 순서, 합성된 ClassBody / 지정자 / source-Literal 노드, 그리고 소스에서 구문 분석한 각 노드의 start 바이트 오프셋을 포함합니다. 노드에는 시작 위치만 저장되므로 end 오프셋은 없습니다. 문자열 Literal 노드에도 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()는 노드마다 한 줄씩 결정적인 요약을 출력합니다(유형과 name= / value= / op= / kind= 속성, 깊이마다 공백 두 칸 들여쓰기). 형식은 tests/Popular/acorn의 acorn 픽스처가 만드는 AST 요약과 바이트 단위로 동일합니다. 따라서 같은 오라클이 JS 파서 경로와 이 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는 파일(script 목표)을 구문 분석하고 Serializer JSON 덤프를 공백 두 칸 들여쓰기로 출력합니다. 전체 플래그 설명은 CLI를 참조하세요.