Json syntax
This commit is contained in:
parent
d1491ec5e6
commit
321e7aa4de
1 changed files with 273 additions and 0 deletions
|
|
@ -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
|
||||
```
|
||||
Loading…
Add table
Add a link
Reference in a new issue