CSV with types, foreign keys, and enums. Designed for LLM data exchange.
3TL extends CSV with a schema declaration syntax. Types are explicit. Relationships are declared. Multiple tables fit in one file.
#! User
#@ id:uint, name:str, email:str, role:enum(admin|user|moderator), active:bool
1, Alice, alice@example.com, admin, true
2, Bob, bob@example.com, user, true
#! Order
#@ id:uint, user_id:ref(User.id), amount:decimal(10,2), status:enum(pending|shipped|delivered)
101, 1, 99.99, shipped
102, 2, 149.50, pending
Parse this without documentation. Types are clear. Foreign keys explicit. Enums defined.
CSV has problems:
- Types inferred (is "123" a string or number?)
- Booleans inconsistent (true/1/yes all valid)
- Precision lost (can't distinguish 0.05 from 0.050)
- Dates ambiguous (01/02/03 is which date?)
- No enum validation (any value accepted)
- Foreign keys unclear (what does user_id reference?)
- Arrays non-standard (comma-separated strings?)
3TL fixes these:
- Types declared:
uint,str,decimal(10,2),bool - Booleans standard:
true/falseonly - Precision explicit:
decimal(10,2)means exactly 2 decimals - Dates ISO:
2003-01-02unambiguous - Enums validated:
enum(pending|shipped|delivered) - Foreign keys explicit:
ref(User.id) - Arrays typed:
str[]
i8,i16,i32,i64- signed integers (8 to 64 bit)u8,u16,u32,u64- unsigned integersint- alias fori64uint- alias foru64
f32,f64- IEEE 754 floatsfloat- alias forf64decimal(precision, scale)- exact decimal (e.g.,decimal(10,2)for currency)
str- UTF-8 stringtext- alias forstr
bool-trueorfalse
date- ISO 8601 date (YYYY-MM-DD)time- ISO 8601 time (HH:MM:SS)datetime- ISO 8601 datetimetimestamp- Unix timestamp
enum(val1|val2|val3)- enumerated valuesref(Table.column)- foreign key referencetype[]- array of typetype?- nullable type
# This is a comment
#! TableName
#@ column1:type1, column2:type2, ...
Standard CSV format after schema declaration.
# User accounts
#! User
#@ id:uint, name:str, email:str, created:date, role:enum(admin|user|guest), active:bool
1, Alice, alice@example.com, 2024-01-15, admin, true
2, Bob, bob@example.com, 2024-02-20, user, true
3, Charlie, charlie@example.com, 2024-03-10, guest, false
# Purchase orders
#! Order
#@ id:uint, user_id:ref(User.id), total:decimal(10,2), status:enum(pending|paid|shipped|delivered)
101, 1, 99.99, delivered
102, 2, 149.50, pending
103, 1, 75.00, shipped
Available in 4 languages:
cd python/
pip install -r requirements.txt
python parser.py example.3tl --prettyUses Lark parser. Validates syntax. Outputs JSON.
cd javascript/
npm install
node src/cli.js example.3tl --prettyUses Peggy PEG parser. ES modules. Node 16+.
cd clojure/
clojure -M -m three-tl.parser example.3tlUses Instaparse. Functional transformation. Immutable data structures.
cd go/
go run ./cmd/3tl-parser example.3tl --prettyUses Participle. Struct tags define grammar. Requires Go 1.21+.
All parsers produce identical JSON output.
Tested with Claude 3 Haiku, 3.5 Haiku, and Opus across 23 samples.
- Claude 3.5 Haiku: 95% (21/22)
- Claude 3 Opus: 95% (21/22)
- Claude 3 Haiku: 91% (20/22)
Both formats achieved 100% on comparable tasks. 3TL enables features CSV cannot express.
- 3 rows: +54% (+18 tokens for schema)
- 100 rows: +2% (schema overhead amortizes)
- 1000 rows: +0.2%
Cost with Claude 3.5 Haiku (100 rows): +$0.00004 per request.
100% accuracy (15/15 samples). LLMs understand 3TL without documentation. Format is self-explanatory.
75% accuracy (15/20 samples). Model correctly identified where CSV is ambiguous:
- Type ambiguity: 100%
- Boolean inconsistency: 100%
- Date format confusion: 100%
- Enum validation missing: 100%
- Array representation: 100%
- Schema inference errors: 100%
Partial recognition (50%) in cases where model was "too smart" and inferred from context. This proves the point: CSV relies on inference, 3TL is explicit.
- Database schema communication with LLMs
- Type precision matters (financial, scientific)
- Multiple related tables
- Code generation from schemas
- Data validation required
- Explicit foreign keys needed
- Simple tabular data
- Maximum tool compatibility
- Very small datasets (<10 rows)
- Types don't matter
Full grammar and type system documented in SPECIFICATION.md.
Formal ABNF grammar in 3tl-grammar.abnf.
See examples/ for:
products.3tl- E-commerce with enums, nullable fields, refsblog.3tl- Multi-table with foreign keysinvoices.3tl- Financial data with decimal typesunicode.3tl- International text (Spanish, French, Japanese, Russian, Greek)
See evals/ for:
RESULTS.md- Single model evaluation (Claude 3 Haiku)MULTI_MODEL_RESULTS.md- Cross-model comparison (3 Claude models)ZERO_SHOT_RESULTS.md- Understanding without documentationCSV_FAILURE_RESULTS.md- CSV ambiguity vs 3TL clarity
Run evals:
cd evals/
python3 -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
cp .env.example .env # Add API keys
python run_evals.py --model claude-3-5-haiku --all-tasks- Obvious syntax - Uses familiar conventions (# for metadata, : for types)
- Self-documenting - Schema embedded in data
- No ambiguity - Types explicit, not inferred
- Scales well - Schema overhead fixed, amortizes over rows
- LLM-friendly - Follows patterns models already know
- Not a database (no indexes, queries, transactions)
- Not a serialization format (use Protocol Buffers/Avro for that)
- Not for binary data (use base64 in string fields)
- Parsers validate syntax only (not data integrity)
- Foreign keys not enforced (reference validation is application's job)
Experimental. Grammar stable. Parsers functional. Evaluations demonstrate value.
Use for LLM communication. Don't use for systems requiring ACID guarantees.
Apache 2.0