devsite/node_modules/@iarna/toml/lib/parser.js
2024-07-07 18:49:38 -07:00

128 lines
2.9 KiB
JavaScript
Executable File

'use strict'
const ParserEND = 0x110000
class ParserError extends Error {
/* istanbul ignore next */
constructor (msg, filename, linenumber) {
super('[ParserError] ' + msg, filename, linenumber)
this.name = 'ParserError'
this.code = 'ParserError'
if (Error.captureStackTrace) Error.captureStackTrace(this, ParserError)
}
}
class State {
constructor (parser) {
this.parser = parser
this.buf = ''
this.returned = null
this.result = null
this.resultTable = null
this.resultArr = null
}
}
class Parser {
constructor () {
this.pos = 0
this.col = 0
this.line = 0
this.obj = {}
this.ctx = this.obj
this.stack = []
this._buf = ''
this.char = null
this.ii = 0
this.state = new State(this.parseStart)
}
parse (str) {
/* istanbul ignore next */
if (str.length === 0 || str.length == null) return
this._buf = String(str)
this.ii = -1
this.char = -1
let getNext
while (getNext === false || this.nextChar()) {
getNext = this.runOne()
}
this._buf = null
}
nextChar () {
if (this.char === 0x0A) {
++this.line
this.col = -1
}
++this.ii
this.char = this._buf.codePointAt(this.ii)
++this.pos
++this.col
return this.haveBuffer()
}
haveBuffer () {
return this.ii < this._buf.length
}
runOne () {
return this.state.parser.call(this, this.state.returned)
}
finish () {
this.char = ParserEND
let last
do {
last = this.state.parser
this.runOne()
} while (this.state.parser !== last)
this.ctx = null
this.state = null
this._buf = null
return this.obj
}
next (fn) {
/* istanbul ignore next */
if (typeof fn !== 'function') throw new ParserError('Tried to set state to non-existent state: ' + JSON.stringify(fn))
this.state.parser = fn
}
goto (fn) {
this.next(fn)
return this.runOne()
}
call (fn, returnWith) {
if (returnWith) this.next(returnWith)
this.stack.push(this.state)
this.state = new State(fn)
}
callNow (fn, returnWith) {
this.call(fn, returnWith)
return this.runOne()
}
return (value) {
/* istanbul ignore next */
if (this.stack.length === 0) throw this.error(new ParserError('Stack underflow'))
if (value === undefined) value = this.state.buf
this.state = this.stack.pop()
this.state.returned = value
}
returnNow (value) {
this.return(value)
return this.runOne()
}
consume () {
/* istanbul ignore next */
if (this.char === ParserEND) throw this.error(new ParserError('Unexpected end-of-buffer'))
this.state.buf += this._buf[this.ii]
}
error (err) {
err.line = this.line
err.col = this.col
err.pos = this.pos
return err
}
/* istanbul ignore next */
parseStart () {
throw new ParserError('Must declare a parseStart method')
}
}
Parser.END = ParserEND
Parser.Error = ParserError
module.exports = Parser