UNPKG

@sinclair/typebox

Version:

Json Schema Type Builder with Static Type Resolution for TypeScript

124 lines (123 loc) 5.49 kB
import * as Guard from './guard.mjs'; import * as Token from './token.mjs'; // ------------------------------------------------------------------ // Context // ------------------------------------------------------------------ function ParseContext(moduleProperties, left, right, code, context) { const result = ParseParser(moduleProperties, left, code, context); return result.length === 2 ? ParseParser(moduleProperties, right, result[1], result[0]) : []; } // ------------------------------------------------------------------ // Array // ------------------------------------------------------------------ function ParseArray(moduleProperties, parser, code, context) { const buffer = []; let rest = code; while (rest.length > 0) { const result = ParseParser(moduleProperties, parser, rest, context); if (result.length === 0) return [buffer, rest]; buffer.push(result[0]); rest = result[1]; } return [buffer, rest]; } // ------------------------------------------------------------------ // Const // ------------------------------------------------------------------ function ParseConst(value, code, context) { return Token.Const(value, code); } // ------------------------------------------------------------------ // Ident // ------------------------------------------------------------------ function ParseIdent(code, _context) { return Token.Ident(code); } // ------------------------------------------------------------------ // Number // ------------------------------------------------------------------ // prettier-ignore function ParseNumber(code, _context) { return Token.Number(code); } // ------------------------------------------------------------------ // Optional // ------------------------------------------------------------------ function ParseOptional(moduleProperties, parser, code, context) { const result = ParseParser(moduleProperties, parser, code, context); return (result.length === 2 ? [[result[0]], result[1]] : [[], code]); } // ------------------------------------------------------------------ // Ref // ------------------------------------------------------------------ function ParseRef(moduleProperties, ref, code, context) { const parser = moduleProperties[ref]; if (!Guard.IsParser(parser)) throw Error(`Cannot dereference Parser '${ref}'`); return ParseParser(moduleProperties, parser, code, context); } // ------------------------------------------------------------------ // String // ------------------------------------------------------------------ // prettier-ignore function ParseString(options, code, _context) { return Token.String(options, code); } // ------------------------------------------------------------------ // Tuple // ------------------------------------------------------------------ function ParseTuple(moduleProperties, parsers, code, context) { const buffer = []; let rest = code; for (const parser of parsers) { const result = ParseParser(moduleProperties, parser, rest, context); if (result.length === 0) return []; buffer.push(result[0]); rest = result[1]; } return [buffer, rest]; } // ------------------------------------------------------------------ // Union // ------------------------------------------------------------------ // prettier-ignore function ParseUnion(moduleProperties, parsers, code, context) { for (const parser of parsers) { const result = ParseParser(moduleProperties, parser, code, context); if (result.length === 0) continue; return result; } return []; } // ------------------------------------------------------------------ // Parser // ------------------------------------------------------------------ // prettier-ignore function ParseParser(moduleProperties, parser, code, context) { const result = (Guard.IsContext(parser) ? ParseContext(moduleProperties, parser.left, parser.right, code, context) : Guard.IsArray(parser) ? ParseArray(moduleProperties, parser.parser, code, context) : Guard.IsConst(parser) ? ParseConst(parser.value, code, context) : Guard.IsIdent(parser) ? ParseIdent(code, context) : Guard.IsNumber(parser) ? ParseNumber(code, context) : Guard.IsOptional(parser) ? ParseOptional(moduleProperties, parser.parser, code, context) : Guard.IsRef(parser) ? ParseRef(moduleProperties, parser.ref, code, context) : Guard.IsString(parser) ? ParseString(parser.options, code, context) : Guard.IsTuple(parser) ? ParseTuple(moduleProperties, parser.parsers, code, context) : Guard.IsUnion(parser) ? ParseUnion(moduleProperties, parser.parsers, code, context) : []); return (result.length === 2 ? [parser.mapping(result[0], context), result[1]] : result); } /** Parses content using the given parser */ // prettier-ignore export function Parse(...args) { const withModuleProperties = typeof args[1] === 'string' ? false : true; const [moduleProperties, parser, content, context] = withModuleProperties ? [args[0], args[1], args[2], args[3]] : [{}, args[0], args[1], args[2]]; return ParseParser(moduleProperties, parser, content, context); }