| 39 | typeof value === "object" && value !== null && !Array.isArray(value) && !(value instanceof Date) |
| 40 | |
| 41 | class TomlParser { |
| 42 | readonly root = makeTable() |
| 43 | private readonly input: string |
| 44 | private current = this.root |
| 45 | private index = 0 |
| 46 | private line = 1 |
| 47 | private column = 1 |
| 48 | private readonly explicitTables = new Set<string>() |
| 49 | |
| 50 | constructor(input: string) { |
| 51 | this.input = input |
| 52 | } |
| 53 | |
| 54 | parse(): Table { |
| 55 | while (true) { |
| 56 | this.skipDocumentWhitespace() |
| 57 | if (this.done) { |
| 58 | return this.root |
| 59 | } |
| 60 | if (this.peek() === "[") { |
| 61 | this.parseHeader() |
| 62 | } else { |
| 63 | const keys = this.parseKeyPath("=") |
| 64 | this.skipInlineWhitespace() |
| 65 | this.expect("=") |
| 66 | this.skipInlineWhitespace() |
| 67 | this.assign(this.current, keys, this.parseValue()) |
| 68 | this.finishStatement() |
| 69 | } |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | private parseHeader(): void { |
| 74 | this.expect("[") |
| 75 | const array = this.peek() === "[" |
| 76 | if (array) { |
| 77 | this.advance() |
| 78 | } |
| 79 | this.skipInlineWhitespace() |
| 80 | const path = this.parseKeyPath("]") |
| 81 | this.skipInlineWhitespace() |
| 82 | this.expect("]") |
| 83 | if (array) { |
| 84 | this.expect("]") |
| 85 | } |
| 86 | this.finishStatement() |
| 87 | |
| 88 | const pathKey = JSON.stringify(path) |
| 89 | if (!array && this.explicitTables.has(pathKey)) { |
| 90 | this.fail(`Cannot redefine table '${path.join(".")}'`) |
| 91 | } |
| 92 | if (!array) { |
| 93 | this.explicitTables.add(pathKey) |
| 94 | } |
| 95 | this.current = this.resolveTable(path, array) |
| 96 | } |
| 97 | |
| 98 | private resolveTable(path: ReadonlyArray<string>, array: boolean): Table { |
nothing calls this directly
no test coverage detected