func (p *sourceParser) consumeSpecificType() AstNode {
	specificNode := p.startNode(dslshape.NodeTypeSpecificTypeReference)
	defer p.finishNode()
	typeName, ok := p.consumeTypePath()
	if !ok {
		return specificNode
	}
	specificNode.Decorate(dslshape.NodeSpecificReferencePredicateType, typeName)
	if _, ok := p.tryConsume(lexer.TokenTypeHash); !ok {
		return specificNode
	}
	consumed, ok := p.consume(lexer.TokenTypeIdentifier, lexer.TokenTypeEllipsis)
	if !ok {
		return specificNode
	}
	specificNode.Decorate(dslshape.NodeSpecificReferencePredicateRelation, consumed.Value)
	return specificNode
}
consumeSpecificType consumes an identifier as a specific type reference.
package parser
import (
	"fmt"
	"github.com/authzed/spicedb/pkg/schemadsl/dslshape"
	"github.com/authzed/spicedb/pkg/schemadsl/input"
	"github.com/authzed/spicedb/pkg/schemadsl/lexer"
)
func Parse(builder NodeBuilder, source input.InputSource, input string) AstNode {
	lx := lexer.Lex(source, input)
	parser := buildParser(lx, builder, source, input)
	defer parser.close()
	return parser.consumeTopLevel()
}
var ignoredTokenTypes = map[lexer.TokenType]bool{
	lexer.TokenTypeWhitespace:        true,
	lexer.TokenTypeNewline:           true,
	lexer.TokenTypeSinglelineComment: true,
	lexer.TokenTypeMultilineComment:  true,
}
func (p *sourceParser) consumeTopLevel() AstNode {
	rootNode := p.startNode(dslshape.NodeTypeFile)
	defer p.finishNode()
	p.consumeToken()
	if p.currentToken.Kind == lexer.TokenTypeError {
		p.emitError("%s", p.currentToken.Value)
		return rootNode
	}
Loop:
	for {
		if p.isToken(lexer.TokenTypeEOF) {
			break Loop
		}
		p.tryConsumeStatementTerminator()
		if p.isToken(lexer.TokenTypeEOF) {
			break Loop
		}
		switch {
		case p.isKeyword("definition"):
			rootNode.Connect(dslshape.NodePredicateChild, p.consumeDefinition())
		default:
			p.emitError("Unexpected token at root level: %v", p.currentToken.Kind)
			break Loop
		}
	}
	return rootNode
}
func (p *sourceParser) consumeDefinition() AstNode {
	defNode := p.startNode(dslshape.NodeTypeDefinition)
	defer p.finishNode()
	p.consumeKeyword("definition")
	definitionName, ok := p.consumeTypePath()
	if !ok {
		return defNode
	}
	defNode.Decorate(dslshape.NodeDefinitionPredicateName, definitionName)
	_, ok = p.consume(lexer.TokenTypeLeftBrace)
	if !ok {
		return defNode
	}
	for {
		if _, ok := p.tryConsume(lexer.TokenTypeRightBrace); ok {
			break
		}
		switch {
		case p.isKeyword("relation"):
			defNode.Connect(dslshape.NodePredicateChild, p.consumeRelation())
		case p.isKeyword("permission"):
			defNode.Connect(dslshape.NodePredicateChild, p.consumePermission())
		}
		ok := p.consumeStatementTerminator()
		if !ok {
			break
		}
	}
	return defNode
}
func (p *sourceParser) consumeRelation() AstNode {
	relNode := p.startNode(dslshape.NodeTypeRelation)
	defer p.finishNode()
	p.consumeKeyword("relation")
	relationName, ok := p.consumeIdentifier()
	if !ok {
		return relNode
	}
	relNode.Decorate(dslshape.NodePredicateName, relationName)
	_, ok = p.consume(lexer.TokenTypeColon)
	if !ok {
		return relNode
	}
	relNode.Connect(dslshape.NodeRelationPredicateAllowedTypes, p.consumeTypeReference())
	return relNode
}
func (p *sourceParser) consumeTypeReference() AstNode {
	refNode := p.startNode(dslshape.NodeTypeTypeReference)
	defer p.finishNode()
	for {
		refNode.Connect(dslshape.NodeTypeReferencePredicateType, p.consumeSpecificType())
		if _, ok := p.tryConsume(lexer.TokenTypePipe); !ok {
			break
		}
	}
	return refNode
}