| 313 | } |
| 314 | |
| 315 | function kv<T>( |
| 316 | keyParser: ParserComponent<string[]>, |
| 317 | separator: string, |
| 318 | valueParser: ParserComponent<T>, |
| 319 | ): ParserComponent<{ [key: string]: unknown }> { |
| 320 | const Separator = character(separator); |
| 321 | return (scanner: Scanner): ParseResult<{ [key: string]: unknown }> => { |
| 322 | const position = scanner.position; |
| 323 | const key = keyParser(scanner); |
| 324 | if (!key.ok) return failure(); |
| 325 | const sep = Separator(scanner); |
| 326 | if (!sep.ok) { |
| 327 | throw new SyntaxError(`key/value pair doesn't have "${separator}"`); |
| 328 | } |
| 329 | const value = valueParser(scanner); |
| 330 | if (!value.ok) { |
| 331 | const lineEndIndex = scanner.source.indexOf("\n", scanner.position); |
| 332 | const endPosition = lineEndIndex > 0 |
| 333 | ? lineEndIndex |
| 334 | : scanner.source.length; |
| 335 | const line = scanner.source.slice(position, endPosition); |
| 336 | throw new SyntaxError(`Cannot parse value on line '${line}'`); |
| 337 | } |
| 338 | return success(unflat(key.body, value.body)); |
| 339 | }; |
| 340 | } |
| 341 | |
| 342 | function merge( |
| 343 | parser: ParserComponent<unknown[]>, |