1grammar = sp value:v sp end -> v 2 3sp = ws* 4 5ws = '\u0020' | eol | comment 6 | '\u0009' | '\u000B' | '\u000C' | '\u00A0' | '\uFEFF' 7 | anything:x ?( is_unicat(x, 'Zs') ) -> x 8 9eol = '\u000D' '\u000A' | '\u000D' | '\u000A' 10 | '\u2028' | '\u2029' 11 12comment = '//' (~eol anything)* 13 | '/*' (~'*/' anything)* '*/' 14 15value = 'null' -> 'None' 16 | 'true' -> 'True' 17 | 'false' -> 'False' 18 | object:v -> ['object', v] 19 | array:v -> ['array', v] 20 | string:v -> ['string', v] 21 | num_literal:v -> ['number', v] 22 23object = '{' sp member_list:v sp '}' -> v 24 | '{' sp '}' -> [] 25 26array = '[' sp element_list:v sp ']' -> v 27 | '[' sp ']' -> [] 28 29string = squote sqchar*:cs squote -> join('', cs) 30 | dquote dqchar*:cs dquote -> join('', cs) 31 32sqchar = bslash esc_char:c -> c 33 | bslash eol -> '' 34 | ~bslash ~squote ~eol anything:c -> c 35 36dqchar = bslash esc_char:c -> c 37 | bslash eol -> '' 38 | ~bslash ~dquote ~eol anything:c -> c 39 40bslash = '\u005C' 41 42squote = '\u0027' 43 44dquote = '\u0022' 45 46esc_char = 'b' -> '\u0008' 47 | 'f' -> '\u000C' 48 | 'n' -> '\u000A' 49 | 'r' -> '\u000D' 50 | 't' -> '\u0009' 51 | 'v' -> '\u000B' 52 | squote -> '\u0027' 53 | dquote -> '\u0022' 54 | bslash -> '\u005C' 55 | hex_esc:c -> c 56 | unicode_esc:c -> c 57 58hex_esc = 'x' hex:h1 hex:h2 -> xtou(h1 + h2) 59 60unicode_esc = 'u' hex:a hex:b hex:c hex:d -> xtou(a + b + c + d) 61 62element_list = value:v (sp ',' sp value)*:vs sp ','? -> [v] + vs 63 64member_list = member:m (sp ',' sp member)*:ms sp ','? -> [m] + ms 65 66member = string:k sp ':' sp value:v -> [k, v] 67 | ident:k sp ':' sp value:v -> [k, v] 68 69ident = id_start:hd id_continue*:tl -> join('', [hd] + tl) 70 71id_start = ascii_id_start 72 | other_id_start 73 | bslash unicode_esc 74 75ascii_id_start = 'a'..'z' 76 | 'A'..'Z' 77 | '$' 78 | '_' 79 80other_id_start = anything:x ?(is_unicat(x, 'Ll')) -> x 81 | anything:x ?(is_unicat(x, 'Lm')) -> x 82 | anything:x ?(is_unicat(x, 'Lo')) -> x 83 | anything:x ?(is_unicat(x, 'Lt')) -> x 84 | anything:x ?(is_unicat(x, 'Lu')) -> x 85 | anything:x ?(is_unicat(x, 'Nl')) -> x 86 87id_continue = ascii_id_start 88 | digit 89 | other_id_start 90 | anything:x ?(is_unicat(x, 'Mn')) -> x 91 | anything:x ?(is_unicat(x, 'Mc')) -> x 92 | anything:x ?(is_unicat(x, 'Nd')) -> x 93 | anything:x ?(is_unicat(x, 'Pc')) -> x 94 | bslash unicode_esc 95 | '\u200C' 96 | '\u200D' 97 98num_literal = '-' num_literal:n -> '-' + n 99 | '+'? dec_literal:d ~id_start -> d 100 | hex_literal 101 | 'Infinity' 102 | 'NaN' 103 104dec_literal = dec_int_lit:d frac:f exp:e -> d + f + e 105 | dec_int_lit:d frac:f -> d + f 106 | dec_int_lit:d exp:e -> d + e 107 | dec_int_lit:d -> d 108 | frac:f exp:e -> f + e 109 | frac:f -> f 110 111dec_int_lit = '0' ~digit -> '0' 112 | nonzerodigit:d digit*:ds -> d + join('', ds) 113 114digit = '0'..'9' 115 116nonzerodigit = '1'..'9' 117 118hex_literal = ('0x' | '0X') hex+:hs -> '0x' + join('', hs) 119 120hex = 'a'..'f' | 'A'..'F' | digit 121 122frac = '.' digit*:ds -> '.' + join('', ds) 123 124exp = ('e' | 'E') ('+' | '-'):s digit*:ds -> 'e' + s + join('', ds) 125 | ('e' | 'E') digit*:ds -> 'e' + join('', ds) 126