1

I'm using parsimonious to parse some csv. My problem is that the output generated is not coming out in the order expected. For example, if the input string is

Load,File,Sample 

then I'd expect to get:

import database from Sample

What I get instead is:

from Sample import database

This is a consistent problem for every input I try: the first token is the last item in the entry OrderedDict but I can't figure out why.

Here's my code:

from parsimonious.grammar import Grammar
from parsimonious.nodes import NodeVisitor
from collections import OrderedDict

class EntryParser(NodeVisitor):
    def __init__(self, grammar, text):
        self.entry = OrderedDict()
        ast = Grammar(grammar).parse(text)
        self.visit(ast)
    def visit_alt(self, n, vc):
        self.entry['alt'] = "alter "
    def visit_load(self, n, vc):
        self.entry['load'] = "import database "
    def visit_app(self, n, vc):
        self.entry['app'] = "application "
    def visit_db(self, n, vc):
        self.entry['db'] = "database "
    def visit_filter(self, n, vc):
        self.entry['filter'] = "filter "
    def visit_group(self, n, vc):
        self.entry['group'] = "group "
    def visit_obj(self, n, vc):
        self.entry['obj'] = "object "
    def visit_trigger(self, n, vc):
        self.entry['trigger'] = "trigger "
    def visit_user(self, n, vc):
        self.entry['user'] = "user "
    def visit_sql(self, n, vc):
        self.entry['sql'] = "connect as "
    def visit_file(self, n, vc):
        self.entry['file'] = "from "
    def visit_dbname(self, n, vc):
        self.entry['dbname'] = n.text + " "
    def generic_visit(self, n, vc):
        pass

grammar = """\
ts0 = alt / load
sep = ","
alt = "Alt" sep altdomain
altdomain = app / db / filter / group / obj / trigger / user
load = "Load" sep loaddomain
loaddomain = (sql / file) sep dbname
sql = "SQL"
file = "File"
app = "App"
db = "DB"
filter = "Filter"
group = "Group"
obj = "Object"
trigger = "Trigger"
user = "User"
dbname = ~"[A-z]+"
"""

text = """\
Alt,Filter
Alt,App
Alt,DB
Alt,Group,
Alt,Object
Alt,Trigger
Alt,User
Load,SQL,Sample
Load,File,Sample
"""

for line in text.splitlines():
    for v in EntryParser(grammar, line).entry.values():
        print(v, end="")
    print('\n')
sophros
  • 14,672
  • 11
  • 46
  • 75
Drew Rush
  • 710
  • 5
  • 19

1 Answers1

0

I think the OrderedDict is causing problems. Just use a Regular Dictionary instead {}.

Basically change self.entry = OrderedDict() to self.entry = {}

Also the way grammar based parsing works, first the innermost element will be matched, then it will move towards the outer matched rules(in terms of returning the value).

So in order to get the proper order right, you will have to use a stack(or use a regular list and inverse the array).