Reject a name the token grammar reserves
The dot rule was spelled twice — once for a category or folder, once for a field — and covered only the dot. Both now go through checkName, which rejects the four characters no format can name: . | ( and }. ')' stays legal: on its own it is spellable, and rejecting it would refuse a name that works. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -148,8 +148,8 @@ func compileTemplate(m map[string]any) (node, error) {
|
|||||||
if isRef(k) {
|
if isRef(k) {
|
||||||
return nil, fmt.Errorf("field %q starts with %q, which is reserved for {..path} bindings", k, refPrefix)
|
return nil, fmt.Errorf("field %q starts with %q, which is reserved for {..path} bindings", k, refPrefix)
|
||||||
}
|
}
|
||||||
if strings.Contains(k, ".") {
|
if err := checkName(k); err != nil {
|
||||||
return nil, fmt.Errorf("field %q contains a dot, which separates the segments of a path into a field", k)
|
return nil, fmt.Errorf("field %w", err)
|
||||||
}
|
}
|
||||||
n, err := compile(m[k])
|
n, err := compile(m[k])
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -250,12 +250,24 @@ func weightOf(raw any) (float64, error) {
|
|||||||
return w, nil
|
return w, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// checkName rejects a category or folder name no dot path can reach. A dot separates
|
// reservedInName is what a category, folder or field name may not contain: a dot
|
||||||
// path segments, so such a name is unaddressable by every route — unlike a field,
|
// separates the segments of a path, '|' the arms of a token, '(' opens a function
|
||||||
// which its parent's format still reaches by token.
|
// call and '}' ends the token. A name carrying one is reachable by no format, so it
|
||||||
|
// is rejected where it is authored rather than at the token that cannot reach it.
|
||||||
|
// ')' is absent deliberately — it is spellable on its own, so it stays legal.
|
||||||
|
const reservedInName = ".|(}"
|
||||||
|
|
||||||
|
// reservedList is reservedInName spelled out for an error message, so the two
|
||||||
|
// cannot drift apart.
|
||||||
|
var reservedList = strings.Join(strings.Split(reservedInName, ""), " ")
|
||||||
|
|
||||||
|
// checkName rejects a name the dot path and {token} grammars cannot spell. Both a
|
||||||
|
// category or folder and a field go through it, so there is one answer to what a
|
||||||
|
// name may contain.
|
||||||
func checkName(name string) error {
|
func checkName(name string) error {
|
||||||
if strings.Contains(name, ".") {
|
if i := strings.IndexAny(name, reservedInName); i >= 0 {
|
||||||
return fmt.Errorf("%q contains a dot, which a dot path cannot reach", name)
|
return fmt.Errorf("%q contains %q; a name may not use %s, which the dot path and {token} grammars reserve",
|
||||||
|
name, name[i:i+1], reservedList)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user