From 9b89c57ce1e1ed77b27b4ac85b7956da8e53c6c9 Mon Sep 17 00:00:00 2001 From: Joseph Schorr Date: Mon, 25 Nov 2024 13:36:44 -0500 Subject: [PATCH] Add basic parser support for `with expiration` on subject types --- pkg/schemadsl/dslshape/dslshape.go | 19 ++++ .../dslshape/zz_generated.nodetype_string.go | 38 ++++---- pkg/schemadsl/parser/parser.go | 87 ++++++++++++++++--- pkg/schemadsl/parser/parser_impl.go | 33 +++++-- pkg/schemadsl/parser/parser_test.go | 6 ++ .../parser/tests/caveatstype.zed.expected | 8 +- .../parser/tests/expirationnonkeyword.zed | 3 + .../tests/expirationnonkeyword.zed.expected | 29 +++++++ pkg/schemadsl/parser/tests/invaliduse.zed | 3 + .../parser/tests/invaliduse.zed.expected | 22 +++++ .../parser/tests/invaliduseexpiration.zed | 5 ++ .../tests/invaliduseexpiration.zed.expected | 50 +++++++++++ .../parser/tests/multipleslashes.zed.expected | 2 +- .../parser/tests/superlarge.zed.expected | 2 +- pkg/schemadsl/parser/tests/useafterdef.zed | 3 + .../parser/tests/useafterdef.zed.expected | 16 ++++ pkg/schemadsl/parser/tests/useexpiration.zed | 6 ++ .../parser/tests/useexpiration.zed.expected | 66 ++++++++++++++ .../parser/tests/useexpirationkeyword.zed | 5 ++ .../tests/useexpirationkeyword.zed.expected | 27 ++++++ 20 files changed, 387 insertions(+), 43 deletions(-) create mode 100644 pkg/schemadsl/parser/tests/expirationnonkeyword.zed create mode 100644 pkg/schemadsl/parser/tests/expirationnonkeyword.zed.expected create mode 100644 pkg/schemadsl/parser/tests/invaliduse.zed create mode 100644 pkg/schemadsl/parser/tests/invaliduse.zed.expected create mode 100644 pkg/schemadsl/parser/tests/invaliduseexpiration.zed create mode 100644 pkg/schemadsl/parser/tests/invaliduseexpiration.zed.expected create mode 100644 pkg/schemadsl/parser/tests/useafterdef.zed create mode 100644 pkg/schemadsl/parser/tests/useafterdef.zed.expected create mode 100644 pkg/schemadsl/parser/tests/useexpiration.zed create mode 100644 pkg/schemadsl/parser/tests/useexpiration.zed.expected create mode 100644 pkg/schemadsl/parser/tests/useexpirationkeyword.zed create mode 100644 pkg/schemadsl/parser/tests/useexpirationkeyword.zed.expected diff --git a/pkg/schemadsl/dslshape/dslshape.go b/pkg/schemadsl/dslshape/dslshape.go index 2421f59690..cf0b776ad2 100644 --- a/pkg/schemadsl/dslshape/dslshape.go +++ b/pkg/schemadsl/dslshape/dslshape.go @@ -11,6 +11,7 @@ const ( NodeTypeError NodeType = iota // error occurred; value is text of error NodeTypeFile // The file root node NodeTypeComment // A single or multiline comment + NodeTypeUseFlag // A use flag NodeTypeDefinition // A definition. NodeTypeCaveatDefinition // A caveat definition. @@ -24,6 +25,7 @@ const ( NodeTypeTypeReference // A type reference NodeTypeSpecificTypeReference // A reference to a specific type. NodeTypeCaveatReference // A caveat reference under a type. + NodeTypeTraitReference // A trait reference under a typr. NodeTypeUnionExpression NodeTypeIntersectExpression @@ -71,6 +73,13 @@ const ( // The value of the comment, including its delimeter(s) NodeCommentPredicateValue = "comment-value" + // + // NodeTypeUseFlag + // + + // The name of the use flag. + NodeUseFlagPredicateName = "use-flag-name" + // // NodeTypeDefinition // @@ -155,6 +164,9 @@ const ( // A caveat under a type reference. NodeSpecificReferencePredicateCaveat = "caveat" + // A trait under a type reference. + NodeSpecificReferencePredicateTrait = "trait" + // // NodeTypeCaveatReference // @@ -162,6 +174,13 @@ const ( // The caveat name under the caveat. NodeCaveatPredicateCaveat = "caveat-name" + // + // NodeTypeTraitReference + // + + // The trait name under the trait. + NodeTraitPredicateTrait = "trait-name" + // // NodeTypePermission // diff --git a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go index 3567416c6b..4ef1e067e7 100644 --- a/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go +++ b/pkg/schemadsl/dslshape/zz_generated.nodetype_string.go @@ -11,27 +11,29 @@ func _() { _ = x[NodeTypeError-0] _ = x[NodeTypeFile-1] _ = x[NodeTypeComment-2] - _ = x[NodeTypeDefinition-3] - _ = x[NodeTypeCaveatDefinition-4] - _ = x[NodeTypeCaveatParameter-5] - _ = x[NodeTypeCaveatExpression-6] - _ = x[NodeTypeRelation-7] - _ = x[NodeTypePermission-8] - _ = x[NodeTypeTypeReference-9] - _ = x[NodeTypeSpecificTypeReference-10] - _ = x[NodeTypeCaveatReference-11] - _ = x[NodeTypeUnionExpression-12] - _ = x[NodeTypeIntersectExpression-13] - _ = x[NodeTypeExclusionExpression-14] - _ = x[NodeTypeArrowExpression-15] - _ = x[NodeTypeIdentifier-16] - _ = x[NodeTypeNilExpression-17] - _ = x[NodeTypeCaveatTypeReference-18] + _ = x[NodeTypeUseFlag-3] + _ = x[NodeTypeDefinition-4] + _ = x[NodeTypeCaveatDefinition-5] + _ = x[NodeTypeCaveatParameter-6] + _ = x[NodeTypeCaveatExpression-7] + _ = x[NodeTypeRelation-8] + _ = x[NodeTypePermission-9] + _ = x[NodeTypeTypeReference-10] + _ = x[NodeTypeSpecificTypeReference-11] + _ = x[NodeTypeCaveatReference-12] + _ = x[NodeTypeTraitReference-13] + _ = x[NodeTypeUnionExpression-14] + _ = x[NodeTypeIntersectExpression-15] + _ = x[NodeTypeExclusionExpression-16] + _ = x[NodeTypeArrowExpression-17] + _ = x[NodeTypeIdentifier-18] + _ = x[NodeTypeNilExpression-19] + _ = x[NodeTypeCaveatTypeReference-20] } -const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" +const _NodeType_name = "NodeTypeErrorNodeTypeFileNodeTypeCommentNodeTypeUseFlagNodeTypeDefinitionNodeTypeCaveatDefinitionNodeTypeCaveatParameterNodeTypeCaveatExpressionNodeTypeRelationNodeTypePermissionNodeTypeTypeReferenceNodeTypeSpecificTypeReferenceNodeTypeCaveatReferenceNodeTypeTraitReferenceNodeTypeUnionExpressionNodeTypeIntersectExpressionNodeTypeExclusionExpressionNodeTypeArrowExpressionNodeTypeIdentifierNodeTypeNilExpressionNodeTypeCaveatTypeReference" -var _NodeType_index = [...]uint16{0, 13, 25, 40, 58, 82, 105, 129, 145, 163, 184, 213, 236, 259, 286, 313, 336, 354, 375, 402} +var _NodeType_index = [...]uint16{0, 13, 25, 40, 55, 73, 97, 120, 144, 160, 178, 199, 228, 251, 273, 296, 323, 350, 373, 391, 412, 439} func (i NodeType) String() string { if i < 0 || i >= NodeType(len(_NodeType_index)-1) { diff --git a/pkg/schemadsl/parser/parser.go b/pkg/schemadsl/parser/parser.go index 6806420bbe..0b1ad2b69c 100644 --- a/pkg/schemadsl/parser/parser.go +++ b/pkg/schemadsl/parser/parser.go @@ -4,6 +4,8 @@ package parser import ( "strings" + "golang.org/x/exp/maps" + "github.com/authzed/spicedb/pkg/schemadsl/dslshape" "github.com/authzed/spicedb/pkg/schemadsl/input" "github.com/authzed/spicedb/pkg/schemadsl/lexer" @@ -38,12 +40,20 @@ func (p *sourceParser) consumeTopLevel() AstNode { return rootNode } + hasSeenDefinition := false + Loop: for { if p.isToken(lexer.TokenTypeEOF) { break Loop } + if !hasSeenDefinition { + if p.isIdentifier("use") { + rootNode.Connect(dslshape.NodePredicateChild, p.consumeUseFlag()) + } + } + // Consume a statement terminator if one was found. p.tryConsumeStatementTerminator() @@ -57,9 +67,11 @@ Loop: switch { case p.isKeyword("definition"): + hasSeenDefinition = true rootNode.Connect(dslshape.NodePredicateChild, p.consumeDefinition()) case p.isKeyword("caveat"): + hasSeenDefinition = true rootNode.Connect(dslshape.NodePredicateChild, p.consumeCaveat()) default: @@ -231,6 +243,35 @@ func (p *sourceParser) consumeCaveatTypeReference() AstNode { return typeRefNode } +// consumeUseFlag attempts to consume a use flag. +// ``` use flagname ``` +func (p *sourceParser) consumeUseFlag() AstNode { + useNode := p.startNode(dslshape.NodeTypeUseFlag) + defer p.mustFinishNode() + + // consume the `use` + p.consumeIdentifier() + + var useFlag string + if p.isToken(lexer.TokenTypeIdentifier) { + useFlag, _ = p.consumeIdentifier() + } else { + useName, ok := p.consumeVariableKeyword() + if !ok { + return useNode + } + useFlag = useName + } + + if _, ok := lexer.Flags[useFlag]; !ok { + p.emitErrorf("Unknown use flag: `%s`. Options are: %s", useFlag, strings.Join(maps.Keys(lexer.Flags), ", ")) + return useNode + } + + useNode.MustDecorate(dslshape.NodeUseFlagPredicateName, useFlag) + return useNode +} + // consumeDefinition attempts to consume a single schema definition. // ```definition somedef { ... }``` func (p *sourceParser) consumeDefinition() AstNode { @@ -323,17 +364,9 @@ func (p *sourceParser) consumeTypeReference() AstNode { // tryConsumeWithCaveat tries to consume a caveat `with` expression. func (p *sourceParser) tryConsumeWithCaveat() (AstNode, bool) { - if !p.isKeyword("with") { - return nil, false - } - caveatNode := p.startNode(dslshape.NodeTypeCaveatReference) defer p.mustFinishNode() - if ok := p.consumeKeyword("with"); !ok { - return nil, ok - } - consumed, ok := p.consumeTypePath() if !ok { return caveatNode, true @@ -348,14 +381,46 @@ func (p *sourceParser) consumeSpecificTypeWithCaveat() AstNode { specificNode := p.consumeSpecificTypeWithoutFinish() defer p.mustFinishNode() - caveatNode, ok := p.tryConsumeWithCaveat() - if ok { - specificNode.Connect(dslshape.NodeSpecificReferencePredicateCaveat, caveatNode) + // Check for a caveat and/or supported trait. + if !p.isKeyword("with") { + return specificNode + } + + p.consumeKeyword("with") + + if !p.isKeyword("expiration") { + caveatNode, ok := p.tryConsumeWithCaveat() + if ok { + specificNode.Connect(dslshape.NodeSpecificReferencePredicateCaveat, caveatNode) + } + + if !p.tryConsumeKeyword("and") { + return specificNode + } + } + + if p.isKeyword("expiration") { + // Check for expiration trait. + traitNode := p.consumeExpirationTrait() + + // Decorate with the expiration trait. + specificNode.Connect(dslshape.NodeSpecificReferencePredicateTrait, traitNode) } return specificNode } +// consumeExpirationTrait consumes an expiration trait. +func (p *sourceParser) consumeExpirationTrait() AstNode { + expirationTraitNode := p.startNode(dslshape.NodeTypeTraitReference) + p.consumeKeyword("expiration") + + expirationTraitNode.MustDecorate(dslshape.NodeTraitPredicateTrait, "expiration") + defer p.mustFinishNode() + + return expirationTraitNode +} + // consumeSpecificTypeOpen consumes an identifier as a specific type reference. func (p *sourceParser) consumeSpecificTypeWithoutFinish() AstNode { specificNode := p.startNode(dslshape.NodeTypeSpecificTypeReference) diff --git a/pkg/schemadsl/parser/parser_impl.go b/pkg/schemadsl/parser/parser_impl.go index 76f2bf3839..c63aec34ed 100644 --- a/pkg/schemadsl/parser/parser_impl.go +++ b/pkg/schemadsl/parser/parser_impl.go @@ -44,18 +44,18 @@ type commentedLexeme struct { // sourceParser holds the state of the parser. type sourceParser struct { - source input.Source // the name of the input; used only for error reports - input string // the input string itself - lex *lexer.PeekableLexer // a reference to the lexer used for tokenization - builder NodeBuilder // the builder function for creating AstNode instances - nodes *nodeStack // the stack of the current nodes - currentToken commentedLexeme // the current token - previousToken commentedLexeme // the previous token + source input.Source // the name of the input; used only for error reports + input string // the input string itself + lex *lexer.FlaggableLexler // a reference to the lexer used for tokenization + builder NodeBuilder // the builder function for creating AstNode instances + nodes *nodeStack // the stack of the current nodes + currentToken commentedLexeme // the current token + previousToken commentedLexeme // the previous token } // buildParser returns a new sourceParser instance. func buildParser(lx *lexer.Lexer, builder NodeBuilder, source input.Source, input string) *sourceParser { - l := lexer.NewPeekableLexer(lx) + l := lexer.NewFlaggableLexler(lx) return &sourceParser{ source: source, input: input, @@ -163,6 +163,11 @@ func (p *sourceParser) isToken(types ...lexer.TokenType) bool { return false } +// isIdentifier returns true if the current token is an identifier matching that given. +func (p *sourceParser) isIdentifier(identifier string) bool { + return p.isToken(lexer.TokenTypeIdentifier) && p.currentToken.Value == identifier +} + // isKeyword returns true if the current token is a keyword matching that given. func (p *sourceParser) isKeyword(keyword string) bool { return p.isToken(lexer.TokenTypeKeyword) && p.currentToken.Value == keyword @@ -178,6 +183,18 @@ func (p *sourceParser) emitErrorf(format string, args ...interface{}) { p.currentNode().Connect(dslshape.NodePredicateChild, errorNode) } +// consumeVariableKeyword consumes an expected keyword token or adds an error node. +func (p *sourceParser) consumeVariableKeyword() (string, bool) { + if !p.isToken(lexer.TokenTypeKeyword) { + p.emitErrorf("Expected keyword, found token %v", p.currentToken.Kind) + return "", false + } + + token := p.currentToken + p.consumeToken() + return token.Value, true +} + // consumeKeyword consumes an expected keyword token or adds an error node. func (p *sourceParser) consumeKeyword(keyword string) bool { if !p.tryConsumeKeyword(keyword) { diff --git a/pkg/schemadsl/parser/parser_test.go b/pkg/schemadsl/parser/parser_test.go index f5992e5177..b96eead9f9 100644 --- a/pkg/schemadsl/parser/parser_test.go +++ b/pkg/schemadsl/parser/parser_test.go @@ -122,6 +122,12 @@ func TestParser(t *testing.T) { {"arrow illegal operations test", "arrowillegalops"}, {"arrow illegal function test", "arrowillegalfunc"}, {"caveat with keyword parameter test", "caveatwithkeywordparam"}, + {"use expiration test", "useexpiration"}, + {"use expiration keyword test", "useexpirationkeyword"}, + {"expiration non-keyword test", "expirationnonkeyword"}, + {"invalid use", "invaliduse"}, + {"use after definition", "useafterdef"}, + {"invalid use expiration test", "invaliduseexpiration"}, } for _, test := range parserTests { diff --git a/pkg/schemadsl/parser/tests/caveatstype.zed.expected b/pkg/schemadsl/parser/tests/caveatstype.zed.expected index c8a9fa2f8f..bcbc38c8a0 100644 --- a/pkg/schemadsl/parser/tests/caveatstype.zed.expected +++ b/pkg/schemadsl/parser/tests/caveatstype.zed.expected @@ -35,7 +35,7 @@ NodeTypeFile caveat-name = somecaveat end-rune = 67 input-source = caveats type test - start-rune = 53 + start-rune = 58 NodeTypeSpecificTypeReference end-rune = 100 input-source = caveats type test @@ -47,7 +47,7 @@ NodeTypeFile caveat-name = anothercaveat end-rune = 100 input-source = caveats type test - start-rune = 83 + start-rune = 88 NodeTypeRelation end-rune = 187 input-source = caveats type test @@ -75,7 +75,7 @@ NodeTypeFile caveat-name = wildcardcaveat end-rune = 153 input-source = caveats type test - start-rune = 135 + start-rune = 140 NodeTypeSpecificTypeReference end-rune = 187 input-source = caveats type test @@ -86,4 +86,4 @@ NodeTypeFile caveat-name = someprefix/somecaveat end-rune = 187 input-source = caveats type test - start-rune = 162 \ No newline at end of file + start-rune = 167 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/expirationnonkeyword.zed b/pkg/schemadsl/parser/tests/expirationnonkeyword.zed new file mode 100644 index 0000000000..4d23a3f262 --- /dev/null +++ b/pkg/schemadsl/parser/tests/expirationnonkeyword.zed @@ -0,0 +1,3 @@ +caveat expiration(someparam int) { + someparam == 42 +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/expirationnonkeyword.zed.expected b/pkg/schemadsl/parser/tests/expirationnonkeyword.zed.expected new file mode 100644 index 0000000000..109f23c22d --- /dev/null +++ b/pkg/schemadsl/parser/tests/expirationnonkeyword.zed.expected @@ -0,0 +1,29 @@ +NodeTypeFile + end-rune = 52 + input-source = expiration non-keyword test + start-rune = 0 + child-node => + NodeTypeCaveatDefinition + caveat-definition-name = expiration + end-rune = 52 + input-source = expiration non-keyword test + start-rune = 0 + caveat-definition-expression => + NodeTypeCaveatExpression + caveat-expression-expressionstr = someparam == 42 + + end-rune = 51 + input-source = expiration non-keyword test + start-rune = 36 + parameters => + NodeTypeCaveatParameter + caveat-parameter-name = someparam + end-rune = 30 + input-source = expiration non-keyword test + start-rune = 18 + caveat-parameter-type => + NodeTypeCaveatTypeReference + end-rune = 30 + input-source = expiration non-keyword test + start-rune = 28 + type-name = int \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invaliduse.zed b/pkg/schemadsl/parser/tests/invaliduse.zed new file mode 100644 index 0000000000..a74a63239b --- /dev/null +++ b/pkg/schemadsl/parser/tests/invaliduse.zed @@ -0,0 +1,3 @@ +use something + +definition resource {} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invaliduse.zed.expected b/pkg/schemadsl/parser/tests/invaliduse.zed.expected new file mode 100644 index 0000000000..f36654ba97 --- /dev/null +++ b/pkg/schemadsl/parser/tests/invaliduse.zed.expected @@ -0,0 +1,22 @@ +NodeTypeFile + end-rune = 36 + input-source = invalid use + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 12 + input-source = invalid use + start-rune = 0 + child-node => + NodeTypeError + end-rune = 12 + error-message = Unknown use flag: `something`. Options are: expiration + error-source = + + input-source = invalid use + start-rune = 13 + NodeTypeDefinition + definition-name = resource + end-rune = 36 + input-source = invalid use + start-rune = 15 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invaliduseexpiration.zed b/pkg/schemadsl/parser/tests/invaliduseexpiration.zed new file mode 100644 index 0000000000..fc3dab5e81 --- /dev/null +++ b/pkg/schemadsl/parser/tests/invaliduseexpiration.zed @@ -0,0 +1,5 @@ +use expiration + +definition resource { + relation editor: user with somecaveat expiration +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/invaliduseexpiration.zed.expected b/pkg/schemadsl/parser/tests/invaliduseexpiration.zed.expected new file mode 100644 index 0000000000..09ef641bc2 --- /dev/null +++ b/pkg/schemadsl/parser/tests/invaliduseexpiration.zed.expected @@ -0,0 +1,50 @@ +NodeTypeFile + end-rune = 78 + input-source = invalid use expiration test + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 13 + input-source = invalid use expiration test + start-rune = 0 + use-flag-name = expiration + NodeTypeDefinition + definition-name = resource + end-rune = 78 + input-source = invalid use expiration test + start-rune = 16 + child-node => + NodeTypeRelation + end-rune = 78 + input-source = invalid use expiration test + relation-name = editor + start-rune = 42 + allowed-types => + NodeTypeTypeReference + end-rune = 78 + input-source = invalid use expiration test + start-rune = 59 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 78 + input-source = invalid use expiration test + start-rune = 59 + type-name = user + caveat => + NodeTypeCaveatReference + caveat-name = somecaveat + end-rune = 78 + input-source = invalid use expiration test + start-rune = 69 + NodeTypeError + end-rune = 78 + error-message = Expected end of statement or definition, found: TokenTypeKeyword + error-source = expiration + input-source = invalid use expiration test + start-rune = 80 + NodeTypeError + end-rune = 78 + error-message = Unexpected token at root level: TokenTypeKeyword + error-source = expiration + input-source = invalid use expiration test + start-rune = 80 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/multipleslashes.zed.expected b/pkg/schemadsl/parser/tests/multipleslashes.zed.expected index 9f3dad7d74..a9931fc9e7 100644 --- a/pkg/schemadsl/parser/tests/multipleslashes.zed.expected +++ b/pkg/schemadsl/parser/tests/multipleslashes.zed.expected @@ -35,7 +35,7 @@ NodeTypeFile caveat-name = foo/bar/only_on_tuesday end-rune = 116 input-source = multiple slashes in object type - start-rune = 89 + start-rune = 94 NodeTypeCaveatDefinition caveat-definition-name = foo/bar/only_on_tuesday end-rune = 201 diff --git a/pkg/schemadsl/parser/tests/superlarge.zed.expected b/pkg/schemadsl/parser/tests/superlarge.zed.expected index 3169587303..9c37affa9b 100644 --- a/pkg/schemadsl/parser/tests/superlarge.zed.expected +++ b/pkg/schemadsl/parser/tests/superlarge.zed.expected @@ -19910,7 +19910,7 @@ NodeTypeFile caveat-name = unexpired_grant end-rune = 106073 input-source = super large test - start-rune = 106054 + start-rune = 106059 NodeTypePermission end-rune = 106100 input-source = super large test diff --git a/pkg/schemadsl/parser/tests/useafterdef.zed b/pkg/schemadsl/parser/tests/useafterdef.zed new file mode 100644 index 0000000000..e171f928ff --- /dev/null +++ b/pkg/schemadsl/parser/tests/useafterdef.zed @@ -0,0 +1,3 @@ +definition resource {} + +use expiration \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/useafterdef.zed.expected b/pkg/schemadsl/parser/tests/useafterdef.zed.expected new file mode 100644 index 0000000000..7154b75c12 --- /dev/null +++ b/pkg/schemadsl/parser/tests/useafterdef.zed.expected @@ -0,0 +1,16 @@ +NodeTypeFile + end-rune = 22 + input-source = use after definition + start-rune = 0 + child-node => + NodeTypeDefinition + definition-name = resource + end-rune = 21 + input-source = use after definition + start-rune = 0 + NodeTypeError + end-rune = 22 + error-message = Unexpected token at root level: TokenTypeIdentifier + error-source = use + input-source = use after definition + start-rune = 24 \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/useexpiration.zed b/pkg/schemadsl/parser/tests/useexpiration.zed new file mode 100644 index 0000000000..3d39bc6e02 --- /dev/null +++ b/pkg/schemadsl/parser/tests/useexpiration.zed @@ -0,0 +1,6 @@ +use expiration + +definition resource { + relation viewer: user with expiration + relation editor: user with somecaveat and expiration +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/useexpiration.zed.expected b/pkg/schemadsl/parser/tests/useexpiration.zed.expected new file mode 100644 index 0000000000..bc632606f8 --- /dev/null +++ b/pkg/schemadsl/parser/tests/useexpiration.zed.expected @@ -0,0 +1,66 @@ +NodeTypeFile + end-rune = 137 + input-source = use expiration test + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 13 + input-source = use expiration test + start-rune = 0 + use-flag-name = expiration + NodeTypeDefinition + definition-name = resource + end-rune = 137 + input-source = use expiration test + start-rune = 16 + child-node => + NodeTypeRelation + end-rune = 78 + input-source = use expiration test + relation-name = viewer + start-rune = 42 + allowed-types => + NodeTypeTypeReference + end-rune = 78 + input-source = use expiration test + start-rune = 59 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 78 + input-source = use expiration test + start-rune = 59 + type-name = user + trait => + NodeTypeTraitReference + end-rune = 78 + input-source = use expiration test + start-rune = 69 + trait-name = expiration + NodeTypeRelation + end-rune = 135 + input-source = use expiration test + relation-name = editor + start-rune = 84 + allowed-types => + NodeTypeTypeReference + end-rune = 135 + input-source = use expiration test + start-rune = 101 + type-ref-type => + NodeTypeSpecificTypeReference + end-rune = 135 + input-source = use expiration test + start-rune = 101 + type-name = user + caveat => + NodeTypeCaveatReference + caveat-name = somecaveat + end-rune = 120 + input-source = use expiration test + start-rune = 111 + trait => + NodeTypeTraitReference + end-rune = 135 + input-source = use expiration test + start-rune = 126 + trait-name = expiration \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/useexpirationkeyword.zed b/pkg/schemadsl/parser/tests/useexpirationkeyword.zed new file mode 100644 index 0000000000..4271ab396d --- /dev/null +++ b/pkg/schemadsl/parser/tests/useexpirationkeyword.zed @@ -0,0 +1,5 @@ +use expiration + +caveat expiration(someparam int) { + someparam == 42 +} \ No newline at end of file diff --git a/pkg/schemadsl/parser/tests/useexpirationkeyword.zed.expected b/pkg/schemadsl/parser/tests/useexpirationkeyword.zed.expected new file mode 100644 index 0000000000..df7f59d4df --- /dev/null +++ b/pkg/schemadsl/parser/tests/useexpirationkeyword.zed.expected @@ -0,0 +1,27 @@ +NodeTypeFile + end-rune = 21 + input-source = use expiration keyword test + start-rune = 0 + child-node => + NodeTypeUseFlag + end-rune = 13 + input-source = use expiration keyword test + start-rune = 0 + use-flag-name = expiration + NodeTypeCaveatDefinition + end-rune = 21 + input-source = use expiration keyword test + start-rune = 16 + child-node => + NodeTypeError + end-rune = 21 + error-message = Expected identifier, found token TokenTypeKeyword + error-source = expiration + input-source = use expiration keyword test + start-rune = 23 + NodeTypeError + end-rune = 21 + error-message = Unexpected token at root level: TokenTypeKeyword + error-source = expiration + input-source = use expiration keyword test + start-rune = 23 \ No newline at end of file