| 279 | readonly table: Record<string, () => JSONValue>; |
| 280 | |
| 281 | constructor() { |
| 282 | this.string = ''; |
| 283 | this.index = -1; |
| 284 | this.table = { |
| 285 | '!': () => { |
| 286 | const s = this.string; |
| 287 | const c = s.charAt(this.index++); |
| 288 | if (!c) return this.error('"!" at end of input'); |
| 289 | const x = Parser.bangs[c as keyof typeof Parser.bangs]; |
| 290 | if (typeof x == 'function') { |
| 291 | return x.call(null, this); |
| 292 | } |
| 293 | if (typeof x === 'undefined') { |
| 294 | return this.error('unknown literal: "!' + c + '"'); |
| 295 | } |
| 296 | return x; |
| 297 | }, |
| 298 | '(': () => { |
| 299 | const o: JSONValue = {}; |
| 300 | let c; |
| 301 | let count = 0; |
| 302 | while ((c = this.next()) !== ')') { |
| 303 | if (count) { |
| 304 | if (c !== ',') this.error("missing ','"); |
| 305 | } else if (c === ',') { |
| 306 | this.error("extra ','"); |
| 307 | } else --this.index; |
| 308 | const k = this.readValue(); |
| 309 | if (typeof k == 'undefined') return undefined; |
| 310 | if (this.next() !== ':') this.error("missing ':'"); |
| 311 | const v = this.readValue(); |
| 312 | if (typeof v == 'undefined') return undefined; |
| 313 | assert(isString(k)); |
| 314 | o[k] = v; |
| 315 | count++; |
| 316 | } |
| 317 | return o; |
| 318 | }, |
| 319 | "'": () => { |
| 320 | const s = this.string; |
| 321 | let i = this.index; |
| 322 | let start = i; |
| 323 | const segments: string[] = []; |
| 324 | let c; |
| 325 | while ((c = s.charAt(i++)) !== "'") { |
| 326 | //if (i == s.length) return this.error('unmatched "\'"'); |
| 327 | if (!c) this.error('unmatched "\'"'); |
| 328 | if (c === '!') { |
| 329 | if (start < i - 1) segments.push(s.slice(start, i - 1)); |
| 330 | c = s.charAt(i++); |
| 331 | if ("!'".includes(c)) { |
| 332 | segments.push(c); |
| 333 | } else { |
| 334 | this.error('invalid string escape: "!' + c + '"'); |
| 335 | } |
| 336 | start = i; |
| 337 | } |
| 338 | } |