Reputation: 131
Is there a better, more pythonic way to parse and set a value to variable (stored in var_dict dictionary) and get a value from the same?
The code below is fully working, but especially the setting and getting parts look too complicated.
from pyparsing import Word, nums, Forward, ZeroOrMore, alphas, alphanums, Group, Combine
def test_grammar():
number = Word(nums)
itemlist = Forward()
items = (number | itemlist)
itemlist << ('[' + items + ZeroOrMore(',' + items) + ']')
variable = Word(alphas, alphanums+"_")("variable")
data = itemlist("data")
assignment = Group(variable + '=' + data)("assignment")
indexes = ZeroOrMore('[' + number + ']')("index")
query = Combine(variable + indexes)("query")
action = assignment | query
return action
var_dict = {}
test_input1 = "nl = [1, [2, 3]]"
test_input2 = "nl[1][1]"
tokens1 = test_grammar().parseString(test_input1)
variable = tokens1['assignment']['variable']
data = ''.join(tokens1['assignment']['data'])
var_dict[variable] = eval(data)
print var_dict['nl']
tokens2 = test_grammar().parseString(test_input2)
variable = tokens2['query']['variable']
index = ''.join(tokens2['query']['index'])
print eval("var_dict['" + variable + "']" + index)
Produces as desired:
[1, [2, 3]]
3
Upvotes: 1
Views: 66
Reputation: 4689
eval()
is often a sign for taking a, sometimes dangerous, shortcut instead of using the language itself to express the solution. Either out of laziness or lack of knowledge about the language. Both eval()
calls can be avoided.
The first is used to parse a list of numbers which can be addressed by pyparsings parse actions.
The second is just there to avoid a simple loop.
from pyparsing import (
Word, nums, Forward, ZeroOrMore, alphas, alphanums, Group, Combine, Suppress
)
def test_grammar():
number = Word(nums).setParseAction(lambda toks: int(toks[0]))
itemlist = Forward()
items = number | itemlist
itemlist << Group(
Suppress('[')
+ items
+ ZeroOrMore(Suppress(',') + items)
+ Suppress(']')
).setParseAction(lambda toks: list(toks))
variable = Word(alphas, alphanums + '_')('variable')
data = itemlist('data')
assignment = Group(variable + '=' + data)('assignment')
indexes = ZeroOrMore(Suppress('[') + number + Suppress(']'))('indexes')
query = Combine(variable + indexes)('query')
action = assignment | query
return action
def main():
variables = dict()
test_input_a = 'nl = [1, [2, 3]]'
test_input_b = 'nl[1][1]'
grammar = test_grammar()
tokens = grammar.parseString(test_input_a)
data = tokens['assignment']['data'][0]
variables[tokens['assignment']['variable']] = data
print variables['nl']
tokens = grammar.parseString(test_input_b)
data = variables[tokens['query']['variable']]
for index in tokens['query']['indexes']:
data = data[index]
print data
if __name__ == '__main__':
main()
Upvotes: 2