Files
opencloud/services/search/pkg/query/kql/dictionary.peg
Florian Schade 0f2b2b9a94 [full-ci] enhancement: add support for natural language kql date ranges (#7263)
* enhancement: add more kql spec tests and simplify ast normalization

* enhancement: kql parser error if query starts with AND

* enhancement: add kql docs and support for date and time only dateTimeRestriction queries

* enhancement: add the ability to decide how kql nodes get connected

connecting nodes (with edges) seem straight forward when not using group, the default connection for nodes with the same node is always OR. THis only applies for first level nodes, for grouped nodes it is defined differently. The KQL docs are saying, nodes inside a grouped node, with the same key are connected by a AND edge.

* enhancement: explicit error handling for falsy group nodes and queries with leading binary operator

* enhancement: use optimized grammar for kql parser and toolify pigeon

* enhancement: simplify error handling

* fix: kql implicit 'AND' and 'OR' follows the ms html spec instead of the pdf spec

* enhancement: add support for natural language kql date queries

* enhancement: structure kql parser tests into logical clusters

* fix: time-range error naming
2023-09-15 11:31:41 +02:00

233 lines
4.7 KiB
Plaintext

{
package kql
}
////////////////////////////////////////////////////////
// ast
////////////////////////////////////////////////////////
AST <-
n:Nodes {
return buildAST(n, c.text, c.pos)
}
////////////////////////////////////////////////////////
// nodes
////////////////////////////////////////////////////////
Nodes <-
(_ Node)+
Node <-
GroupNode /
PropertyRestrictionNodes /
OperatorBooleanNodes /
FreeTextKeywordNodes
////////////////////////////////////////////////////////
// nesting
////////////////////////////////////////////////////////
GroupNode <-
k:(Char+)? (OperatorColonNode / OperatorEqualNode)? "(" v:Nodes ")" {
return buildGroupNode(k, v, c.text, c.pos)
}
////////////////////////////////////////////////////////
// property restrictions
////////////////////////////////////////////////////////
PropertyRestrictionNodes <-
YesNoPropertyRestrictionNode /
DateTimeRestrictionNode /
TextPropertyRestrictionNode
YesNoPropertyRestrictionNode <-
k:Char+ (OperatorColonNode / OperatorEqualNode) v:("true" / "false"){
return buildBooleanNode(k, v, c.text, c.pos)
}
DateTimeRestrictionNode <-
k:Char+ o:(
OperatorGreaterOrEqualNode /
OperatorLessOrEqualNode /
OperatorGreaterNode /
OperatorLessNode /
OperatorEqualNode /
OperatorColonNode
) '"'? v:(
DateTime /
FullDate /
FullTime
) '"'? {
return buildDateTimeNode(k, o, v, c.text, c.pos)
} /
k:Char+ (
OperatorEqualNode /
OperatorColonNode
) '"'? v:NaturalLanguageDateTime '"'? {
return buildNaturalLanguageDateTimeNodes(k, v, c.text, c.pos)
}
TextPropertyRestrictionNode <-
k:Char+ (OperatorColonNode / OperatorEqualNode) v:(String / [^ ()]+){
return buildStringNode(k, v, c.text, c.pos)
}
////////////////////////////////////////////////////////
// free text-keywords
////////////////////////////////////////////////////////
FreeTextKeywordNodes <-
PhraseNode /
WordNode
PhraseNode <-
OperatorColonNode? _ v:String _ OperatorColonNode? {
return buildStringNode("", v, c.text, c.pos)
}
WordNode <-
OperatorColonNode? _ v:[^ :()]+ _ OperatorColonNode? {
return buildStringNode("", v, c.text, c.pos)
}
////////////////////////////////////////////////////////
// operators
////////////////////////////////////////////////////////
OperatorBooleanNodes <-
OperatorBooleanAndNode /
OperatorBooleanNotNode /
OperatorBooleanOrNode
OperatorBooleanAndNode <-
("AND" / "+") {
return buildOperatorNode(c.text, c.pos)
}
OperatorBooleanNotNode <-
("NOT" / "-") {
return buildOperatorNode(c.text, c.pos)
}
OperatorBooleanOrNode <-
("OR") {
return buildOperatorNode(c.text, c.pos)
}
OperatorColonNode <-
":" {
return buildOperatorNode(c.text, c.pos)
}
OperatorEqualNode <-
"=" {
return buildOperatorNode(c.text, c.pos)
}
OperatorLessNode <-
"<" {
return buildOperatorNode(c.text, c.pos)
}
OperatorLessOrEqualNode <-
"<=" {
return buildOperatorNode(c.text, c.pos)
}
OperatorGreaterNode <-
">" {
return buildOperatorNode(c.text, c.pos)
}
OperatorGreaterOrEqualNode <-
">=" {
return buildOperatorNode(c.text, c.pos)
}
////////////////////////////////////////////////////////
// time
////////////////////////////////////////////////////////
TimeYear <-
Digit Digit Digit Digit {
return c.text, nil
}
TimeMonth <-
Digit Digit {
return c.text, nil
}
TimeDay <-
Digit Digit {
return c.text, nil
}
TimeHour <-
Digit Digit {
return c.text, nil
}
TimeMinute <-
Digit Digit {
return c.text, nil
}
TimeSecond <-
Digit Digit {
return c.text, nil
}
FullDate <-
TimeYear "-" TimeMonth "-" TimeDay {
return c.text, nil
}
FullTime <-
TimeHour ":" TimeMinute ":" TimeSecond ("." Digit+)? ("Z" / ("+" / "-") TimeHour ":" TimeMinute) {
return c.text, nil
}
DateTime <-
FullDate "T" FullTime {
return c.text, nil
}
NaturalLanguageDateTime <-
"today" /
"yesterday" /
"this week" /
"this month" /
"last month" /
"this year" /
"last year" {
return c.text, nil
}
////////////////////////////////////////////////////////
// misc
////////////////////////////////////////////////////////
Char <-
[A-Za-z] {
return c.text, nil
}
String <-
'"' v:[^"]* '"' {
return v, nil
}
Digit <-
[0-9] {
return c.text, nil
}
_ <-
[ \t]* {
return nil, nil
}