karu
karu

Reputation: 131

Handling parsed variables stored in dictionary

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

Answers (1)

BlackJack
BlackJack

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

Related Questions