Skip to content

Commit

Permalink
feat: add nil token to allow nil permission expressions
Browse files Browse the repository at this point in the history
TODO: add more tests to make sure this doesn't break anything
  • Loading branch information
theoriginalstove committed Sep 25, 2024
1 parent 1f1063c commit d995ace
Show file tree
Hide file tree
Showing 5 changed files with 117 additions and 2 deletions.
6 changes: 5 additions & 1 deletion pkg/dsl/lexer/lexer.go
Original file line number Diff line number Diff line change
Expand Up @@ -147,9 +147,13 @@ func (l *Lexer) NextToken() (tok token.Token) {
if isLetter(l.ch) {
tok.PositionInfo = positionInfo(l.linePosition, l.columnPosition)
tok.Literal = l.lexIdent()
if tok.Literal == "true" || tok.Literal == "false" {
switch tok.Literal {
case "true", "false":
tok.Type = token.BOOLEAN
return
case "nil":
tok.Type = token.NIL
return
}
tok.Type = token.LookupKeywords(tok.Literal)
return
Expand Down
92 changes: 92 additions & 0 deletions pkg/dsl/lexer/lexer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -980,5 +980,97 @@ rule check_ip_address(ip_addresses string[]) {
Expect(index + lexeme.Literal).Should(Equal(index + tt.expectedLiteral))
}
})

It("Case 10", func() {
str := `
entity user {}
entity organization {
relation admin @user
relation member @user
action create_repository = nil
action delete = nil
}
`

tests := []struct {
expectedType token.Type
expectedLiteral string
}{
{token.NEWLINE, "\n"},
{token.ENTITY, "entity"},
{token.SPACE, " "},
{token.IDENT, "user"},
{token.SPACE, " "},
{token.LCB, "{"},
{token.RCB, "}"},
{token.NEWLINE, "\n"},
{token.NEWLINE, "\n"},
// --
{token.ENTITY, "entity"},
{token.SPACE, " "},
{token.IDENT, "organization"},
{token.SPACE, " "},
{token.LCB, "{"},
{token.NEWLINE, "\n"},
// --
{token.TAB, "\t"},
{token.RELATION, "relation"},
{token.SPACE, " "},
{token.IDENT, "admin"},
{token.SPACE, " "},
{token.SIGN, "@"},
{token.IDENT, "user"},
{token.NEWLINE, "\n"},
// --
{token.SPACE, " "},
{token.SPACE, " "},
{token.SPACE, " "},
{token.SPACE, " "},
{token.RELATION, "relation"},
{token.SPACE, " "},
{token.IDENT, "member"},
{token.SPACE, " "},
{token.SIGN, "@"},
{token.IDENT, "user"},
{token.NEWLINE, "\n"},
{token.NEWLINE, "\n"},
// --
{token.TAB, "\t"},
{token.PERMISSION, "action"},
{token.SPACE, " "},
{token.IDENT, "create_repository"},
{token.SPACE, " "},
{token.ASSIGN, "="},
{token.SPACE, " "},
{token.NIL, "nil"},
{token.NEWLINE, "\n"},
// --
{token.TAB, "\t"},
{token.PERMISSION, "action"},
{token.SPACE, " "},
{token.IDENT, "delete"},
{token.SPACE, " "},
{token.ASSIGN, "="},
{token.SPACE, " "},
{token.NIL, "nil"},
{token.NEWLINE, "\n"},
{token.RCB, "}"},
{token.NEWLINE, "\n"},
{token.NEWLINE, "\n"},
// --
}

l := NewLexer(str)

for i, tt := range tests {
lexeme := l.NextToken()
index := strconv.Itoa(i) + ": "
Expect(index + lexeme.Type.String()).Should(Equal(index + tt.expectedType.String()))
Expect(index + lexeme.Literal).Should(Equal(index + tt.expectedLiteral))
}
})
})
})
3 changes: 2 additions & 1 deletion pkg/dsl/parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,10 @@ func NewParser(str string) (p *Parser) {
references: ast.NewReferences(), // initialize an empty map for relational references
}

// register prefix parsing functions for token types IDENT and NOT
// register prefix parsing functions for token types IDENT and NIL
p.prefixParseFns = make(map[token.Type]prefixParseFn) // initialize an empty map for prefix parsing functions
p.registerPrefix(token.IDENT, p.parseIdentifierOrCall) // associate the parseIdentifier function with the IDENT token type
p.registerPrefix(token.NIL, p.parseIdentifierOrCall)

// register infix parsing functions for token types AND, OR, NOT
p.infixParseFunc = make(map[token.Type]infixParseFn) // initialize an empty map for infix parsing functions
Expand Down
17 changes: 17 additions & 0 deletions pkg/dsl/parser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1041,5 +1041,22 @@ rule confidentiality_level_low(confidentiality_level double) {
// Ensure the error message contains the expected string
Expect(err.Error()).Should(ContainSubstring("7:15:expected token to be RELATION, PERMISSION, ATTRIBUTE, got OR instead"))
})

It("Case 30 - Nil Permission", func() {
pr := NewParser(`
entity account {
relation owner @user
relation admin @user
action check_balance = nil
permission withdraw = nil
}
`)

_, err := pr.Parse()
// Ensure an error is not returned
Expect(err).ShouldNot(HaveOccurred())
})
})
})
1 change: 1 addition & 0 deletions pkg/dsl/token/token.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ const (
INTEGER = "INTEGER"
DOUBLE = "DOUBLE"
BOOLEAN = "BOOLEAN"
NIL = "NIL"

/*
Symbols
Expand Down

0 comments on commit d995ace

Please sign in to comment.