diff --git a/editions/tw5.com/tiddlers/nodejs/TiddlerFilter Formal Grammar.tid b/editions/tw5.com/tiddlers/nodejs/TiddlerFilter Formal Grammar.tid index 7f352f8ff..dd8eb1c5a 100644 --- a/editions/tw5.com/tiddlers/nodejs/TiddlerFilter Formal Grammar.tid +++ b/editions/tw5.com/tiddlers/nodejs/TiddlerFilter Formal Grammar.tid @@ -4,68 +4,61 @@ tags: Filters title: Filter Formal Grammar type: text/vnd.tiddlywiki -[[Filters]] follow a formal grammar that is presented here for users who are familiar with the notation. It isn't necessary to understand this grammar in order to write your own filter expressions. +[[Filter expressions|Filters]] follow a grammar that is presented here for those who find formal syntax descriptions helpful. However, you can write your own filter expressions without needing to understand this tiddler. -''<filter-string>'' ::= ''<opt-whitespaces>'' ''<filter-operand>'' | ''<opt-whitespaces>'' ''<filter-operand>'' ''<filter-string>'' +* [//x//] denotes an optional //x// +* (//x//)... denotes 1 or more instances of //x// +* Literal characters are `monospaced` +* Bullets indicate alternative possibilities -Whitespace is matched with javascript "\s+", which matches space, tab, carriage return, new line, vertical tab, and form feed. +;filter +* ( [//whitespace//] [`+`|`-`] //run// )... -''<opt-whitespaces>'' ::= ''<opt-whitespace>'' | ''<opt-whitespace>'' ''<opt-whitespaces>'' +;run +* `[` (//operation//)... `]` +* `"` //text// `"` +** The text can contain anything but `"` +* `'` //text// `'` +** The text can contain anything but `'` +* //text// +** The text can contain anything but whitespace and `[` and `]` +** These last three alternatives are short for `[title[text]]` -''<opt-whitespace>'' ::= " " | "\t" | "0xD" | "0xA" | "0xB" | "0xC" +;operation +* [`!`] //operator// //operand// -''<filter-operand>'' ::= ''<opt-operation-prefix>'' ''<string-or-operator-list>'' +;operator +* [//keyword//] [//suffix//] +** Terminated by the `[` or `{` or `<` of the operand +** Keywords are drawn from a reserved list +** A suffix on its own implies the keyword `field` +** An entirely omitted operator defaults to `title` -''<opt-operation-prefix>'' ::= "+" | "-" | "" +;suffix +* `:` [//text//] -''<string-or-operator-list>'' ::= ''<operation>'' | "\"" ''<string>'' "\"" | "'" ''<string>'' "'" | ''<string>'' +;operand +* `[` //text// `]` +** literal -- the text can contain anything but `]` +* `{` //text// `}` +** text reference -- the text can contain anything but `}` +* `<` //text// `>` +** variable -- the text can contain anything but `>` -''<operation>'' ::= "[" ''<operator-list>'' "]" +;whitespace +* One or more spaces, tabs or linefeeds, i.e. a match for the JavaScript regular expression `\s+` -''<operator-list>'' ::= ''<operator>'' | ''<operator>'' ''<operator-list>'' +!Evaluation -''<operator>'' ::= ''<opt-operator-prefix>''''<operator>''''<operand>'' +Each operation returns a set of tiddlers, in the form of a TitleList. -''<opt-operator-prefix>'' ::= "!" | "" +A run evaluates each of the operations it contains, and returns the intersection of the resulting sets. -''<operator>'' ::= ''<operator-name>'' | ''<operator-name>'' ":" ''<opt-operator-suffix>'' +A sequence of runs is evaluated from left to right, as follows: -''<operator-name>'' ::= "" | "is" | "has" | "each" | "field" ... +|!Sequence |!Interpretation | +|run1 run2 |union of the sets, i.e. the tiddlers in //either// run1 //or// run2 | +|run1 -run2 |difference of the sets, i.e. run1 but excluding any tiddlers in run2 | +|run1 +run2 |run2 takes run1 as its input | -''<opt-operator-suffix>'' ::= ''<string>'' | "" - -''<operand>'' ::= "[" ''<search-string>'' "]" | "{" ''<indirect-search-string>'' "}" | "<" ''<variable-name-string>'' ">" - -''<string>'' ::= ''<string-type-1>'' | ''<string-type-2>'' | ... - -At the end of parsing you end up with some or all of: - -* ''<opt-operation-prefix>'' -* ''<opt-operator-prefix>'' -* ''<operator-name>'' -* ''<opt-operator-suffix>'', and -* ''<operand>'' - -These are used differently by the different operators. For example, the field filter operator supports: - -* ''<opt-operator-prefix>'' to negate the result -* ''<regex>'' or ''<string>'' operand (note that this must be explicitly supported by each filter operator) -* ''<opt-operator-suffix>'' to specify a fieldname against which to filter - -NOTES: - -* The ''<string>'' is a terminal that generally supports single- or double- quoted strings which match, respectively, strings of non-single and non-double quotes. Unquoted strings include the extra exclusion of whitespace and square bracket characters. - -* In the case where the ''<string-or-operator-list>'' is NOT an ''<operation>'' it is treated as the operand passed to the default operator (see next bullet). It is not parsed as a full ''<operation>''. - -* If ''<operator-name>'' is the empty string then it will be set to "title" (i.e. the title filter operator is the default operator) - -* Results are collected and each operation is applied in turn. The ''<opt-operation-prefix>'' can be used to specify how the corresponding operation is used. Suppose T is the set of all tiddlers, R0 is the current set of results, and Fx is the xth operation. Then: - -** No prefix (""): R0 = R0 U Fx(T) (set union) -** "-": R0 = R0 - Fx(T) (set difference) -** "+": R0 = Fx(R0) - -Note that ''<filter-operand>''s are not commutative! - -* The parser was simplified by treating regex "/" as a "bracket" of sorts, meaning there could only be a start and end bracket. Thus the regex arguments, like i, are included in parenthesis immediately following the trailing "/". +The first run of a sequence takes `[all[tiddlers]]` as its input, i.e. the set of all non-missing tiddlers.