]> git.phdru.name Git - phdru.name/cgi-bin/blog-ru/search-tags.git/commitdiff
Version 0.6: Use parsley instead of parsimonious parsley v0.6
authorOleg Broytman <phd@phdru.name>
Sat, 20 May 2017 17:13:50 +0000 (20:13 +0300)
committerOleg Broytman <phd@phdru.name>
Sat, 20 May 2017 17:36:04 +0000 (20:36 +0300)
ChangeLog
parser/grammar.ebnf
parser/parser.py [changed mode: 0644->0755]
parser/test_parser.py
search-tags.py
version

index 838760876f367a8bcc1faf375e252a7455e9217f..9b7a3dc9d5348858ef108b973730b5d61fcac72f 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,4 +1,8 @@
-Version 0.5 (2017-04-??)
+Version 0.6 (2017-05-20)
+
+   Use parsley instead of parsimonious.
+
+Version 0.5 (2017-04-22)
 
    Use parsimonious instead of grako.
 
index 935e6a4d3477f7bfa557fde4a28c5dca83786eaa..43752574a181addd522514c7ff8e0e16d6346e6a 100644 (file)
 # This  is a simple version of the grammar and it allows
 # rather stupid expressions, like (TAG) or ((TAG)) or !(!(TAG)).
 
-expression = or_expression / aterm_expression
+expression = inner_expression:e end -> e
 
-or_expression = aterm_expression or_op expression
+inner_expression = (or_expression | aterm_expression):e -> e
 
-and_expression = term_expression and_op aterm_expression
+or_expression = aterm_expression:a or_op inner_expression:e -> ('OR', a, e)
 
-not_expression = not_op space0 (parens_expression / name)
+and_expression = term_expression:t and_op aterm_expression:a -> ('AND',
+t, a)
 
-aterm_expression = and_expression / term_expression
+not_expression = not_op ws (parens_expression | name):n -> ('NOT', n)
 
-term_expression = not_expression / parens_expression / (name space_b4letter)
+aterm_expression = (and_expression | term_expression):e -> e
 
-parens_expression = "(" space0 expression space0 ")"
+term_expression = (not_expression:e -> e) | (parens_expression:p -> p) | (name:n space_b4letter -> n)
 
-and_op = (space0 ("&&" / "&") space0) / (space0 ("AND" / "and") space_b4letter)
+parens_expression = '(' ws inner_expression:e ws ')' -> ('PARENS', e)
 
-or_op = (space0 ("||" / "|") space0) / (space0 ("OR" / "or") space_b4letter)
+and_op = (ws ('&&' | '&') ws) | (ws ('AND' | 'and') space_b4letter)
 
-not_op = (space0 "!" space0) / (space0 ("NOT" / "not") space_b4letter)
+or_op = (ws ('||' | '|') ws) | (ws ('OR' | 'or') space_b4letter)
 
-letter = ~"[a-z]"i
+not_op = (ws '!' ws) | (ws ('NOT' | 'not') space_b4letter)
 
-name = ~"[a-z][a-z0-9_]*"
+name = <lletter lletterOrDigit*>:n -> ('NAME', n)
 
-space_b4letter = (space1 &letter) / space0
+lletter = :l ?(l in 'abcdefghijklmnopqrstuvwxyz') -> l
 
-space0 = ~" *"
+digit = :d ?(d in '0123456789') -> d
 
-space1 = ~" +"
+lletterOrDigit = (lletter | digit):c -> c
+
+space_b4letter = (' '+ ~~letter) | ws
 
 # vim: set ft=text :
old mode 100644 (file)
new mode 100755 (executable)
index dc562dd..3f51d3f
@@ -1,5 +1,7 @@
+#! /usr/bin/env python
+
 import os
-from parsimonious import Grammar, NodeVisitor
+from parsley import makeGrammar
 
 
 # cache
@@ -11,44 +13,21 @@ def load_grammar():
     parser_dir = os.path.dirname(__file__)
     with open(os.path.join(parser_dir, 'grammar.ebnf'), 'rt') as grammar_file:
         grammar_text = grammar_file.read()
-    _grammar = Grammar(grammar_text)
+    _grammar = makeGrammar(grammar_text, {}, 'Tags')
 
 
 def parse(input):
     if _grammar is None:
         load_grammar()
-    return _grammar.parse(input)
-
-
-def cleanup_children(visited_children):
-    children = [c for c in visited_children if c]
-    if len(children) == 1:
-        return children[0]
-    else:
-        return children
-
-
-class Compiler(NodeVisitor):
-    def generic_visit(self, node, visited_children):
-        return cleanup_children(visited_children)
-
-    def visit_or_expression(self, node, visited_children):
-        return ('OR', visited_children[0], visited_children[2])
-
-    def visit_and_expression(self, node, visited_children):
-        return ('AND', visited_children[0], visited_children[2])
-
-    def visit_not_expression(self, node, visited_children):
-        return ('NOT', visited_children[2])
-
-    def visit_parens_expression(self, node, visited_children):
-        return ('PARENS', visited_children[2])
-
-    def visit_name(self, node, visited_children):
-        return ('NAME', node.text)
-
-
-def compile(tree):
-    if isinstance(tree, str):
-        tree = parse(tree)
-    return Compiler().visit(tree)
+    return _grammar(input).expression()
+
+
+if __name__ == '__main__':
+    print parse('test')
+    print parse('!test')
+    print parse('not test')
+    print parse('foo or bar')
+    print parse('foo && bar')
+    print parse('(test)')
+    print parse('(foo || bar)')
+    print parse('(foo and !bar)')
index 0a30eda4217dd655b99c272b6001151c598fd6e6..67c0ae3fc848e0a95df1a47e3c2387017b7d7491 100755 (executable)
@@ -1,12 +1,12 @@
 #! /usr/bin/env python
 
 import unittest
-from parsimonious import ParseError
-from parser import compile
+from ometa.runtime import ParseError
+from parser import parse
 
 class TestParser(unittest.TestCase):
     def _parse(self, input):
-        return compile(input)
+        return parse(input)
 
     def test_02_tag(self):
         self.assertEqual(self._parse('xxx'), ('NAME', 'xxx'))
index c0919660befab6331cff2de6532e3b0b5c01b642..4f6810adc65a34a95c08ca3b843e6eb5316569d0 100755 (executable)
@@ -7,7 +7,7 @@ __copyright__ = "Copyright (C) 2014-2017 PhiloSoft Design"
 __license__ = "GNU GPL"
 
 import cgi, sys
-from parsimonious import ParseError
+from ometa.runtime import ParseError
 from html.response import redirect, response
 from parser import parser
 
@@ -20,7 +20,7 @@ if not form.has_key('q'):
 else:
     q = form['q'].value
     try:
-        tree = parser.compile(q)
+        tree = parser.parse(q)
     except ParseError:
         status = "400 Bad request"
         title = "Error!"
diff --git a/version b/version
index 2eb3c4fe4eebcdea3da0790cc0ba74cb286ec4f4..5a2a5806df6e909afe3609b5706cb1012913ca0e 100644 (file)
--- a/version
+++ b/version
@@ -1 +1 @@
-0.5
+0.6