Allow "sufficiently identifierlike" values in dictionaries too
This commit is contained in:
parent
071566b1e1
commit
2e84614b3b
|
@ -95,7 +95,6 @@ export function anonymousSimplePattern(p: M.SimplePattern): M.NamedPattern {
|
|||
export function namelike(x: Input): string | undefined {
|
||||
if (typeof x === 'string') return x;
|
||||
if (typeof x === 'symbol') return x.description!;
|
||||
if (typeof x === 'number') return '' + x;
|
||||
if (typeof x === 'boolean') return '' + x;
|
||||
if (typeof x === 'boolean') return x ? 'true' : 'false';
|
||||
return void 0;
|
||||
}
|
||||
|
|
|
@ -161,7 +161,12 @@ function parseDefinition(name: symbol, pos: Position | null, body: Array<Input>)
|
|||
p.value._variant === 'lit')
|
||||
{
|
||||
const s = M.namelike(p.value.value);
|
||||
if (s !== void 0) return M.NamedAlternative({ variantLabel: s, pattern: p });
|
||||
if (s !== void 0) {
|
||||
if (M.isValidToken(s)) {
|
||||
return M.NamedAlternative({ variantLabel: s, pattern: p });
|
||||
}
|
||||
throw new SchemaSyntaxError(preserves`Invalid name ${s} inferred for alternative: ${input}`, pos);
|
||||
}
|
||||
}
|
||||
throw new SchemaSyntaxError(preserves`Name missing for alternative: ${input}`, pos);
|
||||
}
|
||||
|
@ -338,11 +343,11 @@ function parsePattern(name: symbol, body0: Array<Input>): Pattern {
|
|||
return (b: Input) => {
|
||||
let name = findName(b);
|
||||
if (name === false) {
|
||||
if (literalName !== void 0 &&
|
||||
typeof literalName === 'symbol' &&
|
||||
M.isValidToken(literalName.description!))
|
||||
{
|
||||
name = literalName;
|
||||
if (literalName !== void 0) {
|
||||
const s = M.namelike(literalName);
|
||||
if (s !== void 0 && M.isValidToken(s)) {
|
||||
name = Symbol.for(s);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (name === false) {
|
||||
|
|
|
@ -80,9 +80,8 @@
|
|||
|
||||
(define (namelike v)
|
||||
(match v
|
||||
[(? string? s) (string->symbol s)]
|
||||
[(? symbol? s) s]
|
||||
[(? number? n) (string->symbol (number->string n))]
|
||||
[(? string? s) (string->symbol s)]
|
||||
[(? boolean? b) (if b 'true 'false)]
|
||||
[_ #f]))
|
||||
|
||||
|
@ -194,9 +193,9 @@
|
|||
values
|
||||
(lambda () (error 'parse-simple-dsl "Compound patterns not accepted here: ~a" (input->string stx)))))
|
||||
|
||||
(define ((maybe-named* knamed kanonymous recur [literal-name #f]) b)
|
||||
(define ((maybe-named* knamed kanonymous recur [literal-name '#:none]) b)
|
||||
(define n (or (find-name b)
|
||||
(and (valid-id? literal-name) literal-name)))
|
||||
(let ((n (namelike literal-name))) (and (valid-id? n) n))))
|
||||
(if n
|
||||
(let ((p (parse-simple-dsl
|
||||
b
|
||||
|
|
|
@ -4,9 +4,11 @@ title: "Preserves Schema"
|
|||
---
|
||||
|
||||
Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||
October 2023. Version 0.3.3.
|
||||
October 2023. Version 0.3.4.
|
||||
|
||||
[abnf]: https://tools.ietf.org/html/rfc7405
|
||||
[identifierlike]: #sufficiently-identifierlike-values
|
||||
[valid identifier]: #identifiers-and-capitalization-conventions
|
||||
|
||||
This document proposes a Schema language for the
|
||||
[Preserves data model](./preserves.html).
|
||||
|
@ -210,8 +212,9 @@ a member of a tagged union type).
|
|||
A variant name can either be given explicitly as `@name` or
|
||||
inferred.[^variant-names-unlike-binding-names] It can only be inferred
|
||||
from the label of a record pattern, from the name of a reference to
|
||||
another definition, or from the text of a "sufficiently identifierlike"
|
||||
literal pattern - one that matches a string, symbol, number or boolean:
|
||||
another definition, or from the text of a "[sufficiently
|
||||
identifierlike][identifierlike]" literal pattern - one that matches a
|
||||
string, symbol or boolean:
|
||||
|
||||
AltPattern = "@" id Pattern
|
||||
/ "<" id PatternSequence ">"
|
||||
|
@ -405,8 +408,10 @@ fixed-position patterns.
|
|||
|
||||
A dictionary pattern matches specific literal keys in an input
|
||||
dictionary. If no explicit name is given for a particular
|
||||
`NamedSimplePattern`, but the key for the pattern is a symbol, then
|
||||
that symbol is used as the name for that dictionary entry.
|
||||
`NamedSimplePattern`, but the key for the pattern is "[sufficiently
|
||||
identifierlike][identifierlike]" (a string, symbol or boolean), then a
|
||||
symbol formed from that key is used as the name for that dictionary
|
||||
entry.
|
||||
|
||||
DictionaryPattern = "{" *(value ":" NamedSimplePattern) "}"
|
||||
|
||||
|
@ -423,6 +428,29 @@ the given name in the overall record type for a definition. The type
|
|||
of value contained in the field will correspond to the `Pattern` or
|
||||
`SimplePattern` given.
|
||||
|
||||
### "Sufficiently Identifierlike" Values
|
||||
|
||||
In some places in a schema, names can be inferred from some nearby
|
||||
literal pattern element. In an `OrPattern`, variant names can be
|
||||
inferred; in a `DictionaryPattern`, names for dictionary entries can be
|
||||
inferred.
|
||||
|
||||
The rules are simple: if the literal pattern would match a specific
|
||||
symbol or string, then that specific value is converted to a symbol and
|
||||
used as the name. If the pattern would match `#t`, the name will be
|
||||
`true`; if it would match `#f`, the name will be `false`.
|
||||
|
||||
For example, in the following grammar, the names for the variants of
|
||||
`Example1` are the symbols `foo` and `bar` and `false`, and the names
|
||||
for the two fields in `Example2` are `example` and `|testing strings|`.
|
||||
Note that `|testing strings|` is a symbol whose name contains a space,
|
||||
which will be rejected because it is not a [valid identifier][].
|
||||
|
||||
```preserves-schema
|
||||
Example1 = =foo / "bar" / #f .
|
||||
Example2 = { "testing strings": int, example: string } .
|
||||
```
|
||||
|
||||
## Semantics
|
||||
|
||||
Having covered concrete syntax, we now give semantics for the schema
|
||||
|
|
Loading…
Reference in New Issue