Path Object Notation
Panduan Super Lengkap
Format Data Sederhana untuk Segala Kebutuhan
Versi 1.0 • Spesifikasi Formal

Muhammad Arif Budianto
Pengembang & Perancang PON
29 Juli 2026
🏆 Dikembangkan Pertama Kali oleh Muhammad Arif Budianto
⚠️ PON dibuat BUKAN untuk menggantikan format data modern yang sudah ada,
melainkan sebagai alternatif pelengkap yang lebih sederhana untuk kebutuhan tertentu.
"Menyederhanakan yang Kompleks,
Menjelaskan yang Tersembunyi"

Klik tombol di atas, lalu pilih "Save as PDF" pada dialog print

📖 Daftar Isi

1. Pengenalan PON

1.1 Apa itu PON?

Path Object Notation (PON) adalah sebuah format data terstruktur yang dirancang untuk menjadi sederhana, ekspresif, dan human-friendly. PON menggabungkan kemudahan penulisan dengan kekuatan type safety dan default values yang terintegrasi.

PON lahir dari kebutuhan akan format data yang dapat:

💡 Inti PON dalam satu baris:

/path:type = value;

Sederhana, namun mampu merepresentasikan struktur data yang sangat kompleks.

📌 PON adalah:

1.2 Sejarah & Latar Belakang

PON dirancang dan dikembangkan pertama kali oleh Muhammad Arif Budianto sebagai solusi atas keterbatasan format data yang ada. Perjalanan pengembangan PON didasari oleh pengalaman panjang dalam bekerja dengan berbagai format data di berbagai proyek.

Masalah yang Dihadapi

Format Masalah Utama Dampak
XML Terlalu verbose, tag berulang, ukuran file besar Sulit dibaca, mahal untuk transfer data
JSON Tidak ada tipe data eksplisit, array 1 elemen ambigu Kesalahan parsing, boilerplate validasi
YAML Bergantung pada indentasi yang rawan error Sering terjadi kesalahan konfigurasi
CSV Tidak support hierarki, tidak ada tipe data Tidak cocok untuk data kompleks
Table Data Hanya untuk data tabular, tidak fleksibel Sulit untuk data yang tidak seragam
⚠️ Akibat dari masalah tersebut:

Dari pengalaman inilah Muhammad Arif Budianto merancang PON sebagai format data yang menjawab semua masalah tersebut dengan pendekatan yang sederhana namun powerful.

1.3 Visi, Misi & Tujuan

Visi

"Menjadi format data pelengkap yang memudahkan developer dalam menulis, membaca, dan memahami data terstruktur."

Misi

  1. Menyediakan format data yang sederhana — Sintaks minimalis namun cukup ekspresif untuk segala kebutuhan.
  2. Mengurangi boilerplate code — Dengan type safety dan default values yang terintegrasi.
  3. Membuat data self-documenting — Struktur dan tipe data terlihat jelas dari formatnya sendiri.
  4. Menjembatani kesenjangan — Antara data hierarkis dan data tabular.
  5. Mendukung berbagai skenario — Dari konfigurasi sederhana hingga data ilmiah yang kompleks.
  6. Melengkapi ekosistem — Bukan menggantikan format yang sudah ada.

Tujuan PON

📝

Memudahkan

Penulisan data terstruktur tanpa alat bantu

👀

Menyederhanakan

Pembacaan data kompleks dengan jelas

🔗

Menjembatani

Data hierarkis dan tabular dalam satu format

1.4 PON BUKAN Pengganti Format Lain

⚠️ PENTING UNTUK DIPAHAMI:

PON dibuat BUKAN untuk menggantikan format data modern yang sudah ada seperti XML, JSON, YAML, CSV, atau format lainnya.

💡 Filosofi PON terkait format lain:

"Kami tidak datang untuk menggantikan, kami datang untuk melengkapi. Setiap format memiliki keunggulannya masing-masing. PON hadir sebagai pilihan tambahan ketika Anda menginginkan kesederhanaan, kejelasan, dan kemudahan tanpa mengorbankan kekuatan."

— Muhammad Arif Budianto, Perancang PON

2. Filosofi & Keunggulan

2.1 Filosofi Desain

PON dibangun di atas empat pilar filosofi yang menjadi landasan setiap keputusan desain:

Pilar Makna Implementasi
🎯 Sederhana Sintaks minimalis, tidak berlebihan Hanya 9 simbol dasar, 1 format utama: /path:type = value;
🔍 Eksplisit Tipe data dan path jelas terlihat :type dan /path selalu eksplisit di setiap level
🔄 Konsisten Satu cara untuk satu tujuan Aturan yang sama untuk semua level hierarki
👤 Human-Friendly Mudah dibaca dan ditulis manusia Sintaks natural, error messages jelas, self-documenting
💡 Prinsip Desain PON:

2.2 Keunggulan Utama

📝

Mudah Ditulis

Sintaks minimalis tanpa kurung kurawal berlebihan. Cukup /path:type = value;

👀

Mudah Dibaca

Hierarki jelas dengan path, tipe data eksplisit, dan format yang natural.

🛡️

Type Safety

20+ tipe data dengan alias, menghindari ambiguitas seperti di JSON/XML.

⚙️

Default Values

Nilai default terintegrasi, mengurangi boilerplate code untuk validasi data.

📊

Array Multidimensi

Support array 1D, 2D, multidimensi, dan jagged dengan sintaks yang natural.

🔗

Konversi Mudah

Dapat dikonversi ke XML, JSON, CSV, YAML, dan format lainnya dengan mudah.

📚

Self-Documenting

Struktur dan tipe data terlihat jelas dari formatnya, tanpa dokumentasi terpisah.

Efisien

Ukuran file 70-90% lebih kecil dari XML, parsing lebih cepat.

3. Sintaks & Tipe Data

3.1 Notasi Dasar

Simbol Nama Fungsi Contoh
/ Path Hierarki data /root/user
@ Atribut Metadata /user/@id
: Tipe Data Type annotation :string, :int
[] Array Koleksi data :int[], :float[2,3]
() Non-Array Object (nama:string)
, Separator Pemisah nilai 1,2,3
; Terminator Akhir statement value;
# Komentar Dokumentasi # komentar
= Assignment Memberi nilai = "Budi"
📝 Catatan Penting: Setiap statement harus diakhiri dengan ; (terminator). Ini memudahkan parsing dan mencegah ambiguitas.

Struktur Dasar

# Format dasar PON
/path:type = value;

# Contoh-contoh
/nama:string = "Budi Santoso";
/umur:int = 25;
/aktif:bool = true;
/gaji:decimal = 15000000.50;
/tanggal_lahir:date = "1990-05-15";

3.2 Tipe Data Lengkap

PON memiliki 24 tipe data yang mencakup berbagai kebutuhan:

Kategori Tipe Alias Contoh
Boolean bool boolean true, false
char wchar, char16 'A', '\u0041;'
String string - "Hello World"
DateTime datetime - "2024-01-15T14:30:00Z"
date - "2024-01-15"
time - "14:30:00"
unixtime - 1705314600
Variant object variant, any "string" atau 123 atau true
Integer byte sbyte, int8, i8 100 (-128 sd 127)
ubyte uint8, u8 200 (0 sd 255)
short int16, i16 1000 (-32768 sd 32767)
ushort uint16, u16 50000 (0 sd 65535)
integer int, int32, i32 100000 (-2^31 sd 2^31-1)
uinteger uint, uint32, u32 3000000000 (0 sd 2^32-1)
long int64, i64 10000000000 (-2^63 sd 2^63-1)
ulong uint64, u64 18000000000000000000 (0 sd 2^64-1)
Floating float single, float32, f32 3.14 (7 digit presisi)
double float64, f64 3.141592653589793 (15-16 digit)
decimal decimal128, currency 15000000.50 (28-29 digit)

Type Inference (Inferensi Tipe Otomatis)

# Numerik → double (paling aman)
/nilai = 12345;           # → double

# Leading zero → string (mempertahankan format)
/kode = 0123456789;       # → string
/telepon = 08123456789;   # → string

# Boolean → bool
/aktif = true;            # → bool
/nonaktif = false;        # → bool

# String dengan quote → string
/nama = "Budi";           # → string
/alamat = 'Jakarta';      # → string

3.3 Aturan Penamaan

Aturan Key dan Atribut:

Contoh Valid & Invalid

✅ Valid:
/nama
/nama_lengkap
/_internal
/user_name
/nama123
/user_profile
/alamat_rumah
❌ Invalid:
/123nama     # Diawali angka
/nama/user   # Mengandung /
/nama@user   # Mengandung @
/nama:user   # Mengandung :
/nama,user   # Mengandung ,
/nama;user   # Mengandung ;
/nama#user   # Mengandung #

4. Struktur Data

4.1 Path & Hierarki

/root
  ├── perusahaan
  │   ├── nama
  │   └── alamat
  │       ├── kota
  │       └── kode
  ├── karyawan[]  # Array of objects
  │   ├── [0]
  │   │   ├── @id
  │   │   ├── nama
  │   │   └── umur
  │   └── [1]
  │       ├── @id
  │       ├── nama
  │       └── umur
  └── barang[]    # Array of primitives

Contoh Path

# Root level
/root = value;

# Level 1
/root/user = value;

# Level 2
/root/user/profile = value;

# Level 3
/root/user/profile/address = value;

# Level n (maksimum rekomendasi: 5-7 level)
/root/a/b/c/d/e = "deep";

4.2 Object (Non-Array)

Object di PON menggunakan () untuk mengelompokkan fields menjadi satu entitas.

# Single object sederhana
/root/karyawan(
    nama:string = "Budi Santoso";
    umur:int = 25;
    aktif:bool = true
);

# Object dengan atribut
/root/karyawan(
    @id:int = 1;
    @department:string = "IT";
    nama:string = "Budi Santoso";
    umur:int = 25
);

# Nested object (object di dalam object)
/root/karyawan(
    nama:string = "Budi Santoso";
    alamat(
        jalan:string = "Jl. Merdeka No. 10";
        kota:string = "Bandung";
        kode:string = "40123"
    )
);

# Object dengan array di dalamnya
/root/karyawan(
    nama:string = "Budi Santoso";
    hobi:string[] = "coding","gaming","reading";
    nilai:int[] = 85,90,78
);

4.3 Array & Koleksi

Array 1D

# Array dinamis (ukuran tidak tetap)
/root/nilai:int[] = 85,90,78,92;
/root/nama:string[] = "Budi","Siti","Andi";

# Array dengan ukuran tetap
/root/nilai:int[3] = 85,90,78;

# Array kosong
/root/kosong:int[] = ;

# Array dengan default (ukuran tetap)
/root/nol:int[5] = ;  # [0,0,0,0,0]

Array Multidimensi

# Matrix 2x3
/root/matrix:float[2,3] = 1,2,3; 4,5,6;

# Visual mapping:
# [2,3] → 2 baris, 3 kolom
# 1,2,3; → Baris 1
# 4,5,6; → Baris 2

# Matrix 3x3
/root/matrix:int[3,3] = 1,2,3; 4,5,6; 7,8,9;

# 3D Array (cube)
/root/cube:float[2,2,2] = 1,2; 3,4; 5,6; 7,8;

# Jagged array (array of arrays, baris bisa beda panjang)
/root/jagged:double[][] = 1,2,3; 4,5; 6,7,8,9;

Array of Objects

# Array of objects dengan skema
/root/karyawan[
    @id:int = 0;
    nama:string;
    umur:int = 0;
    alamat/kota:string = "";
    alamat/kode:string = ""
] =
1,"Budi Santoso",25,"Bandung","40123";
2,"Siti Rahayu",23,"Jakarta","10220";
3,"Andi Wijaya",,"Bandung";  # umur default 0

# Array of objects dengan nested object
/root/karyawan[
    @id:int;
    nama:string;
    alamat(
        kota:string;
        kode:string
    )
] =
1,"Budi Santoso",("Bandung","40123");
2,"Siti Rahayu",("Jakarta","10220");

4.4 Default Values

Default values di PON memungkinkan Anda menentukan nilai fallback jika data tidak tersedia atau kosong.

# Deklarasi default di skema
/root/karyawan[
    @id:int = 0;          # Default 0 jika tidak ada
    nama:string;           # Required (tidak ada default)
    umur:int = 0;          # Default 0
    aktif:bool = true;    # Default true
    alamat/kota:string = "";  # Default string kosong
    alamat/kode:string = ""   # Default string kosong
]

# Data yang menggunakan default
= 1,"Budi Santoso",,"Jakarta";      # umur → 0 (default)
= 2,"Siti Rahayu",, ,"40123";       # umur → 0, kota → "" (default)
= 3,"Andi Wijaya",,;                # umur → 0, kota → "", kode → ""
💡 Tips Default Values:

5. Tutorial Lengkap

5.1 Memulai dengan PON

Langkah 1: Tulis Data Sederhana

# file: data.pon
/root/nama:string = "Budi Santoso";
/root/umur:int = 25;
/root/aktif:bool = true;
/root/gaji:decimal = 15000000.50;

Langkah 2: Tambahkan Struktur

/root/karyawan(
    @id:int = 1;
    nama:string = "Budi Santoso";
    alamat(
        kota:string = "Bandung";
        kode:string = "40123"
    )
);

Langkah 3: Gunakan Array

/root/karyawan[
    @id:int;
    nama:string;
    umur:int
] =
1,"Budi Santoso",25;
2,"Siti Rahayu",23;
3,"Andi Wijaya",30;

Langkah 4: Tambahkan Kompleksitas

/root/perusahaan(
    nama:string = "PT Teknologi Maju";
    alamat(
        kota:string = "Jakarta";
        kode:string = "10220"
    );
    karyawan[
        @id:int;
        nama:string;
        jabatan:string;
        gaji:decimal = 0;
        alamat(
            kota:string;
            kode:string
        );
        aktif:bool = true
    ] =
        1,"Budi Santoso","Manager",15000000,("Jakarta","10220"),true;
        2,"Siti Rahayu","Developer",12000000,("Bandung","40123"),true;
        3,"Andi Wijaya","Staff",8000000,("Surabaya","60111"),false
);
💡 Tips Belajar PON:

5.2 Contoh Praktis

Contoh 1: Data Pengguna

/root/users[
    @id:int;
    username:string;
    email:string;
    password:string = "";
    active:bool = true;
    last_login:datetime = "";
    roles:string[] = "user"
] =
1,"budi","budi@mail.com","hash123",true,"2024-01-15T14:30:00Z",("user","admin");
2,"siti","siti@mail.com","hash456",true,"2024-01-14T10:00:00Z",("user");
3,"andi","andi@mail.com","hash789",false,,("user");

Contoh 2: Data Produk

/root/products[
    @id:int;
    name:string;
    price:decimal = 0;
    stock:int = 0;
    category:string = "General";
    tags:string[] = ;
    variants[
        @id:int;
        name:string;
        price:decimal;
        stock:int
    ] = ;
    active:bool = true
] =
1,"Laptop Pro",15000000,10,"Electronics",("laptop","premium","gaming"),
[(1,"8GB RAM",15000000,5),(2,"16GB RAM",17000000,3),(3,"32GB RAM",19000000,2)],true;
2,"Mouse Wireless",250000,50,"Accessories",("mouse","wireless","ergonomic"),
[(1,"Black",250000,30),(2,"White",250000,20)],true;
3,"Keyboard Mechanical",500000,20,"Accessories",("keyboard","mechanical","rgb"),[],true;

6. Perbandingan Format Data

Untuk memahami keunggulan PON, mari kita bandingkan dengan format data lain yang umum digunakan.

6.1 PON vs XML

XML

<root>
    <nama>Budi</nama>
    <umur>25</umur>
    <aktif>true</aktif>
</root>
<root>
    <karyawan id="1">
        <nama>Budi</nama>
        <umur>25</umur>
    </karyawan>
    <karyawan id="2">
        <nama>Siti</nama>
        <umur>23</umur>
    </karyawan>
</root>

PON

/root/nama:string = "Budi";
/root/umur:int = 25;
/root/aktif:bool = true;
/root/karyawan[
    @id:int;
    nama:string;
    umur:int
] =
1,"Budi",25;
2,"Siti",23;
✅ Keunggulan PON vs XML:

6.2 PON vs JSON

JSON

{
  "root": {
    "user": {
      "name": "Budi",
      "age": 25,
      "active": true,
      "address": {
        "city": "Bandung",
        "zip": "40123"
      }
    }
  }
}

PON

/root/user/name:string = "Budi";
/root/user/age:int = 25;
/root/user/active:bool = true;
/root/user/address/city:string = "Bandung";
/root/user/address/zip:string = "40123";
✅ Keunggulan PON vs JSON:

6.3 PON vs YAML

YAML

root:
  user:
    name: Budi
    age: 25
    active: true
    address:
      city: Bandung
      zip: 40123

PON

/root/user/name:string = "Budi";
/root/user/age:int = 25;
/root/user/active:bool = true;
/root/user/address/city:string = "Bandung";
/root/user/address/zip:string = "40123";
✅ Keunggulan PON vs YAML:

6.4 PON vs CSV

CSV

id,nama,umur,kota
1,Budi,25,Bandung
2,Siti,23,Jakarta
3,Andi,30,Bandung

PON

/root/karyawan[
    @id:int;
    nama:string;
    umur:int;
    alamat/kota:string
] =
1,"Budi",25,"Bandung";
2,"Siti",23,"Jakarta";
3,"Andi",30,"Bandung";
✅ Keunggulan PON vs CSV:

6.5 PON vs Table Data

Table Data

+----+-------+------+----------+
| id | nama  | umur | kota     |
+----+-------+------+----------+
| 1  | Budi  | 25   | Bandung  |
| 2  | Siti  | 23   | Jakarta  |
| 3  | Andi  | 30   | Bandung  |
+----+-------+------+----------+

PON

/root/karyawan[
    @id:int;
    nama:string;
    umur:int;
    alamat/kota:string
] =
1,"Budi",25,"Bandung";
2,"Siti",23,"Jakarta";
3,"Andi",30,"Bandung";
✅ Keunggulan PON vs Table Data:

7. Struktur Dasar vs Bahasa Pemrograman

Berikut adalah padanan struktur dasar PON (single type, array, dan object) dengan berbagai bahasa pemrograman.

7.1 C#

PON C# Contoh
/nama:string = "Budi" string string nama = "Budi";
/umur:int = 25 int int umur = 25;
/nilai:float = 3.14 float float nilai = 3.14f;
/aktif:bool = true bool bool aktif = true;
/data:int[] = 1,2,3 int[] int[] data = {1,2,3};
/user( nama:string = "Budi"; umur:int = 25 ) class class User { string Nama {get;set;} int Umur {get;set;} }

Contoh Lengkap C#

// PON
/root/karyawan[
    @id:int;
    nama:string;
    umur:int;
    aktif:bool = true
] =
1,"Budi",25,true;
2,"Siti",23,true;
// C# Class
public class Karyawan
{
    public int Id { get; set; }
    public string Nama { get; set; }
    public int Umur { get; set; }
    public bool Aktif { get; set; } = true;
}

// List of objects
List<Karyawan> karyawan = new List<Karyawan>
{
    new Karyawan { Id = 1, Nama = "Budi", Umur = 25, Aktif = true },
    new Karyawan { Id = 2, Nama = "Siti", Umur = 23, Aktif = true }
};

7.2 VB.NET

PON VB.NET Contoh
/nama:string = "Budi" String Dim nama As String = "Budi"
/umur:int = 25 Integer Dim umur As Integer = 25
/aktif:bool = true Boolean Dim aktif As Boolean = True
/data:int[] = 1,2,3 Integer() Dim data() As Integer = {1,2,3}
/user(nama:string = "Budi"; umur:int = 25) Class Class User Public Property Nama As String ...

Contoh Lengkap VB.NET

' VB.NET Class
Public Class Karyawan
    Public Property Id As Integer
    Public Property Nama As String
    Public Property Umur As Integer
    Public Property Aktif As Boolean = True
End Class

' List of objects
Dim karyawan As New List(Of Karyawan) From {
    New Karyawan With {.Id = 1, .Nama = "Budi", .Umur = 25, .Aktif = True},
    New Karyawan With {.Id = 2, .Nama = "Siti", .Umur = 23, .Aktif = True}
}

7.3 Java

PON Java Contoh
/nama:string = "Budi" String String nama = "Budi";
/umur:int = 25 int int umur = 25;
/aktif:bool = true boolean boolean aktif = true;
/data:int[] = 1,2,3 int[] int[] data = {1,2,3};
/user(nama:string = "Budi"; umur:int = 25) class class User { String nama; int umur; }

Contoh Lengkap Java

// Java Class
public class Karyawan {
    private int id;
    private String nama;
    private int umur;
    private boolean aktif = true;
    
    // Constructor, getters, setters
}

// List of objects
List<Karyawan> karyawan = Arrays.asList(
    new Karyawan(1, "Budi", 25, true),
    new Karyawan(2, "Siti", 23, true)
);

7.4 Python

PON Python Contoh
/nama:string = "Budi" str nama = "Budi"
/umur:int = 25 int umur = 25
/aktif:bool = true bool aktif = True
/data:int[] = 1,2,3 list data = [1,2,3]
/user(nama:string = "Budi"; umur:int = 25) dict / dataclass {"nama": "Budi", "umur": 25}

Contoh Lengkap Python

# Python Dataclass
from dataclasses import dataclass

@dataclass
class Karyawan:
    id: int
    nama: str
    umur: int
    aktif: bool = True

# List of objects
karyawan = [
    Karyawan(id=1, nama="Budi", umur=25, aktif=True),
    Karyawan(id=2, nama="Siti", umur=23, aktif=True)
]

7.5 JavaScript

PON JavaScript Contoh
/nama:string = "Budi" string const nama = "Budi";
/umur:int = 25 number const umur = 25;
/aktif:bool = true boolean const aktif = true;
/data:int[] = 1,2,3 Array const data = [1,2,3];
/user(nama:string = "Budi"; umur:int = 25) Object { nama: "Budi", umur: 25 }

Contoh Lengkap JavaScript

// JavaScript Object
class Karyawan {
    constructor(id, nama, umur, aktif = true) {
        this.id = id;
        this.nama = nama;
        this.umur = umur;
        this.aktif = aktif;
    }
}

// Array of objects
const karyawan = [
    new Karyawan(1, "Budi", 25, true),
    new Karyawan(2, "Siti", 23, true)
];

7.6 Rust

PON Rust Contoh
/nama:string = "Budi" String let nama = String::from("Budi");
/umur:int = 25 i32 let umur: i32 = 25;
/aktif:bool = true bool let aktif: bool = true;
/data:int[] = 1,2,3 Vec<i32> let data = vec![1,2,3];
/user(nama:string = "Budi"; umur:int = 25) struct struct User { nama: String, umur: i32 }

Contoh Lengkap Rust

// Rust Struct
#[derive(Debug)]
struct Karyawan {
    id: i32,
    nama: String,
    umur: i32,
    aktif: bool,
}

// Vector of objects
let karyawan = vec![
    Karyawan { id: 1, nama: String::from("Budi"), umur: 25, aktif: true },
    Karyawan { id: 2, nama: String::from("Siti"), umur: 23, aktif: true }
];

8. Spesifikasi Formal (EBNF/ANTLR)

Berikut adalah spesifikasi formal PON dalam format EBNF (Extended Backus-Naur Form) dan ANTLR (Another Tool for Language Recognition).

8.1 EBNF Grammar

(* ============================================================
    PON - Path Object Notation
    Spesifikasi Formal EBNF
    Versi 1.0 - 29 Juli 2026
    ============================================================ *)

(* Dokumen PON terdiri dari kumpulan statement *)
PONDocument = { Statement };

(* Statement = komentar opsional + deklarasi + terminator *)
Statement = [Comment] Declaration Terminator;

(* Komentar dimulai dengan # sampai akhir baris *)
Comment = "#" { Character - "\n" };

(* Terminator adalah titik koma *)
Terminator = ";";

(* Deklarasi = path + tipe opsional + struktur opsional + assignment opsional *)
Declaration = Path [Type] [Structure] [Assignment];

(* Path = / diikuti oleh key dan sub-path *)
Path = "/" Key { "/" Key };

(* Key = huruf, angka, underscore (tidak diawali angka) *)
Key = Letter { Letter | Digit | "_" };

(* Type = : diikuti nama tipe dan spesifikasi array opsional *)
Type = ":" TypeName [ArraySpec];

(* TypeName = salah satu dari daftar tipe data *)
TypeName = "bool" | "boolean" | "char" | "wchar" | "char16" |
           "string" | "datetime" | "date" | "time" | "unixtime" |
           "object" | "variant" | "any" |
           "byte" | "sbyte" | "int8" | "i8" |
           "ubyte" | "uint8" | "u8" |
           "short" | "int16" | "i16" |
           "ushort" | "uint16" | "u16" |
           "integer" | "int" | "int32" | "i32" |
           "uinteger" | "uint" | "uint32" | "u32" |
           "long" | "int64" | "i64" |
           "ulong" | "uint64" | "u64" |
           "float" | "single" | "float32" | "f32" |
           "double" | "float64" | "f64" |
           "decimal" | "decimal128" | "currency";

(* ArraySpec = dimensi dalam [] *)
ArraySpec = "[" [ Number { "," Number } ] "]" |
            "[" "]" |
            "[" "]" { "[" "]" };

(* Structure = object fields dalam () *)
Structure = "(" Field { ";" Field } ")";

(* Field = path + tipe opsional + default opsional *)
Field = Path [Type] [Default];

(* Default = = Value *)
Default = "=" Value;

(* Assignment = = Value *)
Assignment = "=" Value;

(* Value = berbagai tipe nilai *)
Value = Primitive | Array | Object | ArrayOfObjects;

(* Primitive = number, string, boolean, datetime, null *)
Primitive = Number | String | Boolean | DateTime | "null";

(* Number = integer atau float *)
Number = [ "-" ] Digit { Digit } [ "." Digit { Digit } ];

(* String = dalam quote (" atau ') *)
String = '"' { Character | Escape } '"' |
         "'" { Character | Escape } "'";

(* Boolean = true atau false *)
Boolean = "true" | "false";

(* DateTime = ISO 8601 format *)
DateTime = "'" DatePattern [ "T" TimePattern [ "Z" | TimeZone ] ] "'";

(* Array = nilai-nilai dipisahkan koma *)
Array = Value { "," Value };

(* Object = field assignments dalam () *)
Object = "(" FieldAssignment { ";" FieldAssignment } ")";

(* FieldAssignment = path + tipe opsional + = value *)
FieldAssignment = Path [Type] "=" Value;

(* ArrayOfObjects = skema [] = data object *)
ArrayOfObjects = "[" Field { ";" Field } "]" "=" ObjectData;

(* ObjectData = object atau beberapa object dipisahkan ; *)
ObjectData = Object { ";" Object };

(* Escape sequences *)
Escape = "\"" | "\'" | "\\" | "\n" | "\r" | "\t" | Unicode;
Unicode = "\u" HexDigit HexDigit HexDigit HexDigit ";" |
          "\" Number ";";

(* Token dasar *)
Letter = "A" | "B" | ... | "Z" | "a" | "b" | ... | "z";
Digit = "0" | "1" | ... | "9";
HexDigit = Digit | "A" | "B" | "C" | "D" | "E" | "F" | "a" | "b" | "c" | "d" | "e" | "f";

8.2 ANTLR Grammar

// ============================================================
// PON - Path Object Notation
// Spesifikasi Formal ANTLR v4
// Versi 1.0 - 29 Juli 2026
// ============================================================

grammar PON;

// ========================
// Parser Rules
// ========================

ponDocument: statement+;

statement: comment? declaration terminator;

terminator: SEMICOLON;

comment: HASH ~[\r\n]*;

declaration: path (type)? (structure)? (assignment)?;

path: SLASH key (SLASH key)*;

key: IDENTIFIER;

type: COLON typeName arraySpec?;

typeName: BOOL | BOOLEAN | CHAR | WCHAR | CHAR16
        | STRING | DATETIME | DATE | TIME | UNIXTIME
        | OBJECT | VARIANT | ANY
        | BYTE | SBYTE | INT8 | I8
        | UBYTE | UINT8 | U8
        | SHORT | INT16 | I16
        | USHORT | UINT16 | U16
        | INTEGER | INT | INT32 | I32
        | UINTEGER | UINT | UINT32 | U32
        | LONG | INT64 | I64
        | ULONG | UINT64 | U64
        | FLOAT | SINGLE | FLOAT32 | F32
        | DOUBLE | FLOAT64 | F64
        | DECIMAL | DECIMAL128 | CURRENCY;

arraySpec: LBRACK (number (COMMA number)*)? RBRACK
         | LBRACK RBRACK (LBRACK RBRACK)*;

structure: LPAREN field (SEMICOLON field)* RPAREN;

field: path (type)? (defaultValue)?;

defaultValue: EQUALS value;

assignment: EQUALS value;

value: primitive | array | object | arrayOfObjects;

primitive: number | string | boolean | datetime | NULL;

number: MINUS? DIGIT+ (DOT DIGIT+)?;

string: DOUBLE_QUOTE (ESC_SEQ | ~["\\])* DOUBLE_QUOTE
      | SINGLE_QUOTE (ESC_SEQ | ~['\\])* SINGLE_QUOTE;

boolean: TRUE | FALSE;

datetime: SINGLE_QUOTE datePattern (T timePattern (Z | timeZone)?)? SINGLE_QUOTE;

array: value (COMMA value)*;

object: LPAREN fieldAssignment (SEMICOLON fieldAssignment)* RPAREN;

fieldAssignment: path (type)? EQUALS value;

arrayOfObjects: LBRACK field (SEMICOLON field)* RBRACK EQUALS objectData;

objectData: object (SEMICOLON object)*;

// ========================
// Lexer Rules
// ========================

// Keywords - Type Names
BOOL: 'bool';
BOOLEAN: 'boolean';
CHAR: 'char';
WCHAR: 'wchar';
CHAR16: 'char16';
STRING: 'string';
DATETIME: 'datetime';
DATE: 'date';
TIME: 'time';
UNIXTIME: 'unixtime';
OBJECT: 'object';
VARIANT: 'variant';
ANY: 'any';
BYTE: 'byte';
SBYTE: 'sbyte';
INT8: 'int8';
I8: 'i8';
UBYTE: 'ubyte';
UINT8: 'uint8';
U8: 'u8';
SHORT: 'short';
INT16: 'int16';
I16: 'i16';
USHORT: 'ushort';
UINT16: 'uint16';
U16: 'u16';
INTEGER: 'integer';
INT: 'int';
INT32: 'int32';
I32: 'i32';
UINTEGER: 'uinteger';
UINT: 'uint';
UINT32: 'uint32';
U32: 'u32';
LONG: 'long';
INT64: 'int64';
I64: 'i64';
ULONG: 'ulong';
UINT64: 'uint64';
U64: 'u64';
FLOAT: 'float';
SINGLE: 'single';
FLOAT32: 'float32';
F32: 'f32';
DOUBLE: 'double';
FLOAT64: 'float64';
F64: 'f64';
DECIMAL: 'decimal';
DECIMAL128: 'decimal128';
CURRENCY: 'currency';

// Boolean values
TRUE: 'true';
FALSE: 'false';

// Null
NULL: 'null';

// Punctuation
SLASH: '/';
COLON: ':';
SEMICOLON: ';';
COMMA: ',';
LBRACK: '[';
RBRACK: ']';
LPAREN: '(';
RPAREN: ')';
HASH: '#';
EQUALS: '=';
MINUS: '-';
DOT: '.';
DOUBLE_QUOTE: '"';
SINGLE_QUOTE: '\'';

// Identifier
IDENTIFIER: LETTER (LETTER | DIGIT | '_')*;

// Number
DIGIT: [0-9]+;

// Escape Sequence
ESC_SEQ: '\\' [btnrf\"'\\]
       | '\\u' HEX HEX HEX HEX ';'
       | '\\' DIGIT+ ';';

// Whitespace (skip)
WS: [ \t\r\n]+ -> skip;

// Fragments
fragment LETTER: [a-zA-Z];
fragment HEX: [0-9a-fA-F];

// Pattern helpers
datePattern: DIGIT DIGIT DIGIT DIGIT '-' DIGIT DIGIT '-' DIGIT DIGIT;
timePattern: DIGIT DIGIT ':' DIGIT DIGIT ':' DIGIT DIGIT ('.' DIGIT+)?;
timeZone: (PLUS | MINUS) DIGIT DIGIT ':' DIGIT DIGIT;
PLUS: '+';

9. Studi Kasus

9.1 Konfigurasi Aplikasi

# ============================================================
# FILE: app-config.pon
# KONFIGURASI APLIKASI MyApp v3.0
# ============================================================

/root/app(
    @version:string = "3.0.0";
    @environment:string = "production";
    
    # ---- Server Configuration ----
    server(
        host:string = "0.0.0.0";
        port:int = 8080;
        workers:int = 4;
        max_connections:int = 1000;
        timeout:int = 60;
        ssl:bool = false
    );
    
    # ---- Database Configuration ----
    database(
        default[
            driver:string = "postgresql";
            host:string = "localhost";
            port:int = 5432;
            name:string = "myapp_db";
            username:string = "app_user";
            password:string = "";
            pool_size:int = 10
        ];
        cache[
            driver:string = "redis";
            host:string = "redis.example.com";
            port:int = 6379;
            ttl:int = 3600
        ]
    );
    
    # ---- Logging Configuration ----
    logging(
        level:string = "info";
        console:bool = true;
        file[
            enabled:bool = true;
            path:string = "/var/log/myapp/app.log";
            max_size:int = 104857600;   # 100MB
            format:string = "json"
        ]
    );
    
    # ---- Feature Flags ----
    features[
        @id:string;
        enabled:bool = true;
        description:string = ""
    ] =
        "dark_mode",true,"Dark theme support";
        "beta_features",false,"Beta features preview";
        "analytics",true,"Analytics tracking"
);

9.2 Data Master Karyawan

# ============================================================
# FILE: master-karyawan.pon
# DATA MASTER KARYAWAN PT TEKNOLOGI MAJU
# ============================================================

/root/perusahaan(
    @id:int = 1;
    nama:string = "PT Teknologi Maju";
    established:date = "2010-01-01";
    alamat(
        kota:string = "Jakarta Selatan";
        kode:string = "10220";
        negara:string = "Indonesia"
    );
    kontak(
        telepon:string = "021-1234567";
        email:string = "info@teknologimaju.com"
    )
);

/root/karyawan[
    @id:int;
    @status:string = "active";
    
    # Personal
    nama_lengkap:string;
    jenis_kelamin:char = 'M';
    tempat_lahir:string;
    tanggal_lahir:date;
    kewarganegaraan:string = "Indonesia";
    
    # Contact
    alamat(
        jalan:string;
        kota:string;
        kode:string;
        negara:string = "Indonesia"
    );
    kontak(
        telepon_seluler:string;
        email_pribadi:string;
        email_kantor:string = ""
    );
    
    # Employment
    nip:string;
    jabatan:string;
    department:string;
    tanggal_bergabung:date;
    status_kepegawaian:string = "Permanent";
    
    # Financial
    gaji_pokok:decimal = 0;
    rekening(
        bank:string;
        nomor:string;
        atas_nama:string
    );
    
    # Education
    pendidikan[
        @tingkatan:string;
        institusi:string;
        jurusan:string = "";
        tahun_lulus:int;
        ipk:float = 0
    ] = ;
    
    # Skills
    skill[
        @kategori:string;
        nama:string;
        level:string;
        years:int = 0
    ] = ;
    
    # Family
    keluarga[
        @hubungan:string;
        nama:string;
        jenis_kelamin:char;
        pekerjaan:string = "";
        tanggungan:bool = false
    ] = ;
    
    created_by:int;
    created_at:datetime
] =
    1,"active","Budi Santoso",'M',"Jakarta","1990-05-15","Indonesia",
    ("Jl. Merdeka No. 10","Bandung","40123","Indonesia"),
    ("08123456789","budi@mail.com","budi@teknologimaju.com"),
    "EMP-001","Senior Developer","IT","2018-06-01","Permanent",
    15000000,("BCA","1234567890","Budi Santoso"),
    [("S1","Universitas Indonesia","Ilmu Komputer",2018,3.75)],
    [("Technical","C#","Expert",5),("Technical","SQL","Expert",5)],
    [("Spouse","Siti Rahayu",'F',"Dokter",true)],
    1,"2018-06-01T08:00:00Z";
    
    2,"active","Siti Rahayu",'F',"Bandung","1992-08-20","Indonesia",
    ("Jl. Diponegoro No. 5","Jakarta","10220","Indonesia"),
    ("08129876543","siti@mail.com","siti@teknologimaju.com"),
    "EMP-002","Developer","IT","2021-03-15","Permanent",
    12000000,("Mandiri","2345678901","Siti Rahayu"),
    [("S1","Universitas Gadjah Mada","Ilmu Komputer",2020,3.68)],
    [("Technical","Python","Expert",4),("Technical","Django","Advanced",3)],
    [("Spouse","Andi Wijaya",'M',"Data Scientist",true)],
    1,"2021-03-15T09:00:00Z";
    
    3,"active","Andi Wijaya",'M',"Bandung","1988-12-01","Indonesia",
    ("Jl. Ahmad Yani No. 10","Bandung","40132","Indonesia"),
    ("08123456788","andi@mail.com","andi@teknologimaju.com"),
    "EMP-003","Senior Developer","IT","2019-06-01","Permanent",
    18000000,("BNI","3456789012","Andi Wijaya"),
    [("S1","ITB","Teknik Informatika",2014,3.45),("S2","ITB","Ilmu Komputer",2016,3.92)],
    [("Technical","Java","Expert",6),("Technical","Spring","Expert",4)],
    [("Spouse","Rina Lestari",'F',"Dokter",true)],
    1,"2019-06-01T08:00:00Z"
);

10. Referensi Cepat

10.1 Cheat Sheet

# ============================================================
# PON CHEAT SHEET - REFERENSI CEPAT
# ============================================================

# ===== SINTAKS DASAR =====
/path:type = value;
/root/name:string = "Budi";
/root/age:int = 25;
/root/active:bool = true;

# ===== TIPE DATA =====
bool, boolean      # Boolean
char, wchar, char16 # Karakter 16-bit
string             # String
datetime, date, time, unixtime  # Tanggal/Waktu
object, variant, any  # Any type
byte, ubyte, short, ushort, integer, uinteger, long, ulong  # Integer
float, double, decimal  # Floating point

# ===== ARRAY =====
# Array 1D
/values:int[] = 1,2,3,4;
/names:string[3] = "A","B","C";

# Array 2D (Multidimensi)
/matrix:float[2,3] = 1,2,3; 4,5,6;

# Jagged Array
/jagged:int[][] = 1,2,3; 4,5; 6,7,8,9;

# ===== OBJECT (NON-ARRAY) =====
/object(field1:type = value1; field2:type = value2);

# ===== ARRAY OF OBJECTS =====
/objects[
    field1:type = default1;
    field2:type = default2
] =
    value1,value2;
    value3,value4;

# ===== ATTRIBUTE =====
/@attribute:type = value;

# ===== COMMENT =====
# Ini komentar

# ===== DEFAULT VALUES =====
/objects[
    id:int = 0;        # Default 0
    name:string;       # Required
    active:bool = true # Default true
] =
    1,"Budi";          # active default true
    2,"Siti",;         # active default true
    3,"Andi",false;    # active override

10.2 Type Reference

Tipe Alias Ukuran Contoh
boolboolean1 bittrue, false
charwchar, char1616-bit'A'
string-Variable"Hello"
datetime-64-bit"2024-01-15T14:30:00Z"
date-32-bit"2024-01-15"
time-32-bit"14:30:00"
unixtime-64-bit1705314600
objectvariant, anyVariable"string" atau 123
bytesbyte, int8, i88-bit100
ubyteuint8, u88-bit200
shortint16, i1616-bit1000
ushortuint16, u1616-bit50000
integerint, int32, i3232-bit100000
uintegeruint, uint32, u3232-bit3000000000
longint64, i6464-bit10000000000
ulonguint64, u6464-bit18000000000000000000
floatsingle, float32, f3232-bit3.14
doublefloat64, f6464-bit3.141592653589793
decimaldecimal128, currency128-bit15000000.50

Lampiran

A. Spesifikasi Lengkap

Berikut adalah ringkasan spesifikasi lengkap PON:

A.1 Sintaks Dasar

PON Document = { Statement }
Statement = [Comment] Declaration Terminator
Comment = "#" text
Declaration = Path [Type] [Structure] [Assignment]
Path = "/" Key { "/" Key }
Key = Letter { Letter | Digit | "_" }
Type = ":" TypeName [ArraySpec]
TypeName = ( "bool" | "boolean" | "char" | "wchar" | "char16" | 
             "string" | "datetime" | "date" | "time" | "unixtime" |
             "object" | "variant" | "any" |
             "byte" | "sbyte" | "int8" | "i8" |
             "ubyte" | "uint8" | "u8" |
             "short" | "int16" | "i16" |
             "ushort" | "uint16" | "u16" |
             "integer" | "int" | "int32" | "i32" |
             "uinteger" | "uint" | "uint32" | "u32" |
             "long" | "int64" | "i64" |
             "ulong" | "uint64" | "u64" |
             "float" | "single" | "float32" | "f32" |
             "double" | "float64" | "f64" |
             "decimal" | "decimal128" | "currency" )
ArraySpec = "[" [ Number { "," Number } ] "]" | "[" "]" | "[" "]" { "[" "]" }
Structure = "(" Field { ";" Field } ")"
Field = Path [Type] [ Default ]
Assignment = "=" Value
Value = Primitive | Array | Object | ArrayOfObjects
Primitive = Number | String | Boolean | DateTime | null
String = '"' { Character | Escape } '"' | "'" { Character | Escape } "'"
Number = [ "-" ] Digit { Digit } [ "." Digit { Digit } ]
Boolean = "true" | "false"
DateTime = ISO 8601 format
Array = Value { "," Value }
Object = "(" FieldAssignment { ";" FieldAssignment } ")"
FieldAssignment = Path [Type] "=" Value
ArrayOfObjects = "[" Field { ";" Field } "]" "=" ObjectData
ObjectData = Object { ";" Object }
Terminator = ";"

B. Contoh File PON

B.1 config.pon

# ============================================================
# FILE: app-config.pon
# KONFIGURASI APLIKASI SEDERHANA
# ============================================================

/root/app(
    @version:string = "1.0.0";
    @environment:string = "development";
    
    server(
        host:string = "localhost";
        port:int = 3000;
        debug:bool = true
    );
    
    database(
        host:string = "localhost";
        port:int = 5432;
        name:string = "myapp_dev";
        username:string = "dev_user";
        password:string = ""
    )
);

B.2 data.pon

# ============================================================
# FILE: master-data.pon
# DATA MASTER SEDERHANA
# ============================================================

/root/users[
    @id:int;
    username:string;
    email:string;
    active:bool = true;
    roles:string[] = "user"
] =
    1,"budi","budi@mail.com",true,("user","admin");
    2,"siti","siti@mail.com",true,("user");
    3,"andi","andi@mail.com",false,("user");

/root/products[
    @id:int;
    name:string;
    price:decimal = 0;
    stock:int = 0;
    category:string = "General"
] =
    1,"Laptop Pro",15000000,10,"Electronics";
    2,"Mouse Wireless",250000,50,"Accessories";
    3,"Keyboard",500000,0,"Accessories";

PON
Path Object Notation
Versi 1.0 • 29 Juli 2026

"Menyederhanakan yang Kompleks, Menjelaskan yang Tersembunyi"

Pengembang & Perancang: Muhammad Arif Budianto

Lisensi: MIT License

© 2026 - PON Project

🏆 Dikembangkan Pertama Kali oleh Muhammad Arif Budianto

⚠️ PON dibuat BUKAN untuk menggantikan format data modern yang sudah ada