1 # Grammar rules for tag searching
3 # The grammar defines expressions in the following forms:
4 # TAG - search blog posts that contain the tag;
5 # !TAG - search blog posts that don't contain the tag;
6 # TAG & TAG - search blog posts that contain both tags;
7 # TAG | TAG - search blog posts that contain any of the tags;
8 # Parentheses are allowed to group expressions; for example:
11 # Allowed operators: conjunction - & && AND and
12 # disjunction - | || OR or
13 # negation - ! NOT not
14 # Usual priority: NOT recognized before AND, AND before OR.
15 # This is a simple version of the grammar and it allows
16 # rather stupid expressions, like (TAG) or ((TAG)) or !(!(TAG)).
18 expression = inner_expression:e end -> e
20 inner_expression = (or_expression | aterm_expression):e -> e
22 or_expression = aterm_expression:a or_op inner_expression:e -> ('OR', a, e)
24 and_expression = term_expression:t and_op aterm_expression:a -> ('AND',
27 not_expression = not_op ws (parens_expression | name):n -> ('NOT', n)
29 aterm_expression = (and_expression | term_expression):e -> e
31 term_expression = (not_expression:e -> e) | (parens_expression:p -> p) | (name:n space_b4letter -> n)
33 parens_expression = '(' ws inner_expression:e ws ')' -> ('PARENS', e)
35 and_op = (ws ('&&' | '&') ws) | (ws ('AND' | 'and') space_b4letter)
37 or_op = (ws ('||' | '|') ws) | (ws ('OR' | 'or') space_b4letter)
39 not_op = (ws '!' ws) | (ws ('NOT' | 'not') space_b4letter)
41 name = <lletter lletterOrDigit*>:n -> ('NAME', n)
43 lletter = :l ?(l in 'abcdefghijklmnopqrstuvwxyz') -> l
45 digit = :d ?(d in '0123456789') -> d
47 lletterOrDigit = (lletter | digit):c -> c
49 space_b4letter = (' '+ ~~letter) | ws