]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blob - parser/grammar.ebnf
Version 0.6: Use parsley instead of parsimonious
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / grammar.ebnf
1 # Grammar rules for tag searching
2
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:
9 #  TAG & (TAG | TAG)
10 #  !(TAG | TAG)
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)).
17
18 expression = inner_expression:e end -> e
19
20 inner_expression = (or_expression | aterm_expression):e -> e
21
22 or_expression = aterm_expression:a or_op inner_expression:e -> ('OR', a, e)
23
24 and_expression = term_expression:t and_op aterm_expression:a -> ('AND',
25 t, a)
26
27 not_expression = not_op ws (parens_expression | name):n -> ('NOT', n)
28
29 aterm_expression = (and_expression | term_expression):e -> e
30
31 term_expression = (not_expression:e -> e) | (parens_expression:p -> p) | (name:n space_b4letter -> n)
32
33 parens_expression = '(' ws inner_expression:e ws ')' -> ('PARENS', e)
34
35 and_op = (ws ('&&' | '&') ws) | (ws ('AND' | 'and') space_b4letter)
36
37 or_op = (ws ('||' | '|') ws) | (ws ('OR' | 'or') space_b4letter)
38
39 not_op = (ws '!' ws) | (ws ('NOT' | 'not') space_b4letter)
40
41 name = <lletter lletterOrDigit*>:n -> ('NAME', n)
42
43 lletter = :l ?(l in 'abcdefghijklmnopqrstuvwxyz') -> l
44
45 digit = :d ?(d in '0123456789') -> d
46
47 lletterOrDigit = (lletter | digit):c -> c
48
49 space_b4letter = (' '+ ~~letter) | ws
50
51 # vim: set ft=text :