Shrubbery syntax adalah fondasi notasi struktural yang digunakan oleh ekosistem Racket modern (termasuk dialek Rhombus) untuk menjembatani keterbacaan sintaksis berbasis indentasi dengan fleksibilitas manipulasi pohon sintaks abstrak (AST) khas S-expression. Ketika tim menggunakan DSL (Domain-Specific Language) berbasis Shrubbery, inkonsistensi spasi atau penempatan operator dapat merusak struktur pohon token sebelum fase kompilasi semantik dimulai. Mengintegrasikan validasi parsing Shrubbery syntax di CI (Continuous Integration) mendeteksi kesalahan sintaksis lebih awal dan mencegah masuknya format rusak ke repositori utama.
Arsitektur Shrubbery Syntax: Tokenisasi, Indentasi, dan Grup
Berbeda dari S-expression tradisional yang hanya bergantung pada tanda kurung (...), parser Shrubbery membagi kode ke dalam tingkatan struktural berbasis indentasi, operator, dan pembatas. Shrubbery tidak langsung menghasilkan representasi semantik, melainkan menghasilkan struktur intermediat bernama shrubbery term.
1. Indentasi dan Baris (Lines and Groups)
Shrubbery mengubah baris bertingkat menjadi struktur grup (group) dan blok (block). Setiap blok diindikasikan oleh baris baru yang memiliki indentasi lebih dalam setelah tanda titik dua (:) atau operator pembuka. Jika indentasi tidak konsisten (misalnya pencampuran tab dan spasi atau level indentasi yang ganjil), tokeniser shrubbery/parse langsung melemparkan error leksikal tanpa melanjutkan ke tahap kompilasi kode Racket.
2. Operator Precedence pada Tingkat Sintaksis
Di S-expression, urutan evaluasi ditentukan sepenuhnya oleh tanda kurung: (+ (* a b) c). Shrubbery memungkinkan notasi infix tanpa membubarkan sifat Lisp-nya. Shrubbery mengelompokkan token berdampingan dan membiarkan macro layer atau resolver tata bahasa menentukan preseden operator berurutan di dalam grup yang sama, asalkan delimitasi grupnya valid.
Script Validasi Syntax Menggunakan Racket
Untuk memvalidasi file DSL berbasis Shrubbery secara programmatic, manfaatkan package shrubbery yang disediakan oleh Racket. Script ini membaca berkas target dan mem-parsing stream menjadi struktur shrubbery. Script mengembalikan exit code 0 jika valid, atau 1 jika terjadi kegagalan parse.
#lang racket/base
(require racket/cmdline
racket/file
shrubbery/parse)
(define (validate-shrubbery file-path)
(with-handlers
([exn:fail:read?
(λ (e)
(eprintf "[ERROR] Syntax error in ~a: ~a\n" file-path (exn-message e))
#f)]
[exn:fail?
(λ (e)
(eprintf "[ERROR] Unexpected error reading ~a: ~a\n" file-path (exn-message e))
#f)])
(call-with-input-file file-path
(λ (in)
(port-count-lines! in)
;; parse-all membaca seluruh file menjadi list of shrubbery groups
(parse-all in)
#t))))
(define (main)
(define files (vector->list (current-command-line-arguments)))
(when (null? files)
(eprintf "Usage: racket validate-shrubbery.rkt <file1.rktl> [...files]\n")
(exit 1))
(define failed? #f)
(for ([file files])
(unless (file-exists? file)
(eprintf "[WARN] File not found: ~a\n" file)
(set! failed? #t))
(when (file-exists? file)
(define ok? (validate-shrubbery file))
(unless ok?
(set! failed? #t))))
(if failed?
(exit 1)
(begin
(displayln "All Shrubbery DSL files parsed successfully.")
(exit 0))))
(main)
Implementasi Pre-commit Hook
Pemeriksaan lokal sebelum kode didorong (pushed) menghemat waktu antrean CI. Buat berkas executable pada .git/hooks/pre-commit atau gunakan framework pengelola hook seperti Husky / pre-commit.
#!/usr/bin/env bash
set -euo pipefail
# Ambil berkas DSL berbasis shrubbery yang ada di stage Git
FILES=$(git diff --cached --name-only --diff-filter=ACM | grep -E '\.(rhm|shrub)$' || true)
if [ -z "$FILES" ]; then
exit 0
fi
echo "Running Shrubbery syntax validation..."
racket scripts/validate-shrubbery.rkt $FILES
Pastikan script hook memiliki hak akses eksekusi menggunakan perintah chmod +x .git/hooks/pre-commit.
Workflow CI Menggunakan GitHub Actions
Langkah validasi di GitHub Actions memastikan tidak ada commit cacat yang lolos dari mesin lokal pengembang. Gunakan runner berbasis Linux dengan instalasi minimal Racket.
name: Validate Shrubbery Syntax
on:
pull_request:
paths:
- '**/*.rhm'
- '**/*.shrub'
- 'scripts/**'
push:
branches:
- main
jobs:
validate-dsl:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Racket
uses: Bogdanp/[email protected]
with:
architecture: 'x64'
distribution: 'minimal'
version: '8.12'
- name: Install Shrubbery Package
run: |
raco pkg install --auto --batch shrubbery
- name: Validate DSL Files
run: |
# Temukan semua file DSL target dan jalankan validator
mapfile -t FILES < <(find . -type f \( -name "*.rhm" -o -name "*.shrub" \))
if [ ${#FILES[@]} -gt 0 ]; then
racket scripts/validate-shrubbery.rkt "${FILES[@]}"
else
echo "No Shrubbery files found to validate."
fi
Kesalahan Umum dan Troubleshooting
- Pencampuran Spasi dan Tab: Shrubbery menolak berkas yang mencampurkan karakter tab dan spasi untuk indentasi dalam scope yang sama. Standardisasi editor config ke 2 atau 4 spasi mutlak diperlukan.
- Line Counting Nonaktif: Pemanggilan
port-count-lines!wajib dipanggil sebelumparse-alldieksekusi pada input port. Jika dilewati, pesan error parser tidak akan menyertakan baris dan kolom yang presisi saat terjadi kesalahan sintaksis. - File Encoding: Parser Shrubbery mengharapkan representasi UTF-8 valid. Berkas dengan byte-order mark (BOM) tertentu dapat memicu
exn:fail:readdi awal pembacaan stream.
Komentar
0 komentar
Masuk ke akun kamu untuk ikut berkomentar.
Belum ada komentar
Jadilah yang pertama ikut berdiskusi!