Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CQL language support #3811

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions components.json
Original file line number Diff line number Diff line change
Expand Up @@ -346,6 +346,10 @@
"title": "Content-Security-Policy",
"owner": "ScottHelme"
},
"cql": {
"title": "Contextual Query Language",
"owner": "Querela"
},
"cooklang": {
"title": "Cooklang",
"owner": "ahue"
Expand Down
114 changes: 114 additions & 0 deletions components/prism-cql.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
(function (Prism) {

var boolExp = /\b(?:AND|NOT|OR|PROX)\b/i;
var stringExp = /(?:"(?:\\[\s\S]|(?!")[^\\])*")/;
var wordExp = /[^\s()=<>"\/]+/;
var identifierExp = RegExp('(?:' + stringExp.source + '|' + wordExp.source + ')');

var comparitorNamedExp = identifierExp;
var comparitorSymbolExp = /(?:<>|[=><]=?)/;
var comparitorExp = RegExp('(?:' + comparitorSymbolExp.source + '|' + comparitorNamedExp.source + ')');

var modifierExp = RegExp('/\\s*' + identifierExp.source + '(?:\\s*' + comparitorSymbolExp.source + '\\s*' + identifierExp.source + ')?');
var modifierListExp = RegExp('(?:\\s*' + modifierExp.source + ')*');

var relationExp = RegExp(comparitorExp.source + modifierListExp.source);

var modifier = {
pattern: modifierExp,
inside: {
'modifier': {
pattern: RegExp('(/\\s*)' + identifierExp.source),
lookbehind: true,
alias: 'property',
},
'value': {
pattern: RegExp(identifierExp.source + '$'),
alias: 'string',
},
'comparitor': {
pattern: comparitorSymbolExp,
alias: 'operator',
},
'punctuation': /\//,
}
};

var searchClause = {
pattern: RegExp('(?:' + identifierExp.source + '\\s*' + relationExp.source + '\\s*)?' + identifierExp.source),
inside: {
// required last part, search term
'term': {
pattern: RegExp(identifierExp.source + '(?!.)'),
alias: 'string',
},
// optional index with relation
'index': {
pattern: RegExp('^' + identifierExp.source),
alias: 'property',
},
'relation-modifier': modifier,
'relation': {
pattern: comparitorExp,
alias: 'operator',
},
},
};

var boolClause = {
pattern: RegExp(boolExp.source + modifierListExp.source, 'i'),
inside: {
'boolean': {
pattern: boolExp,
alias: 'operator'
},
'boolean-modifier': modifier,
},
};

var prefix = {
pattern: RegExp('(^\\s*)>\\s*(?:' + identifierExp.source + '\\s*=\\s*)?' + identifierExp.source),
lookbehind: true,
inside: {
'uri': {
pattern: RegExp(identifierExp.source + '$'),
alias: 'string',
},
'prefix': {
pattern: identifierExp,
alias: 'property',
},
'punctuation': /[>=]/,
}
};

var sortby = {
// XXX: too complex exponential/polynomial backtracking possible ...
//pattern: RegExp('sortby(?:\\s*' + identifierExp.source + modifierListExp.source + ')+\\s*$', 'i'),
pattern: RegExp('(^|\\s)sortby\\b(?:' + identifierExp.source + '\\b|[\\s=></])+$', 'i'),
lookbehind: true,
inside: {
'keyword': /sortby/i,
'sortby-index-modifier': modifier,
'index': {
pattern: identifierExp,
alias: 'property',
}
}
};

Prism.languages['cql'] = {
// prefix / suffix
'prefix': prefix,
'sortby': sortby,

// conjuctions
'bool-group': boolClause,
// search clause triples
'search-clause': searchClause,

// grouping
'punctuation': /[()]/,
};

}(Prism));
60 changes: 60 additions & 0 deletions examples/prism-cql.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<h2>CQL Query</h2>

<pre><code>dc.title any fish</code></pre>
<pre><code>dc.title any fish or dc.creator any sanderson</code></pre>
<pre><code>dc.title any fish sortBy dc.date/sort.ascending</code></pre>
<pre><code>> dc = "info:srw/context-sets/1/dc-v1.1" dc.title any fish</code></pre>

<h2>Search Clause</h2>

<pre><code>dc.title any fish</code></pre>
<pre><code>fish</code></pre>
<pre><code>cql.serverChoice = fish</code></pre>

<h2>Search Term</h2>

<pre><code>"fish"</code></pre>
<pre><code>fish</code></pre>
<pre><code>"squirrels fish"</code></pre>
<pre><code>""</code></pre>

<h2>Index Name</h2>

<pre><code>title any fish</code></pre>
<pre><code>dc.title any fish</code></pre>

<h2>Relation</h2>

<pre><code>dc.title any fish</code></pre>
<pre><code>dc.title cql.any fish</code></pre>

<h2>Relation Modifiers</h2>

<pre><code>dc.title any/relevant fish</code></pre>
<pre><code>dc.title any/ relevant /cql.string fish</code></pre>
<pre><code>dc.title any/rel.algorithm=cori fish</code></pre>

<h2>Boolean Operators</h2>

<pre><code>dc.title any fish or dc.creator any sanderson</code></pre>
<pre><code>dc.title any fish or (dc.creator any sanderson and dc.identifier = "id:1234567")</code></pre>

<h2>Boolean Modifiers</h2>

<pre><code>dc.title any fish or/rel.combine=sum dc.creator any sanderson</code></pre>
<pre><code>dc.title any fish prox/unit=word/distance&gt;3 dc.title any squirrel</code></pre>

<h2>Sorting</h2>

<pre><code>"cat" sortBy dc.title</code></pre>
<pre><code>"dinosaur" sortBy dc.date/sort.descending dc.title/sort.ascending</code></pre>

<h2>Prefix Assignment</h2>

<pre><code>&gt; dc = "http://deepcustard.org/" dc.custardDepth &gt; 10</code></pre>
<pre><code>&gt; "http://deepcustard.org/" custardDepth &gt; 10</code></pre>

<h2>Case Insensitive</h2>

<pre><code>dC.tiTlE any fish</code></pre>
<pre><code>dc.TitlE Any/rEl.algOriThm=cori fish soRtbY Dc.TitlE </code></pre>
57 changes: 57 additions & 0 deletions tests/languages/cql/boolean_modifiers.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
dc.title any fish or/rel.combine=sum dc.creator any sanderson

dc.title any fish prox/unit=word/distance>3 dc.title any squirrel

----------------------------------------------------

[
["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]],
["bool-group", [
["boolean", "or"],
["boolean-modifier", [
["punctuation", "/"],
["modifier", "rel.combine"],
["comparitor", "="],
["value", "sum"]
]]
]],
["search-clause", [
["index", "dc.creator"],
["relation", "any"],
["term", "sanderson"]
]],

["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]],
["bool-group", [
["boolean", "prox"],
["boolean-modifier", [
["punctuation", "/"],
["modifier", "unit"],
["comparitor", "="],
["value", "word"]
]],
["boolean-modifier", [
["punctuation", "/"],
["modifier", "distance"],
["comparitor", ">"],
["value", "3"]
]]
]],
["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "squirrel"]
]]
]

----------------------------------------------------

Boolean modifiers.
49 changes: 49 additions & 0 deletions tests/languages/cql/boolean_operators.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
dc.title any fish or dc.creator any sanderson

dc.title any fish or (dc.creator any sanderson and dc.identifier = "id:1234567")

----------------------------------------------------

[
["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]],
["bool-group", [
["boolean", "or"]
]],
["search-clause", [
["index", "dc.creator"],
["relation", "any"],
["term", "sanderson"]
]],

["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]],
["bool-group", [
["boolean", "or"]
]],
["punctuation", "("],
["search-clause", [
["index", "dc.creator"],
["relation", "any"],
["term", "sanderson"]
]],
["bool-group", [
["boolean", "and"]
]],
["search-clause", [
["index", "dc.identifier"],
["relation", "="],
["term", "\"id:1234567\""]
]],
["punctuation", ")"]
]

----------------------------------------------------

Boolean operators.
33 changes: 33 additions & 0 deletions tests/languages/cql/case_insensitive.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
dC.tiTlE any fish

dc.TitlE Any/rEl.algOriThm=cori fish soRtbY Dc.TitlE

----------------------------------------------------

[
["search-clause", [
["index", "dC.tiTlE"],
["relation", "any"],
["term", "fish"]
]],

["search-clause", [
["index", "dc.TitlE"],
["relation", "Any"],
["relation-modifier", [
["punctuation", "/"],
["modifier", "rEl.algOriThm"],
["comparitor", "="],
["value", "cori"]
]],
["term", "fish"]
]],
["sortby", [
["keyword", "soRtbY"],
["index", "Dc.TitlE"]
]]
]

----------------------------------------------------

Case Insenstivity.
15 changes: 15 additions & 0 deletions tests/languages/cql/clause_feature_1.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
dc.title any fish

----------------------------------------------------

[
["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]]
]

----------------------------------------------------

Search clauses.
13 changes: 13 additions & 0 deletions tests/languages/cql/clause_feature_2.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
fish

----------------------------------------------------

[
["search-clause", [
["term", "fish"]
]]
]

----------------------------------------------------

Search clauses.
15 changes: 15 additions & 0 deletions tests/languages/cql/clause_feature_3.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
cql.serverChoice = fish

----------------------------------------------------

[
["search-clause", [
["index", "cql.serverChoice"],
["relation", "="],
["term", "fish"]
]]
]

----------------------------------------------------

Search clauses.
23 changes: 23 additions & 0 deletions tests/languages/cql/index_feature.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
title any fish

dc.title any fish

----------------------------------------------------

[
["search-clause", [
["index", "title"],
["relation", "any"],
["term", "fish"]
]],

["search-clause", [
["index", "dc.title"],
["relation", "any"],
["term", "fish"]
]]
]

----------------------------------------------------

Index names.
Loading
Loading