mirror of
https://github.com/voson-wang/toon.git
synced 2026-01-29 23:34:10 +08:00
refactor: use specific error types in decoders and parser
This commit is contained in:
@@ -29,7 +29,7 @@ import {
|
|||||||
export function decodeValueFromLines(cursor: LineCursor, options: ResolvedDecodeOptions): JsonValue {
|
export function decodeValueFromLines(cursor: LineCursor, options: ResolvedDecodeOptions): JsonValue {
|
||||||
const first = cursor.peek()
|
const first = cursor.peek()
|
||||||
if (!first) {
|
if (!first) {
|
||||||
throw new Error('No content to decode')
|
throw new ReferenceError('No content to decode')
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for root array
|
// Check for root array
|
||||||
@@ -230,7 +230,7 @@ function decodeListArray(
|
|||||||
if (options.strict && !cursor.atEnd()) {
|
if (options.strict && !cursor.atEnd()) {
|
||||||
const nextLine = cursor.peek()
|
const nextLine = cursor.peek()
|
||||||
if (nextLine && nextLine.depth === itemDepth && nextLine.content.startsWith(LIST_ITEM_PREFIX)) {
|
if (nextLine && nextLine.depth === itemDepth && nextLine.content.startsWith(LIST_ITEM_PREFIX)) {
|
||||||
throw new Error(`Expected ${header.length} list array items, but found more`)
|
throw new RangeError(`Expected ${header.length} list array items, but found more`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -284,7 +284,7 @@ function decodeTabularArray(
|
|||||||
|
|
||||||
if (!hasColon) {
|
if (!hasColon) {
|
||||||
// No colon = data row (for single-field tables)
|
// No colon = data row (for single-field tables)
|
||||||
throw new Error(`Expected ${header.length} tabular rows, but found more`)
|
throw new RangeError(`Expected ${header.length} tabular rows, but found more`)
|
||||||
}
|
}
|
||||||
else if (hasDelimiter) {
|
else if (hasDelimiter) {
|
||||||
// Has both colon and delimiter - check which comes first
|
// Has both colon and delimiter - check which comes first
|
||||||
@@ -292,7 +292,7 @@ function decodeTabularArray(
|
|||||||
const delimiterPos = nextLine.content.indexOf(header.delimiter)
|
const delimiterPos = nextLine.content.indexOf(header.delimiter)
|
||||||
if (delimiterPos < colonPos) {
|
if (delimiterPos < colonPos) {
|
||||||
// Delimiter before colon = data row
|
// Delimiter before colon = data row
|
||||||
throw new Error(`Expected ${header.length} tabular rows, but found more`)
|
throw new RangeError(`Expected ${header.length} tabular rows, but found more`)
|
||||||
}
|
}
|
||||||
// Colon before delimiter = key-value pair, OK
|
// Colon before delimiter = key-value pair, OK
|
||||||
}
|
}
|
||||||
@@ -315,7 +315,7 @@ function decodeListItem(
|
|||||||
): JsonValue {
|
): JsonValue {
|
||||||
const line = cursor.next()
|
const line = cursor.next()
|
||||||
if (!line) {
|
if (!line) {
|
||||||
throw new Error('Expected list item')
|
throw new ReferenceError('Expected list item')
|
||||||
}
|
}
|
||||||
|
|
||||||
const afterHyphen = line.content.slice(LIST_ITEM_PREFIX.length)
|
const afterHyphen = line.content.slice(LIST_ITEM_PREFIX.length)
|
||||||
@@ -382,7 +382,7 @@ function decodeFirstFieldOnHyphen(
|
|||||||
|
|
||||||
function assertExpectedCount(actual: number, expected: number, what: string, options: ResolvedDecodeOptions): void {
|
function assertExpectedCount(actual: number, expected: number, what: string, options: ResolvedDecodeOptions): void {
|
||||||
if (options.strict && actual !== expected) {
|
if (options.strict && actual !== expected) {
|
||||||
throw new Error(`Expected ${expected} ${what}, but got ${actual}`)
|
throw new RangeError(`Expected ${expected} ${what}, but got ${actual}`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ export function decode(input: string, options?: DecodeOptions): JsonValue {
|
|||||||
const lines = toParsedLines(input, resolved.indent)
|
const lines = toParsedLines(input, resolved.indent)
|
||||||
|
|
||||||
if (lines.length === 0) {
|
if (lines.length === 0) {
|
||||||
throw new Error('Cannot decode empty input')
|
throw new TypeError('Cannot decode empty input: input must be a non-empty string')
|
||||||
}
|
}
|
||||||
|
|
||||||
const cursor = new LineCursor(lines)
|
const cursor = new LineCursor(lines)
|
||||||
|
|||||||
@@ -256,7 +256,7 @@ export function parseStringLiteral(token: string): string {
|
|||||||
if (trimmed[i] === DOUBLE_QUOTE) {
|
if (trimmed[i] === DOUBLE_QUOTE) {
|
||||||
// Found closing quote
|
// Found closing quote
|
||||||
if (i !== trimmed.length - 1) {
|
if (i !== trimmed.length - 1) {
|
||||||
throw new Error('Unexpected characters after closing quote')
|
throw new SyntaxError('Unexpected characters after closing quote')
|
||||||
}
|
}
|
||||||
const content = trimmed.slice(1, i)
|
const content = trimmed.slice(1, i)
|
||||||
return unescapeString(content)
|
return unescapeString(content)
|
||||||
@@ -265,7 +265,7 @@ export function parseStringLiteral(token: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If we get here, no closing quote was found
|
// If we get here, no closing quote was found
|
||||||
throw new Error('Unterminated string: missing closing quote')
|
throw new SyntaxError('Unterminated string: missing closing quote')
|
||||||
}
|
}
|
||||||
|
|
||||||
return trimmed
|
return trimmed
|
||||||
@@ -278,7 +278,7 @@ export function unescapeString(value: string): string {
|
|||||||
while (i < value.length) {
|
while (i < value.length) {
|
||||||
if (value[i] === BACKSLASH) {
|
if (value[i] === BACKSLASH) {
|
||||||
if (i + 1 >= value.length) {
|
if (i + 1 >= value.length) {
|
||||||
throw new Error('Invalid escape sequence: backslash at end of string')
|
throw new SyntaxError('Invalid escape sequence: backslash at end of string')
|
||||||
}
|
}
|
||||||
|
|
||||||
const next = value[i + 1]
|
const next = value[i + 1]
|
||||||
@@ -308,7 +308,7 @@ export function unescapeString(value: string): string {
|
|||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(`Invalid escape sequence: \\${next}`)
|
throw new SyntaxError(`Invalid escape sequence: \\${next}`)
|
||||||
}
|
}
|
||||||
|
|
||||||
result += value[i]
|
result += value[i]
|
||||||
@@ -326,7 +326,7 @@ export function parseUnquotedKey(content: string, start: number): { key: string,
|
|||||||
|
|
||||||
// Validate that a colon was found
|
// Validate that a colon was found
|
||||||
if (end >= content.length || content[end] !== COLON) {
|
if (end >= content.length || content[end] !== COLON) {
|
||||||
throw new Error('Missing colon after key')
|
throw new SyntaxError('Missing colon after key')
|
||||||
}
|
}
|
||||||
|
|
||||||
const key = content.slice(start, end).trim()
|
const key = content.slice(start, end).trim()
|
||||||
@@ -355,7 +355,7 @@ export function parseQuotedKey(content: string, start: number): { key: string, e
|
|||||||
|
|
||||||
// Validate and skip colon after quoted key
|
// Validate and skip colon after quoted key
|
||||||
if (end >= content.length || content[end] !== COLON) {
|
if (end >= content.length || content[end] !== COLON) {
|
||||||
throw new Error('Missing colon after key')
|
throw new SyntaxError('Missing colon after key')
|
||||||
}
|
}
|
||||||
end++
|
end++
|
||||||
|
|
||||||
@@ -366,7 +366,7 @@ export function parseQuotedKey(content: string, start: number): { key: string, e
|
|||||||
i++
|
i++
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new Error('Unterminated quoted key')
|
throw new SyntaxError('Unterminated quoted key')
|
||||||
}
|
}
|
||||||
|
|
||||||
export function parseKeyToken(content: string, start: number): { key: string, end: number } {
|
export function parseKeyToken(content: string, start: number): { key: string, end: number } {
|
||||||
|
|||||||
Reference in New Issue
Block a user