You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
2.7 KiB
110 lines
2.7 KiB
const WHITE_SPACE_CHAR_REGEXP = /^\s/
|
|
|
|
const throwParsingError = function (path, index) {
|
|
throw new Error('Parsing data path "' + path + '" failed at char "' + path[index] + '" (index ' + index + ')')
|
|
}
|
|
|
|
const parseArrIndex = function (path, state) {
|
|
const startIndex = state.index
|
|
while (state.index < state.length) {
|
|
const ch = path[state.index]
|
|
if (/^[0-9]/.test(ch)) {
|
|
state.index++
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
if (startIndex === state.index) {
|
|
throwParsingError(path, state.index)
|
|
}
|
|
return parseInt(path.slice(startIndex, state.index), 10)
|
|
}
|
|
|
|
const parseIdent = function (path, state) {
|
|
const startIndex = state.index
|
|
const ch = path[startIndex]
|
|
if (/^[_a-zA-Z$]/.test(ch)) {
|
|
state.index++
|
|
while (state.index < state.length) {
|
|
const ch = path[state.index]
|
|
if (/^[_a-zA-Z0-9$]/.test(ch)) {
|
|
state.index++
|
|
continue
|
|
}
|
|
break
|
|
}
|
|
} else {
|
|
throwParsingError(path, state.index)
|
|
}
|
|
return path.slice(startIndex, state.index)
|
|
}
|
|
|
|
const parseSinglePath = function (path, state) {
|
|
const ret = [parseIdent(path, state)]
|
|
while (state.index < state.length) {
|
|
const ch = path[state.index]
|
|
if (ch === '[') {
|
|
state.index++
|
|
ret.push(parseArrIndex(path, state))
|
|
const nextCh = path[state.index]
|
|
if (nextCh !== ']') throwParsingError(path, state.index)
|
|
state.index++
|
|
} else if (ch === '.') {
|
|
state.index++
|
|
ret.push(parseIdent(path, state))
|
|
} else {
|
|
break
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
const parseMultiPaths = function (path, state) {
|
|
while (WHITE_SPACE_CHAR_REGEXP.test(path[state.index])) {
|
|
state.index++
|
|
}
|
|
const ret = [parseSinglePath(path, state)]
|
|
let splitted = false
|
|
while (state.index < state.length) {
|
|
const ch = path[state.index]
|
|
if (WHITE_SPACE_CHAR_REGEXP.test(ch)) {
|
|
state.index++
|
|
} else if (ch === ',') {
|
|
splitted = true
|
|
state.index++
|
|
} else if (splitted) {
|
|
splitted = false
|
|
ret.push(parseSinglePath(path, state))
|
|
}
|
|
}
|
|
return ret
|
|
}
|
|
|
|
const parseEOF = function (path, state) {
|
|
if (state.index < state.length) throwParsingError(path, state.index)
|
|
}
|
|
|
|
const parseSingleDataPath = function (path) {
|
|
const state = {
|
|
length: path.length,
|
|
index: 0
|
|
}
|
|
const ret = parseSinglePath(path, state)
|
|
parseEOF(path, state)
|
|
return ret
|
|
}
|
|
|
|
const parseMultiDataPaths = function (path) {
|
|
const state = {
|
|
length: path.length,
|
|
index: 0
|
|
}
|
|
const ret = parseMultiPaths(path, state)
|
|
parseEOF(path, state)
|
|
return ret
|
|
}
|
|
|
|
export default {
|
|
parseSingleDataPath,
|
|
parseMultiDataPaths
|
|
}
|
|
|