const constant = s=> map(some(({value, type})=> value === s && type === "NAME"), tokval);
const op = s=> map(some(({value, type})=> value === s && type === "OP"), tokval);
export function getParser() { let name = map(some(t('NAME')), tokval); let rawString = map(some(t('STRING')), tokval, strip); let num = map(some(t("NUMBER")), tokval, parseFloat); let _true = map(constant("true"), always(true)); let _false = map(constant("false"), always(false)); let _null = map(constant("null"), always(null)); let enumItem = or(num, _true, _false, _null, name, rawString); let _enum = anno("enum", sep(skip(op("|")), enumItem)); let boolean = anno("boolean", map(constant("bool"), always(null))); let null_ = anno("null", map(constant("null"), always(null))); let numRange = seq(skip(op('{')), maybe(num), skip(op(",")), maybe(num), skip(op('}'))); let regexp = map(some(t("REGEXP")), tokval, strip); let string = anno("string", or(seq(skip(constant("str")), maybe(numRange), maybe(regexp)), seq(maybe(numRange), regexp))); let format = anno("format", seq(skip(op("%")), name)); let numRangeStep = seq(skip(op("{")), maybe(num), skip(op(",")), maybe(num), maybe(seq(skip(op(",")), num)), skip(op('}'))); let number = anno("number", seq(skip(constant("num")), maybe(numRangeStep))); let integer = anno("integer", seq(skip(constant("int")), maybe(numRangeStep))); let schema = decl(); let array = anno("array", seq(skip(op("[")), maybe(sep(skip(op(",")), schema)), skip(op("]")), maybe(numRange), maybe(op("!")))); let _indent = anno("indent", map(some(t("INDENT")), tokval)); let _dedent = some(t("DEDENT"), tokval); let nl = some(t("NL")); let definition = seq(op("@"), name); let key = seq(or(seq(or(name, string), maybe(op("?"))), definition), skip(op(":"))); let ref = anno("ref", seq(skip(op("@")), or(name, seq(name, skip(op(":")), name)))); let refDeclaration = map(seq(skip(op("@")), name, rawString), ([name, url])=> [name, "extref", url]); let baseSchema = or(ref, string, number, integer, boolean, null_, format, array); let oneof = anno("oneof", map(seq(oneplus(seq(baseSchema, skip(op("|")))), baseSchema), append)); let allof = anno("allof", map(seq(oneplus(seq(baseSchema, skip(op("&")))), baseSchema), append)); let anyof = anno("anyof", map(seq(oneplus(seq(baseSchema, skip(op("/")))), baseSchema), append)); let simpleSchema = or(anyof, oneof, allof, baseSchema, _enum); let dots = map(op("..."), always([null, "open", null])); let refid = map(seq(skip(op("@")), rawString), x=> [null, "id", x]); let object = decl(); let nestedObject = seq(skip(nl), skip(_indent), object, skip(_dedent)); object.define(anno("object", map(oneplus(or(map(seq(key, or(seq(simpleSchema, skip(nl)), nestedObject)), append), seq(or(dots, refid, refDeclaration), skip(nl)))), list2dict))); schema.define(or(object, simpleSchema)); return seq(skip(maybe(nl)), schema, skip(maybe(nl)), skip(done)); }