summaryrefslogtreecommitdiff
path: root/vendor/github.com/bufbuild/protocompile/ast/identifiers.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/bufbuild/protocompile/ast/identifiers.go')
-rw-r--r--vendor/github.com/bufbuild/protocompile/ast/identifiers.go153
1 files changed, 153 insertions, 0 deletions
diff --git a/vendor/github.com/bufbuild/protocompile/ast/identifiers.go b/vendor/github.com/bufbuild/protocompile/ast/identifiers.go
new file mode 100644
index 0000000..511389d
--- /dev/null
+++ b/vendor/github.com/bufbuild/protocompile/ast/identifiers.go
@@ -0,0 +1,153 @@
+// Copyright 2020-2024 Buf Technologies, Inc.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package ast
+
+import (
+ "fmt"
+ "strings"
+)
+
+// Identifier is a possibly-qualified name. This is used to distinguish
+// ValueNode values that are references/identifiers vs. those that are
+// string literals.
+type Identifier string
+
+// IdentValueNode is an AST node that represents an identifier.
+type IdentValueNode interface {
+ ValueNode
+ AsIdentifier() Identifier
+}
+
+var _ IdentValueNode = (*IdentNode)(nil)
+var _ IdentValueNode = (*CompoundIdentNode)(nil)
+
+// IdentNode represents a simple, unqualified identifier. These are used to name
+// elements declared in a protobuf file or to refer to elements. Example:
+//
+// foobar
+type IdentNode struct {
+ terminalNode
+ Val string
+}
+
+// NewIdentNode creates a new *IdentNode. The given val is the identifier text.
+func NewIdentNode(val string, tok Token) *IdentNode {
+ return &IdentNode{
+ terminalNode: tok.asTerminalNode(),
+ Val: val,
+ }
+}
+
+func (n *IdentNode) Value() interface{} {
+ return n.AsIdentifier()
+}
+
+func (n *IdentNode) AsIdentifier() Identifier {
+ return Identifier(n.Val)
+}
+
+// ToKeyword is used to convert identifiers to keywords. Since keywords are not
+// reserved in the protobuf language, they are initially lexed as identifiers
+// and then converted to keywords based on context.
+func (n *IdentNode) ToKeyword() *KeywordNode {
+ return (*KeywordNode)(n)
+}
+
+// CompoundIdentNode represents a qualified identifier. A qualified identifier
+// has at least one dot and possibly multiple identifier names (all separated by
+// dots). If the identifier has a leading dot, then it is a *fully* qualified
+// identifier. Example:
+//
+// .com.foobar.Baz
+type CompoundIdentNode struct {
+ compositeNode
+ // Optional leading dot, indicating that the identifier is fully qualified.
+ LeadingDot *RuneNode
+ Components []*IdentNode
+ // Dots[0] is the dot after Components[0]. The length of Dots is always
+ // one less than the length of Components.
+ Dots []*RuneNode
+ // The text value of the identifier, with all components and dots
+ // concatenated.
+ Val string
+}
+
+// NewCompoundIdentNode creates a *CompoundIdentNode. The leadingDot may be nil.
+// The dots arg must have a length that is one less than the length of
+// components. The components arg must not be empty.
+func NewCompoundIdentNode(leadingDot *RuneNode, components []*IdentNode, dots []*RuneNode) *CompoundIdentNode {
+ if len(components) == 0 {
+ panic("must have at least one component")
+ }
+ if len(dots) != len(components)-1 && len(dots) != len(components) {
+ panic(fmt.Sprintf("%d components requires %d dots, not %d", len(components), len(components)-1, len(dots)))
+ }
+ numChildren := len(components) + len(dots)
+ if leadingDot != nil {
+ numChildren++
+ }
+ children := make([]Node, 0, numChildren)
+ var b strings.Builder
+ if leadingDot != nil {
+ children = append(children, leadingDot)
+ b.WriteRune(leadingDot.Rune)
+ }
+ for i, comp := range components {
+ if i > 0 {
+ dot := dots[i-1]
+ children = append(children, dot)
+ b.WriteRune(dot.Rune)
+ }
+ children = append(children, comp)
+ b.WriteString(comp.Val)
+ }
+ if len(dots) == len(components) {
+ dot := dots[len(dots)-1]
+ children = append(children, dot)
+ b.WriteRune(dot.Rune)
+ }
+ return &CompoundIdentNode{
+ compositeNode: compositeNode{
+ children: children,
+ },
+ LeadingDot: leadingDot,
+ Components: components,
+ Dots: dots,
+ Val: b.String(),
+ }
+}
+
+func (n *CompoundIdentNode) Value() interface{} {
+ return n.AsIdentifier()
+}
+
+func (n *CompoundIdentNode) AsIdentifier() Identifier {
+ return Identifier(n.Val)
+}
+
+// KeywordNode is an AST node that represents a keyword. Keywords are
+// like identifiers, but they have special meaning in particular contexts.
+// Example:
+//
+// message
+type KeywordNode IdentNode
+
+// NewKeywordNode creates a new *KeywordNode. The given val is the keyword.
+func NewKeywordNode(val string, tok Token) *KeywordNode {
+ return &KeywordNode{
+ terminalNode: tok.asTerminalNode(),
+ Val: val,
+ }
+}