Json syntax

This commit is contained in:
Yura Dupyn 2026-04-25 16:51:05 +02:00
parent d1491ec5e6
commit 321e7aa4de

View file

@ -0,0 +1,273 @@
# JSON Syntax
This is a JSON-like concrete syntax used for parser and source span experiments.
The starting point is standard JSON syntax, with one deliberate experiment-friendly choice: a `Document` may contain zero or more JSON values. Standard JSON allows exactly one top-level value, but allowing a sequence makes it easier to test recovery and multiple independent syntax trees.
## Grammar
This grammar is intentionally semi-formal. `Whitespace` may appear between the major syntactic parts shown below.
```txt
Document ::= Value*
Value ::= Object
| Array
| String
| Number
| "true"
| "false"
| "null"
Object ::= "{" ObjectBody? "}"
ObjectBody ::= Member ("," Member)*
Member ::= String ":" Value
Array ::= "[" ArrayBody? "]"
ArrayBody ::= Value ("," Value)*
String ::= '"' StringChar* '"'
StringChar ::= UnescapedStringChar
| Escape
Escape ::= '\"'
| "\\"
| "\/"
| "\b"
| "\f"
| "\n"
| "\r"
| "\t"
| UnicodeEscape
UnicodeEscape ::= "\u" HexDigit HexDigit HexDigit HexDigit
Number ::= "-"? Integer Fraction? Exponent?
Integer ::= "0" | NonZeroDigit Digit*
Fraction ::= "." Digit+
Exponent ::= ("e" | "E") ("+" | "-")? Digit+
Digit ::= "0" | "1" | "2" | "3" | "4"
| "5" | "6" | "7" | "8" | "9"
NonZeroDigit ::= "1" | "2" | "3" | "4"
| "5" | "6" | "7" | "8" | "9"
HexDigit ::= Digit | "a" ... "f" | "A" ... "F"
Whitespace ::= " " | "\t" | "\n" | "\r"
```
Notes:
- `Document` may be empty in this experiment.
- Objects and arrays do not allow trailing commas.
- Object keys must be strings.
- Strings use JSON escapes; raw newline and raw carriage return are not allowed inside strings.
- Number syntax follows JSON number rules, so leading zeroes like `012` are invalid.
## Document
A document is a sequence of zero or more values.
```json
true
true false null
{"x": 1} [1, 2, 3]
```
Empty input is valid for this experiment.
## Values
A value is one of:
- object
- array
- string
- number
- `true`
- `false`
- `null`
Examples:
```json
null
true
false
"hello"
123
{"name": "Ada"}
[1, 2, 3]
```
## Objects
Objects use braces and contain zero or more comma-separated members.
```json
{}
{"x": 1}
{"x": 1, "y": 2}
{"nested": {"ok": true}}
```
Members are string keys followed by a colon and a value:
```json
"name": "Ada"
```
Invalid objects:
```json
{x: 1}
{"x" 1}
{"x": 1,}
{"x": 1 "y": 2}
```
## Arrays
Arrays use brackets and contain zero or more comma-separated values.
```json
[]
[1]
[1, 2, 3]
[true, false, null]
[{"x": 1}, ["nested"]]
```
Trailing commas are invalid:
```json
[1, 2,]
```
Missing separators are invalid:
```json
[1 2]
[true false]
```
Repeated separators are invalid:
```json
[1,, 2]
```
## Strings
Strings use double quotes.
```json
""
"hello"
"quote: \""
"slash: \\"
"unicode: \u03bb"
```
Valid escapes:
```json
"\""
"\\"
"\/"
"\b"
"\f"
"\n"
"\r"
"\t"
"\u0041"
```
Invalid strings:
```json
"unterminated
"bad escape: \x"
"bad unicode: \u12"
"raw
newline"
```
## Numbers
Numbers follow JSON number syntax.
Valid numbers:
```json
0
-0
12
-12
1.5
0.25
1e10
1E-10
-12.34e+56
```
Invalid numbers:
```json
01
-
1.
.5
1e
1e+
123abc
```
## Keywords
The only keywords are:
```json
true
false
null
```
These must match exactly:
```json
true
false
null
```
Invalid keyword-like fragments:
```json
True
FALSE
nil
nullish
truefalse
```
## Delimiters
Objects and arrays must close with matching delimiters:
```json
{"x": 1}
[1, 2, 3]
```
These are invalid:
```json
{"x": 1]
[1, 2}
{"x": 1
[1, 2
```