# Grammar rules for tag searching # The grammar defines expressions in the following forms: # TAG - search blog posts that contain the tag; # !TAG - search blog posts that don't contain the tag; # TAG & TAG - search blog posts that contain both tags; # TAG | TAG - search blog posts that contain any of the tags; # Parentheses are allowed to group expressions; for example: # TAG & (TAG | TAG) # !(TAG | TAG) # Allowed operators: conjunction - & && AND and # disjunction - | || OR or # negation - ! NOT not # Usual priority: NOT recognized before AND, AND before OR. # This is a simple version of the grammar and it allows # rather stupid expressions, like (TAG) or ((TAG)) or !(!(TAG)). expression = inner_expression:e end -> e inner_expression = (or_expression | aterm_expression):e -> e or_expression = aterm_expression:a or_op inner_expression:e -> ('OR', a, e) and_expression = term_expression:t and_op aterm_expression:a -> ('AND', t, a) not_expression = not_op ws (parens_expression | name):n -> ('NOT', n) aterm_expression = (and_expression | term_expression):e -> e term_expression = (not_expression:e -> e) | (parens_expression:p -> p) | (name:n space_b4letter -> n) parens_expression = '(' ws inner_expression:e ws ')' -> ('PARENS', e) and_op = (ws ('&&' | '&') ws) | (ws ('AND' | 'and') space_b4letter) or_op = (ws ('||' | '|') ws) | (ws ('OR' | 'or') space_b4letter) not_op = (ws '!' ws) | (ws ('NOT' | 'not') space_b4letter) name = :n -> ('NAME', n) lletter = :l ?(l in 'abcdefghijklmnopqrstuvwxyz') -> l digit = :d ?(d in '0123456789') -> d lletterOrDigit = (lletter | digit):c -> c space_b4letter = (' '+ ~~letter) | ws # vim: set ft=text :