From 94223148d697b3beeaa1ec3ca5dc68a73cb9efcd Mon Sep 17 00:00:00 2001 From: Roger Peppe Date: Mon, 6 Feb 2023 10:04:44 +0000 Subject: [PATCH] cue/ast: fix IsValidIdent for _0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Currently `IsValidIdent` returns false for the identifier `_1`. This is not correct: the specification defines as valid identifier as: identifier = [ "#" | "_#" ] letter { letter | unicode_digit } . where `letter` includes underscore. This caused an observed panic in `internal/core/export.(*pivotter)` when it calls `exporter.ident`. I was wanting to add the test before introducing the fix, but this isn't possible with the current `IsValidIdentifer` tests because they check for consistency between `LabelName` and `IsValidIdentifier` and the current logic is not consistent for this case. Signed-off-by: Roger Peppe Change-Id: Icb571edbcac97e7f076497d45a03c7b524d92d20 Reviewed-on: https://review.gerrithub.io/c/cue-lang/cue/+/549423 Reviewed-by: Daniel Martí Unity-Result: CUEcueckoo TryBot-Result: CUEcueckoo --- cue/ast/ident.go | 17 +++++++++-------- cue/ast/ident_test.go | 8 ++++++++ 2 files changed, 17 insertions(+), 8 deletions(-) diff --git a/cue/ast/ident.go b/cue/ast/ident.go index 3d81806a7cd..20d7b5d6bd0 100644 --- a/cue/ast/ident.go +++ b/cue/ast/ident.go @@ -39,25 +39,26 @@ func IsValidIdent(ident string) bool { return false } - // TODO: use consumed again to allow #0. - // consumed := false + consumed := false if strings.HasPrefix(ident, "_") { ident = ident[1:] - // consumed = true + consumed = true if len(ident) == 0 { return true } } if strings.HasPrefix(ident, "#") { ident = ident[1:] - // consumed = true + // Note: _#0 is not allowed by the spec, although _0 is. + // TODO: set consumed to true here to allow #0. + consumed = false } - // if !consumed { - if r, _ := utf8.DecodeRuneInString(ident); isDigit(r) { - return false + if !consumed { + if r, _ := utf8.DecodeRuneInString(ident); isDigit(r) { + return false + } } - // } for _, r := range ident { if isLetter(r) || isDigit(r) || r == '_' || r == '$' { diff --git a/cue/ast/ident_test.go b/cue/ast/ident_test.go index 1093320f519..2437cd42ab1 100644 --- a/cue/ast/ident_test.go +++ b/cue/ast/ident_test.go @@ -72,6 +72,14 @@ func TestLabelName(t *testing.T) { in: &ast.Ident{Name: "_"}, out: "_", isIdent: true, + }, { + in: &ast.Ident{Name: "_1"}, + out: "_1", + isIdent: true, + }, { + in: &ast.Ident{Name: "_#1"}, + out: "", + err: true, }, { in: &ast.Ident{Name: "8ball"}, out: "",