diff --git a/src/preserves/schemaparse.nim b/src/preserves/schemaparse.nim index 58a825a..0b2a284 100644 --- a/src/preserves/schemaparse.nim +++ b/src/preserves/schemaparse.nim @@ -63,13 +63,9 @@ proc match(text: string; p: var ParseState) const parser = peg("Schema", p: ParseState): - S <- *{ ' ', '\t', '\r', '\n' } + Schema <- S * +Clause * !1 - Schema <- +Clause * S * !1 - - Clause <- *LineComment * S * (Version | EmbeddedTypeName | Include | Definition) * S * '.' - - LineComment <- S * '#' * @'\n' + Clause <- (Version | EmbeddedTypeName | Include | Definition | +LineComment) * S * '.' * S Version <- "version" * S * >(*Digit): if parseInt($1) != 1: fail() @@ -86,18 +82,19 @@ const parser = peg("Schema", p: ParseState): match(readFile path, state) p.schema = move state.schema - Definition <- >id * S * '=' * S * (OrPattern | AndPattern | Pattern): + Definition <- ?Annotation * *LineComment * id * '=' * S * (OrPattern | AndPattern | Pattern): if p.schema.definitions.hasKey(Symbol $1): - raise newException(ValueError, "duplicate definition of " & $1) + raise newException(ValueError, "duplicate definition of " & $0) var node = popStack() def: Definition if not fromPreserve(def, node): - raise newException(ValueError, $1 & ": " & $node) + raise newException(ValueError, "failed to convert " & $1 & " to a Definition: " & $node) p.schema.definitions[Symbol $1] = def p.stack.setLen(0) - OrPattern <- ?('/' * S) * AltPattern * +(S * '/' * S * AltPattern): + OrDelim <- *LineComment * '/' * S * *LineComment + OrPattern <- ?OrDelim * AltPattern * +(S * OrDelim * AltPattern): var node = initRecord(toSymbol("or"), toPreserve takeStackAt()) pushStack node @@ -107,11 +104,11 @@ const parser = peg("Schema", p: ParseState): AltRef | AltLiteralPattern - AltNamed <- '@' * >id * S * Pattern: + AltNamed <- atId * ?Annotation * Pattern: var n = toPreserve @[toPreserve $1] & takeStackAt() pushStack n - AltRecord <- '<' * >id * *(S * NamedPattern) * '>': + AltRecord <- '<' * id * *NamedPattern * '>': var n = toPreserve @[ toPreserve $1, initRecord( @@ -140,13 +137,13 @@ const parser = peg("Schema", p: ParseState): initRecord(toSymbol"lit", parsePreserves $1)] pushStack n - AndPattern <- ?('&' * S) * NamedPattern * +(S * '&' * S * NamedPattern): + AndPattern <- ?'&' * S * NamedPattern * +('&' * S * NamedPattern): var node = initRecord(toSymbol("and"), toPreserve takeStackAt()) pushStack node - Pattern <- ?Annotation * (SimplePattern | CompoundPattern) + Pattern <- SimplePattern | CompoundPattern - SimplePattern <- + SimplePattern <- ( AnyPattern | AtomKindPattern | EmbeddedPattern | @@ -154,7 +151,7 @@ const parser = peg("Schema", p: ParseState): SequenceOfPattern | SetOfPattern | DictOfPattern | - Ref + Ref ) * S AnyPattern <- "any": pushStack toSymbol"any" @@ -189,17 +186,17 @@ const parser = peg("Schema", p: ParseState): LiteralPattern <- ('=' * >symbol) | ("<" * >Preserves.Value * ">") | >nonSymbolAtom: pushStack initRecord(toSymbol"lit", parsePreserves($1)) - SequenceOfPattern <- '[' * S * SimplePattern * S * "..." * S * ']': + SequenceOfPattern <- '[' * S * SimplePattern * "..." * S * ']': var n = initRecord(toSymbol"seqof", popStack()) pushStack n - SetOfPattern <- "#{" * S * SimplePattern * S * '}': + SetOfPattern <- "#{" * S * SimplePattern * '}': var n = initRecord(toSymbol"setof", popStack()) pushStack n DictOfPattern <- - '{' * - S * SimplePattern * S * ':' * S * SimplePattern * S * "...:..." * S * + '{' * S * + ?Annotation * SimplePattern * ':' * S * SimplePattern * "...:..." * S * '}': var val = popStack() @@ -214,14 +211,15 @@ const parser = peg("Schema", p: ParseState): var n = initRecord(toSymbol"ref", path, name) pushStack n - CompoundPattern <- + CompoundPattern <- ( RecordPattern | + VariableRecordPattern | TuplePattern | VariableTuplePattern | - DictionaryPattern + DictionaryPattern ) * S RecordPattern <- - ("<" * S * NamedPattern * *(S * NamedPattern) * '>') | + ("<" * S * NamedPattern * *NamedPattern * '>') | ('<' * >Value * *(S * NamedPattern) * '>'): if capture.len == 2: var n = initRecord(toSymbol"rec", @@ -232,20 +230,30 @@ const parser = peg("Schema", p: ParseState): var n = initRecord(toSymbol"rec", takeStackAfter()) pushStack n + VariableRecordPattern <- '<' * >Value * S * *(NamedPattern) * "..." * S * '>': + var fields = takeStackAfter() + var tail = fields.pop + tail[1] = initRecord(toSymbol"seqof", tail[1]) + var n = initRecord( + toSymbol"rec", + toSymbolLit $1, + initRecord(toSymbol"tuplePrefix", toPreserve fields, tail)) + pushStack n + TuplePattern <- - '[' * S * *(NamedPattern * S) * ']': + '[' * S * *NamedPattern * ']': var n = initRecord(toSymbol"tuple", toPreserve takeStackAfter()) pushStack n VariableTuplePattern <- - '[' * S * *(NamedPattern * S) * ?(Pattern * S) * "..." * S * ']': + '[' * S * *NamedPattern * ?Pattern * "..." * S * ']': var fields = takeStackAfter() var tail = fields.pop tail[1] = initRecord(toSymbol"seqof", tail[1]) var node = initRecord(toSymbol"tuplePrefix", toPreserve fields, tail) pushStack node - DictionaryPattern <- '{' * S * *(>Value * S * ':' * S * NamedSimplePattern * ?',' * S) * '}': + DictionaryPattern <- '{' * *(S * >Value * S * ':' * S * NamedSimplePattern * ?',') * S * '}': var dict = initDictionary(void) for i in countDown(pred capture.len, 1): let key = toSymbol capture[i].s @@ -253,19 +261,18 @@ const parser = peg("Schema", p: ParseState): var n = initRecord(toSymbol"dict", dict) pushStack n - NamedPattern <- ('@' * >id * S * SimplePattern) | Pattern: + NamedPattern <- ((atId * ?Annotation * SimplePattern) | Pattern): if capture.len == 2: var n = initRecord(toSymbol"named", toSymbol $1, popStack()) pushStack n - NamedSimplePattern <- ('@' * >id * S * SimplePattern) | SimplePattern: + NamedSimplePattern <- ((atId * ?Annotation * SimplePattern) | SimplePattern): if capture.len == 2: var n = initRecord(toSymbol"named", toSymbol $1, popStack()) pushStack n - id <- Alpha * *Alnum - - Comment <- '#' * @'\n' + id <- >(Alpha * *Alnum) * S + atId <- ?Annotation * '@' * id symbol <- Preserves.Symbol @@ -280,7 +287,11 @@ const parser = peg("Schema", p: ParseState): Value <- Preserves.Value: discard - Annotation <- S * '@' * Value + Annotation <- '@' * (Preserves.String | Preserves.Record) * S + + S <- *{ ' ', '\t', '\r', '\n' } + + LineComment <- '#' * @'\n' * S proc match(text: string; p: var ParseState) = let match = parser.match(text, p)