]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/blobdiff - parser/grammar.ebnf
Version 0.7: Use lark instead of parsley
[phdru.name/cgi-bin/blog-ru/search-tags.git] / parser / grammar.ebnf
index 43752574a181addd522514c7ff8e0e16d6346e6a..3be4d166e0ed7eac1643b7e0176d35e2e75f7d8a 100644 (file)
@@ -1,4 +1,4 @@
-# Grammar rules for tag searching
+# Grammar rules for tag searching; EBNF.
 
 # The grammar defines expressions in the following forms:
 #  TAG - search blog posts that contain the 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)).
+# rather stupid expressions, like !!TAG or ((TAG)); in the future
+# it will be fixed by making the grammar more complex and stricter.
 
-expression = inner_expression:e end -> e
+?start : expression
 
-inner_expression = (or_expression | aterm_expression):e -> e
+?expression : or_expression
+            | and_expression
+            | and_sub_expression
 
-or_expression = aterm_expression:a or_op inner_expression:e -> ('OR', a, e)
+or_expression : or_sub_expression (or or_sub_expression)+
 
-and_expression = term_expression:t and_op aterm_expression:a -> ('AND',
-t, a)
+?or_sub_expression : and_expression
+                   | and_sub_expression
 
-not_expression = not_op ws (parens_expression | name):n -> ('NOT', n)
+and_expression : and_sub_expression (and and_sub_expression)+
 
-aterm_expression = (and_expression | term_expression):e -> e
+?and_sub_expression : not_expression
+                    | expression_parens
+                    | name
 
-term_expression = (not_expression:e -> e) | (parens_expression:p -> p) | (name:n space_b4letter -> n)
+not_expression: not and_sub_expression
 
-parens_expression = '(' ws inner_expression:e ws ')' -> ('PARENS', e)
+expression_parens : "(" expression ")"
 
-and_op = (ws ('&&' | '&') ws) | (ws ('AND' | 'and') space_b4letter)
+name : /[a-z][a-z0-9_]+/
 
-or_op = (ws ('||' | '|') ws) | (ws ('OR' | 'or') space_b4letter)
+?and : and_op
+     | and_op and_op
+     | and_word
 
-not_op = (ws '!' ws) | (ws ('NOT' | 'not') space_b4letter)
+?or : or_op
+    | or_op or_op
+    | or_word
 
-name = <lletter lletterOrDigit*>:n -> ('NAME', n)
+?not : not_op
+     | not_word
 
-lletter = :l ?(l in 'abcdefghijklmnopqrstuvwxyz') -> l
+?and_op : "&"
 
-digit = :d ?(d in '0123456789') -> d
+?or_op : "|"
 
-lletterOrDigit = (lletter | digit):c -> c
+?not_op : "!"
 
-space_b4letter = (' '+ ~~letter) | ws
+?and_word : "AND"
+          | "and"
 
-# vim: set ft=text :
+?or_word : "OR"
+         | "or"
+
+?not_word : "NOT"
+          | "not"
+
+%import common.WS
+%ignore WS