Files
opencloud/pkg/kql/dictionary.peg
T

292 lines
6.1 KiB
Plaintext

{
package kql
}
////////////////////////////////////////////////////////
// ast
////////////////////////////////////////////////////////
AST <-
n:Nodes _ EOF {
return buildAST(n, c.text, c.pos)
}
EOF <-
!.
////////////////////////////////////////////////////////
// nodes
////////////////////////////////////////////////////////
Nodes <-
(_ Node)+
Node <-
GroupNode /
PropertyRestrictionNodes /
OperatorBooleanNodes /
FreeTextKeywordNodes
////////////////////////////////////////////////////////
// nesting
////////////////////////////////////////////////////////
GroupNode <-
k:Key? (OperatorColonNode / OperatorEqualNode)? "(" v:Nodes ")" {
return buildGroupNode(k, v, c.text, c.pos)
}
////////////////////////////////////////////////////////
// property restrictions
////////////////////////////////////////////////////////
PropertyRestrictionNodes <-
YesNoPropertyRestrictionNode /
DateTimeRestrictionNode /
NumberRestrictionNode /
TextPropertyRestrictionNode
YesNoPropertyRestrictionNode <-
k:Key (OperatorColonNode / OperatorEqualNode) v:("true" / "false") ValueEnd {
return buildBooleanNode(k, v, c.text, c.pos)
}
DateTimeRestrictionNode <-
k:Key o:(
OperatorGreaterOrEqualNode /
OperatorLessOrEqualNode /
OperatorGreaterNode /
OperatorLessNode /
OperatorEqualNode /
OperatorColonNode
) v:DateTimeValue {
return buildDateTimeNode(k, o, v, c.text, c.pos)
} /
k:Key (
OperatorEqualNode /
OperatorColonNode
) v:NaturalLanguageDateTimeValue {
return buildNaturalLanguageDateTimeNodes(k, v, c.text, c.pos)
}
NumberRestrictionNode <-
k:Key o:(
OperatorGreaterOrEqualNode /
OperatorLessOrEqualNode /
OperatorGreaterNode /
OperatorLessNode
) v:NumberValue {
return buildNumberNode(k, o, v, c.text, c.pos)
}
TextPropertyRestrictionNode <-
k:Key OperatorEqualNode v:(String / [^ ()"]+) {
return buildStringNode(k, v, true, c.text, c.pos)
} /
k:Key OperatorColonNode v:(String / [^ ()"]+) {
return buildStringNode(k, v, false, c.text, c.pos)
}
////////////////////////////////////////////////////////
// free text-keywords
////////////////////////////////////////////////////////
FreeTextKeywordNodes <-
PhraseNode /
WordNode
PhraseNode <-
OperatorColonNode? _ v:String _ OperatorColonNode? {
return buildStringNode("", v, false, c.text, c.pos)
}
WordNode <-
OperatorColonNode? _ v:[^ :()"]+ _ OperatorColonNode? {
return buildStringNode("", v, false, 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" /
"last week" /
"last 7 days" /
"this month" /
"last month" /
"last 30 days" /
"this year" /
"last year" {
return c.text, nil
}
////////////////////////////////////////////////////////
// misc
////////////////////////////////////////////////////////
Char <-
[A-Za-z] {
return c.text, nil
}
Key <-
Char+ ("." Char+)* {
return c.text, nil
}
// a double quote inside the quotes is written as two double quotes, nothing
// else is special in there (MS-KQL 2.3.1)
String <-
'"' (`""` / [^"])* '"' {
return unquote(c.text), nil
}
// a date or number only counts if it is the whole value, quoted or not.
// Otherwise the value is text: name:todays_report is not the date today
// followed by _report, and name:"2024-01-01""x""" is not a date followed by x"
DateTimeValue <-
'"' v:(DateTime / FullDate / FullTime) '"' !'"' {
return v, nil
} /
v:(DateTime / FullDate / FullTime) ValueEnd {
return v, nil
}
NaturalLanguageDateTimeValue <-
'"' v:NaturalLanguageDateTime '"' !'"' {
return v, nil
} /
v:NaturalLanguageDateTime ValueEnd {
return v, nil
}
NumberValue <-
'"' v:Number '"' !'"' {
return v, nil
} /
v:Number ValueEnd {
return v, nil
}
// where an unquoted date, number or boolean ends
ValueEnd <-
&[ \t()"] / EOF
Number <-
[0-9]+ ("." [0-9]+)? {
return string(c.text), nil
}
Digit <-
[0-9] {
return c.text, nil
}
_ <-
[ \t]* {
return nil, nil
}