Skip to content

Instantly share code, notes, and snippets.

@shripadk
Created August 23, 2022 21:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save shripadk/49179f8ab6ed97d82288a38cc8114989 to your computer and use it in GitHub Desktop.
Save shripadk/49179f8ab6ed97d82288a38cc8114989 to your computer and use it in GitHub Desktop.
/**
MIT License
Copyright 2022 Shripad Krishna <i@shripadk.me>
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions
of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
{
moduleInclude: `
function transposeArray(array, innerKey, innerValue, relation) {
const obj = {}
for (let i = 0; i < array.length; i++) {
const hasRelation = array[i][relation] != null
const key = array[i][innerKey]
const value = array[i][innerValue]
if (hasRelation) {
obj[value] = obj[value] || []
obj[value].push({ on: array[i][relation], if: key })
} else {
obj[key] = obj[key] || []
obj[key].push(value)
}
}
return obj
}
`,
lex: {
startConditions: {
COMMENT: 1,
QUERY: 1,
},
rules: [
[`\\s+`, `/* skip whitespace */`],
[`\\#+`, `this.pushState('COMMENT')`],
[[`COMMENT`], `\\n`, `this.popState()`],
[[`COMMENT`], `.+`, `/* skip comment */`],
[`.+\\(`, `this.pushState('QUERY'); yytext = yytext.slice(0, -1); return 'QUERY_NAME'`],
[[`QUERY`], `.+\\)`, `yytext = '(' + yytext; return 'QUERY_ARGS'`],
[[`QUERY`], `\\;`, `this.popState()`],
[[`QUERY`], `[^\\;]*`, `return 'QUERY_BODY'`],
[`resource`, `return 'RESOURCE_KEYWORD'`],
[`actor`, `return 'ACTOR_KEYWORD'`],
[`permissions`, `return 'PERMISSIONS_KEYWORD'`],
[`roles`, `return 'ROLES_KEYWORD'`],
[`relations`, `return 'RELATIONS_KEYWORD'`],
[`if`, `return 'IF'`],
[`on`, `return 'ON'`],
[`\\d+`, `return 'NUMBER'`],
[`\\w+`, `return 'STRING'`],
[`\\{+`, `return 'CURLY_BRACE_OPEN'`],
[`\\}+`, `return 'CURLY_BRACE_CLOSE'`],
[`\\(+`, `return 'BRACE_OPEN'`],
[`\\)+`, `return 'BRACE_CLOSE'`],
[`\\=+`, `return 'EQUALS'`],
[`\\[+`, `return 'SQUARE_BRACE_OPEN'`],
[`\\]+`, `return 'SQUARE_BRACE_CLOSE'`],
[`\\"+`, `return 'DOUBLE_QUOTE'`],
[`\\,+`, `return 'COMMA'`],
[`\\:+`, `return 'COLON'`],
[`\\;+`, `return 'SEMICOLON'`],
],
},
start: 'PROGRAM',
operators: [
[`left`, `RESOURCE_KEYWORD`],
[`left`, `ACTOR_KEYWORD`],
[`left`, `DOUBLE_QUOTE`],
[`left`, `STRING`],
[`left`, `QUERY_NAME`],
],
bnf: {
PROGRAM: [
[`LIST`]
],
LIST: [
[`LIST RESOURCE_LIST`, `$$ = [$1, $2].flat()`],
[`LIST ACTOR_LIST`, `$$ = [$1, $2].flat()`],
[`LIST QUERY_LIST`, `$$ = [$1, $2].flat()`],
[`RESOURCE_LIST`, `$$ = $1`],
[`ACTOR_LIST`, `$$ = $1`],
[`QUERY_LIST`, `$$ = $1`],
],
RESOURCE_LIST: [
[`RESOURCE_LIST RESOURCE`, `$$ = [$1, $2].flat()`],
[`RESOURCE`, `$$ = $1`],
],
RESOURCE: [
[`RESOURCE_KEYWORD RESOURCE_NAME RESOURCE_BLOCK`, `$$ = { type: 'RESOURCE', name: $2, blocks: $3 }`],
],
RESOURCE_NAME: [
[`STRING`],
],
RESOURCE_BLOCK: [
[`CURLY_BRACE_OPEN RESOURCE_BLOCK_CONTENT CURLY_BRACE_CLOSE`, `$$ = $2`],
[`CURLY_BRACE_OPEN CURLY_BRACE_CLOSE`],
],
RESOURCE_BLOCK_CONTENT: [
[`RESOURCE_BLOCK_CONTENT RESOURCE_BLOCK_CONTENT_ITEM`, `$$ = [$1, $2].flat()`],
[`RESOURCE_BLOCK_CONTENT_ITEM`, `$$ = $1`],
],
RESOURCE_BLOCK_CONTENT_ITEM: [
[`RESOURCE_BLOCK_PERMISSIONS`, `$$ = { type: 'PERMISSIONS', permissions: $1 instanceof Array ? $1 : [$1] }`],
[`RESOURCE_BLOCK_ROLES`, `$$ = { type: 'ROLES', roles: $1 instanceof Array ? $1 : [$1]}`],
[`RESOURCE_BLOCK_RELATIONS`, `$$ = { type: 'RELATIONS', relations: $1 instanceof Array ? $1 : [$1] }`],
[`RESOURCE_BLOCK_GRANTS`, `$$ = { type: 'GRANTS', grants: transposeArray($1, 'entity', 'grant', 'relation') }`],
],
RESOURCE_BLOCK_PERMISSIONS: [
[`PERMISSIONS_KEYWORD EQUALS SQUARE_BRACE_OPEN RESOURCE_BLOCK_PERMISSION_LIST SQUARE_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
],
RESOURCE_BLOCK_PERMISSION_LIST: [
[`RESOURCE_BLOCK_PERMISSION_LIST COMMA RESOURCE_BLOCK_PERMISSION_LIST_ITEM`, `$$ = [$1, $3].flat()`],
[`RESOURCE_BLOCK_PERMISSION_LIST_ITEM`, `$$ = $1`],
],
RESOURCE_BLOCK_PERMISSION_LIST_ITEM: [
[`DOUBLE_QUOTE RESOURCE_BLOCK_PERMISSION DOUBLE_QUOTE`, `$$ = $2`],
],
RESOURCE_BLOCK_PERMISSION: [
[`STRING`],
],
RESOURCE_BLOCK_ROLES: [
[`ROLES_KEYWORD EQUALS SQUARE_BRACE_OPEN RESOURCE_BLOCK_ROLE_LIST SQUARE_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
],
RESOURCE_BLOCK_ROLE_LIST: [
[`RESOURCE_BLOCK_ROLE_LIST COMMA RESOURCE_BLOCK_ROLE_LIST_ITEM`, `$$ = [$1, $3].flat()`],
[`RESOURCE_BLOCK_ROLE_LIST_ITEM`, `$$ = $1`],
],
RESOURCE_BLOCK_ROLE_LIST_ITEM: [
[`DOUBLE_QUOTE RESOURCE_BLOCK_ROLE DOUBLE_QUOTE`, `$$ = $2`],
],
RESOURCE_BLOCK_ROLE: [
[`STRING`],
],
RESOURCE_BLOCK_RELATIONS: [
[`RELATIONS_KEYWORD EQUALS CURLY_BRACE_OPEN RESOURCE_BLOCK_RELATION_LIST COMMA CURLY_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
[`RELATIONS_KEYWORD EQUALS CURLY_BRACE_OPEN RESOURCE_BLOCK_RELATION_LIST CURLY_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
],
RESOURCE_BLOCK_RELATION_LIST: [
[`RESOURCE_BLOCK_RELATION_LIST COMMA RESOURCE_BLOCK_RELATION_LIST_ITEM`, `$$ = [$1, $3].flat()`],
[`RESOURCE_BLOCK_RELATION_LIST_ITEM`, `$$ = $1`],
],
RESOURCE_BLOCK_RELATION_LIST_ITEM: [
[`STRING COLON STRING`, `$$ = { relation: $1, entity: $3 }`],
],
RESOURCE_BLOCK_GRANTS: [
[`RESOURCE_BLOCK_GRANTS RESOURCE_BLOCK_GRANT`, `$$ = [$1, $2].flat()`],
[`RESOURCE_BLOCK_GRANT`, `$$ = $1`],
],
RESOURCE_BLOCK_GRANT: [
[`DOUBLE_QUOTE STRING DOUBLE_QUOTE IF DOUBLE_QUOTE STRING DOUBLE_QUOTE ON DOUBLE_QUOTE STRING DOUBLE_QUOTE SEMICOLON`, `$$ = [{ entity: $6, grant: $2, relation: $10 }]`],
[`DOUBLE_QUOTE STRING DOUBLE_QUOTE IF DOUBLE_QUOTE STRING DOUBLE_QUOTE SEMICOLON`, `$$ = [{ entity: $6, grant: $2 }]`],
],
ACTOR_LIST: [
[`ACTOR_LIST ACTOR`, `$$ = [$1, $2].flat()`],
[`ACTOR`, `$$ = $1`],
],
ACTOR: [
[`ACTOR_KEYWORD ACTOR_NAME ACTOR_BLOCK`, `$$ = { type: 'ACTOR', name: $2, block: $3 }`],
],
ACTOR_NAME: [
[`STRING`],
],
ACTOR_BLOCK: [
[`CURLY_BRACE_OPEN ACTOR_BLOCK_CONTENT CURLY_BRACE_CLOSE`, `$$ = $2`],
[`CURLY_BRACE_OPEN CURLY_BRACE_CLOSE`],
],
ACTOR_BLOCK_CONTENT: [
[`ACTOR_BLOCK_CONTENT ACTOR_BLOCK_CONTENT_ITEM`, `$$ = [$1, $2].flat()`],
[`ACTOR_BLOCK_CONTENT_ITEM`, `$$ = $1`],
],
ACTOR_BLOCK_CONTENT_ITEM: [
[`ACTOR_BLOCK_PERMISSIONS`, `$$ = { type: 'PERMISSIONS', permissions: $1 }`],
[`ACTOR_BLOCK_ROLES`, `$$ = { type: 'ROLES', roles: $1 }`],
],
ACTOR_BLOCK_PERMISSIONS: [
[`PERMISSIONS_KEYWORD EQUALS SQUARE_BRACE_OPEN ACTOR_BLOCK_PERMISSION_LIST SQUARE_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
],
ACTOR_BLOCK_PERMISSION_LIST: [
[`ACTOR_BLOCK_PERMISSION_LIST COMMA ACTOR_BLOCK_PERMISSION_LIST_ITEM`, `$$ = [$1, $3].flat()`],
[`ACTOR_BLOCK_PERMISSION_LIST_ITEM`, `$$ = $1`],
],
ACTOR_BLOCK_PERMISSION_LIST_ITEM: [
[`DOUBLE_QUOTE ACTOR_BLOCK_PERMISSION DOUBLE_QUOTE`, `$$ = $2`],
],
ACTOR_BLOCK_PERMISSION: [
[`STRING`],
],
ACTOR_BLOCK_ROLES: [
[`ROLES_KEYWORD EQUALS SQUARE_BRACE_OPEN ACTOR_BLOCK_ROLE_LIST SQUARE_BRACE_CLOSE SEMICOLON`, `$$ = $4`],
],
ACTOR_BLOCK_ROLE_LIST: [
[`ACTOR_BLOCK_ROLE_LIST COMMA ACTOR_BLOCK_ROLE_LIST_ITEM`, `$$ = [$1, $3].flat()`],
[`ACTOR_BLOCK_ROLE_LIST_ITEM`, `$$ = $1`],
],
ACTOR_BLOCK_ROLE_LIST_ITEM: [
[`DOUBLE_QUOTE ACTOR_BLOCK_ROLE DOUBLE_QUOTE`, `$$ = $2`],
],
ACTOR_BLOCK_ROLE: [
[`STRING`],
],
QUERY_LIST: [
[`QUERY_LIST QUERY_LIST_ITEM`, `$$ = [$1, $2].flat()`],
[`QUERY_LIST_ITEM`, `$$ = $1`],
],
QUERY_LIST_ITEM: [
[`QUERY_NAME QUERY_ARGS QUERY_BODY`, `$$ = { type: 'QUERY', name: $1, args: $2, body: $3 }`],
],
},
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment