Lewati ke konten

Ast: pohon dokumen semantik dan serialisasi

Modul Ast menyediakan pohon sintaksis abstrak (AST) dokumen semantik untuk mesin. Modul ini memodelkan dokumen sebagai hierarki simpul dengan tipe berikut: Document, Section, Heading, Paragraph, List, Table, Figure, Code, dan FormField. Model ini mencatat kotak pembatas dan jangkar sitasi, lalu diserialisasi ke JavaScript Object Notation (JSON) berversi. Lapisan penandaan aksesibilitas menggunakan pohon ini untuk menghasilkan pohon struktur.

Stabilitas: eksperimental. Ini adalah permukaan model internal. Kelas-kelasnya tidak memiliki jaminan application programming interface (API) publik yang dibekukan per versi. Kumpulan simpul dan atribut simpul dapat berubah. Skema serialisasi diberi versi secara independen (AstDocument::CURRENT_SCHEMA_VERSION = '1.0.0'). Serializer mendeteksi dan menolak skema yang tidak kompatibel, sehingga JSON AST yang dipersistenkan tetap menjaga kontrak yang stabil bahkan ketika API dalam memori berubah.

Terminal window
composer require nextpdf/core:^3

Di sini, sebuah AST merepresentasikan struktur logis dokumen. Ini bukan pohon sintaksis milik parser untuk satu format masukan. AstDocument adalah kontainernya. Kontainer ini menyimpan AstNode akar (yang harus berupa NodeType::Document), versi skema, hash dari berkas Portable Document Format (PDF) sumber, dan jumlah halaman. Kontainer ini menolak konstruksi yang tidak valid, termasuk versi skema kosong, jumlah halaman di bawah satu, atau tipe akar yang salah.

AstNode adalah simpul rekursif. NodeType menjabarkan jenis-jenis semantiknya. Sebuah simpul membawa anak-anak, BoundingBox opsional, konten teks opsional, dan atribut yang divalidasi oleh NodeAttributeSchema. API simpul mendukung derivasi immutable. withBboxAndText() mengembalikan simpul baru. deepClone() menyalin sebuah subpohon. NodeId adalah identitas value-object. CitationAnchor mengaitkan simpul dengan lokasi sumber demi keterlacakan. AstNodeCollection adalah himpunan Countable/IteratorAggregate dengan penyaringan ofType().

AstSerializer adalah batas persistensi. serialize() menulis sebuah AstDocument ke JSON. deserialize() membacanya kembali. canDeserialize() dan extractSchemaVersion() memungkinkan Anda memeriksa kompatibilitas sebelum mem-parsing, sehingga ketidakcocokan skema menjadi kondisi yang terdeteksi, bukan pemuatan yang rusak. AstDocument::estimateTokenCount() membantu mengukur konten untuk pemrosesan hilir yang dibatasi token.

KelasAnggota utamaPeran
AstDocumenttoJson(), nodeCount(), estimateTokenCount(), CURRENT_SCHEMA_VERSIONKontainer akar; memvalidasi tipe akar dan skema
AstNodeaddChild(), children(), childCount(), totalNodeCount(), withBboxAndText(), deepClone()Simpul semantik rekursif
NodeType (enum)Document, Heading, Table, Figure, FormField, …Jenis simpul semantik
AstNodeCollectionadd(), count(), isEmpty(), ofType(), toArray()Himpunan simpul yang dapat diiterasi dan difilter berdasarkan tipe
AstSerializerserialize(), deserialize(), canDeserialize(), extractSchemaVersion()Persistensi JSON berversi
BoundingBoxtoArray(), equals()Value object geometri (perbandingan epsilon)
NodeId / CitationAnchortoString(), equals(), toArray()Identitas simpul dan jangkar keterlacakan sumber
NodeAttributeSchemavalidasi atributSkema untuk atribut simpul

Jalankan composer docs:generate-api-php -- --module=Ast untuk menghasilkan tabel PHPDoc lengkap.

Bangun pohon kecil, lalu serialisasikan.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Ast\AstNode;
use NextPDF\Ast\AstSerializer;
use NextPDF\Ast\NodeType;
$root = new AstNode(NodeType::Document);
$heading = new AstNode(NodeType::Heading);
$root->addChild($heading);
$root->addChild(new AstNode(NodeType::Paragraph));
echo "Nodes: {$root->totalNodeCount()}\n";
$json = (new AstSerializer())->serialize(/* an AstDocument wrapping $root */);

Lakukan round-trip AST yang dipersistenkan secara defensif. Periksa kompatibilitas skema sebelum Anda mendeserialisasi JSON yang tidak tepercaya.

<?php
declare(strict_types=1);
require_once __DIR__ . '/../vendor/autoload.php';
use NextPDF\Ast\AstDocument;
use NextPDF\Ast\AstSerializer;
use Psr\Log\LoggerInterface;
final readonly class AstStore
{
public function __construct(
private AstSerializer $serializer,
private LoggerInterface $logger,
) {}
public function load(string $json): ?AstDocument
{
if (!$this->serializer->canDeserialize($json)) {
$this->logger->warning('AST JSON schema incompatible; rejected.', [
'found_schema' => $this->serializer->extractSchemaVersion($json),
'expected' => AstDocument::CURRENT_SCHEMA_VERSION,
]);
return null;
}
return $this->serializer->deserialize($json);
}
}
  • AstDocument mengharuskan simpul akar berupa NodeType::Document. Pohon dengan akar lain mana pun akan melempar saat dikonstruksi.
  • AstNode::withBboxAndText() dan deepClone() mengembalikan instans baru. Mutator simpul yang tersedia (addChild()) memutasi simpul. Helper derivasi tidak. Pastikan metode mana yang Anda panggil.
  • Selalu jaga deserialize() dengan canDeserialize() untuk JSON yang berasal dari luar. Ketidakcocokan versi skema adalah kondisi yang dapat dideteksi dan diharapkan.
  • estimateTokenCount() adalah perkiraan untuk mengukur pemrosesan hilir, bukan hitungan tokenizer yang persis. Jangan menganggapnya otoritatif.
  • BoundingBox::equals() adalah perbandingan epsilon (standar 0.001). Kesamaan float yang persis bukanlah kontraknya.

Konstruksi dan penelusuran pohon adalah O(n) terhadap jumlah simpul. Serialisasi bersifat linear terhadap ukuran pohon. Profil reprodusibilitasnya adalah bitwise. Pohon yang sama diserialisasi menjadi byte JSON yang sama, sehingga skema tetap stabil sebagai kontrak persistensi. Beban kerja referensi standar tetap jauh di bawah anggaran 1500 ms wall / 64 MB puncak.

AstSerializer::deserialize() mem-parsing JSON yang mungkin dipersistenkan atau ditransmisikan. Validasi kompatibilitas dengan canDeserialize() terlebih dahulu. Perlakukan konten teks dan atribut dari pohon yang dideserialisasi sebagai string yang tidak tepercaya ketika masuk kembali ke aplikasi atau dirender. Modul ini sendiri tidak melakukan input/output (I/O) dan tidak menyematkan data eksternal apa pun. Lihat model ancaman mesin di /modules/core/security/.

Modul ini tidak menegaskan klaim normatif spesifikasi PDF apa pun. AST semantik adalah abstraksi internal mesin. Modul ini tidak mengimplementasikan model dokumen terstandardisasi yang klausa-klausanya harus disitasi. Ketika AST memasok penandaan aksesibilitas, konformansi PDF/UA dan tagged-PDF dari keluaran didokumentasikan dan divalidasi di /modules/core/accessibility/ dan /modules/core/conformance/, bukan di sini.