blob: f70d7f2c462f707c022fdcd7ab2e24dfad9849cb [file] [log] [blame]
grammar = sp value:v sp -> v
sp = ws*
ws = '\u0020' | eol | comment
| '\u0009' | '\u000B' | '\u000C' | '\u00A0' | '\uFEFF'
| anything:x ?( is_unicat(x, 'Zs') ) -> x
eol = '\u000D' '\u000A' | '\u000D' | '\u000A'
| '\u2028' | '\u2029'
comment = '//' (~eol anything)*
| '/*' (~'*/' anything)* '*/'
value = 'null' -> ['null', null]
| 'true' -> ['true', true]
| 'false' -> ['false', false]
| object:v -> ['object', v]
| array:v -> ['array', v]
| string:v -> ['string', v]
| num_literal:v -> ['number', v]
object = '{' sp member_list:v sp '}' -> v
| '{' sp '}' -> []
array = '[' sp element_list:v sp ']' -> v
| '[' sp ']' -> []
string = squote sqchar*:cs squote -> join('', cs)
| dquote dqchar*:cs dquote -> join('', cs)
sqchar = bslash esc_char:c -> c
| bslash eol -> ''
| ~bslash ~squote ~eol anything:c -> c
dqchar = bslash esc_char:c -> c
| bslash eol -> ''
| ~bslash ~dquote ~eol anything:c -> c
bslash = '\u005C'
squote = '\u0027'
dquote = '\u0022'
esc_char = 'b' -> '\u0008'
| 'f' -> '\u000C'
| 'n' -> '\u000A'
| 'r' -> '\u000D'
| 't' -> '\u0009'
| 'v' -> '\u000B'
| squote -> '\u0027'
| dquote -> '\u0022'
| bslash -> '\u005C'
| hex_esc:c -> c
| unicode_esc:c -> c
hex_esc = 'x' hex:h1 hex:h2 -> xtou(h1 + h2)
unicode_esc = 'u' hex:a hex:b hex:c hex:d -> xtou(a + b + c + d)
element_list = value:v sp ',' sp element_list:vs -> [v] + vs
| value:v sp ',' -> [v]
| value:v -> [v]
member_list = member:m sp ',' sp member_list:ms -> [m] + ms
| member:m sp ',' -> [m]
| member:m -> [m]
member = string:k sp ':' sp value:v -> [k, v]
| ident:k sp ':' sp value:v -> [k, v]
ident = id_start:hd id_continue*:tl -> join('', [hd] + tl)
id_start = ascii_id_start
| other_id_start
| bslash unicode_esc
ascii_id_start = 'a'..'z'
| 'A'..'Z'
| '$'
| '_'
other_id_start = anything:x ?(is_unicat(x, 'Ll')) -> x
| anything:x ?(is_unicat(x, 'Lm')) -> x
| anything:x ?(is_unicat(x, 'Lo')) -> x
| anything:x ?(is_unicat(x, 'Lt')) -> x
| anything:x ?(is_unicat(x, 'Lu')) -> x
| anything:x ?(is_unicat(x, 'Nl')) -> x
id_continue = ascii_id_start
| digit
| other_id_start
| anything:x ?(is_unicat(x, 'Mn')) -> x
| anything:x ?(is_unicat(x, 'Mc')) -> x
| anything:x ?(is_unicat(x, 'Nd')) -> x
| anything:x ?(is_unicat(x, 'Pc')) -> x
| '\u200C'
| '\u200D'
num_literal = '-' num_literal:n -> '-' + n
| '+'? dec_literal:d ~id_start -> d
| hex_literal
| 'Infinity'
| 'NaN'
dec_literal = dec_int_lit:d frac:f exp:e -> d + f + e
| dec_int_lit:d '.' exp:e -> d + '.' + e
| dec_int_lit:d frac:f -> d + f
| dec_int_lit:d '.' -> d + '.'
| dec_int_lit:d exp:e -> d + e
| dec_int_lit:d -> d
| frac:f exp:e -> f + e
| frac:f -> f
dec_int_lit = '0' ~digit -> '0'
| nonzerodigit:d digit*:ds -> d + join('', ds)
digit = '0'..'9'
nonzerodigit = '1'..'9'
hex_literal = ('0x' | '0X') hex+:hs -> '0x' + join('', hs)
hex = 'a'..'f' | 'A'..'F' | digit
frac = '.' digit+:ds -> '.' + join('', ds)
exp = ('e' | 'E') ('+' | '-'):s digit+:ds -> 'e' + s + join('', ds)
| ('e' | 'E') digit+:ds -> 'e' + join('', ds)