Alternator
Alternator

Reputation: 575

Refactoring Python

I am trying to rewrite the following piece of python code which generates the current output below

 import json
 import re

 jsoninput = open("input.json").read()
 data = json.loads(jsoninput)
 dictat = {}
 dicvalue = {}
 def ev_declaration(line):
     tree = line['declared-variable']
     re.match ("x", line['declared-variable'])
     value = ev_value(line['value'])
     if line['declared-variable'] not in dictat.keys():
         dictat.update({line['declared-variable']:(value)})
     dicvalue.update({tree: (value)})
     return 'let ',tree ,value

 def ev_expression(line):
     if line['operator'] == 'set':
         args = [ev_value(a) for a in line['arguments']]
         try:
             return set(args)
         except:
             return (args)
     elif line['operator']== 'tuple':
         args = [ev_value(b) for b in line['arguments']]
         return (tuple(x for x in args))
     elif line['operator']=='equal':
         args = [ev_value(a) for a in line['arguments']]
         if args[0] == args[1]:
             return 1
         else:
             return 0
     elif line['operator']=='member':
         args = line['arguments']
         if ev_value(args[0]) in ev_value(args[1]):
             return 1
         else:
             return 0
     else:
         print ("Undefined!")

 def ev_value(line):
     try:
         if type(line) is int:
             return line
         elif type(line) is set:
             return line
         elif 'operator' in line:
             return ev_expression(line)
         elif 'variable' in line:
             if line['variable'] not in dictat.keys():
                 return 'undefined'
             if line['variable'] in dictat.keys():
                 return dictat[line['variable']]

     except TypeError:
         return ('be ', line)

 def output_tree(data):
     declaration_list = data['declaration-list']
     with open("output.txt","w")as outputfile:
         for i in declaration_list:
                 ev_declaration(i)
                 #json.dump(dicvalue,outputfile)
                 outputfile.write(';\n')
     with open("output.txt","w")as outputfile:
         for i in dicvalue:
             if i is not None:
                 temp = dicvalue[i]
                 print "let", i, "be", temp
     print dicvalue

 if __name__ == "__main__":
     output_tree(data)

as the following,

 import json
 import re

 jsoninput = open("input.json").read()
 data = json.loads(jsoninput)
 dictat = {}
 dicvalue = {}
 def parse_declaration(valinfo):
     tree = valinfo['declared-variable']
     re.match ("x", valinfo['declared-variable'])
     value = parse_rvalue(valinfo['value'])
     if valinfo['declared-variable'] not in dictat.keys():
         dictat.update({valinfo['declared-variable']:(value)})
     dicvalue.update({tree: (value)})
     return ('let ',tree ,value)


#def ev_expression(valinfo):
    #opfunc = _rv_parser[valinfo['operator']]
    #return opfunc(valinfo)

 def _rv_parse_set(valinfo):
     assert valinfo['operator'] == 'set'
     args = [parse_rvalue(a) for a in valinfo['arguments']]
     try:
         return set(args)
     except:
         return (args)

 def _rv_parse_equal(valinfo):
     assert valinfo['operator']=='equal'
     args = [parse_rvalue(a) for a in valinfo['arguments']]
     if args[0] == args[1]:
         return 1
     else:
         return 0   

 def _rv_parse_tuple(valinfo):
     assert valinfo['operator']== 'tuple'
     args = [parse_rvalue(b) for b in valinfo['arguments']]
     return (tuple(x for x in args))

 def _rv_parse_member(valinfo):
     assert valinfo['operator']=='member'
     args = valinfo['arguments']
     if parse_rvalue(args[0]) in parse_rvalue(args[1]):
         return 1
     else:
         return 0

_rv_parser = {
    "set": _rv_parse_set,
    "tuple":_rv_parse_tuple,
    "equal":_rv_parse_equal,
    "member":_rv_parse_member,
}

 def parse_rvalue(valinfo):
     try:
         if type(valinfo) is int:
             return valinfo
         elif type(valinfo) is set:
             return valinfo
         elif 'operator' in valinfo:
             return ev_expression(valinfo)
         elif 'variable' in valinfo:
             if valinfo['variable'] not in dictat.keys():
                 return 'undefined'
             if valinfo['variable'] in dictat.keys():
                 return dictat[valinfo['variable']]

     except TypeError:
         return ('be ', valinfo)


 def parse_json(data):
     declaration_list = data['declaration-list']
     with open("output.txt","w")as outputfile:
         for i in declaration_list:
                 parse_declaration(i)
                #json.dump(dicvalue,outputfile)
                 outputfile.write(';\n')
     with open("output.txt","w")as outputfile:
         for i in dicvalue:
             if i is not None:
                 temp = dicvalue[i]
                 print "let", i, "be", temp
     print dicvalue

 if __name__ == "__main__":
     parse_json(data)

like to know if i'm doing this correctly and if not, how to go about fixing it? as it doesn't seem to be working. do i need to declare a def ev_expression(line) as well? The first code parsecs the input below as json and is supposed to return the expected below. It mostly works in my first code above, but i'm trying to refactor to make it a bit clearer as well output to a text file instead of printing to the terminal

Current Output

 Undefined!
 Undefined!
 Undefined!
 Undefined!
 let x5 be None #should be Undefined
 let x13 be 0
 let x7 be None #should be Undefined
 let x19 be ([set([8, 1, 2]), (1, set([8, 1, 2]))], set([8, 1, 2]))
 let x14 be 1
 let x15 be 1
 let x18 be [set([8, 1, 2]), (1, set([8, 1, 2]))]
 let x2 be set([1, 2])
 let x8 be ((0, 1), (3, (4, 5)))
 let x9 be set([((0, 1), (3, (4, 5)))])
 let x4 be None #should be undefined
 let x11 be None #should be undefined
 let x10 be set([(1, 6), (0, 4)])
 let x3 be set([(1, 2), (3, 4)])
 let x0 be 1
 let x1 be 2
 let x6 be 1
 let x12 be -1
 let x16 be 8
 let x17 be set([8, 1, 2])

Expected Output

 let x0 be 1;
 let x1 be 2;
 let x2 be {1, 2};
 let x3 be {(1, 2), (3, 4)};
 let x6 be 1;
 let x8 be ((0, 1), (3, (4, 5)));
 let x9 be {((0, 1), (3, (4, 5)))};
 let x10 be {(0, 4), (1, 6)};
 let x12 be -1;
 let x13 be 0;
 let x14 be 1;
 let x15 be 1;
 let x16 be 8;
 let x17 be {1, 2, 8};
 let x18 be {{1, 2, 8}, (1, {1, 2, 8})};
 let x19 be ({{1, 2, 8}, (1, {1, 2, 8})}, {1, 2, 8});
 Undefined!
 Undefined!
 Undefined!
 Undefined!
 Undefined!
 Undefined!
 Undefined!
 Undefined!
 Undefined!

and input

{
"declaration-list": [{
    "declared-variable": "x0",
    "value": 1
}, {
    "declared-variable": "x1",
    "value": 2
}, {
    "declared-variable": "x2",
    "value": {
        "operator": "set",
        "arguments": [{
            "variable": "x0"
        }, {
            "variable": "x1"
        }]
    }

although the python program parses the input from a json file

Upvotes: 2

Views: 175

Answers (1)

aghast
aghast

Reputation: 15310

Yes, you still need a declaration for ev_expression, unless you also refactor it out. You will probably want a dict mapping the various operators to the functions. Something like:

op_funcs = {
    'set' : _rv_parse_set,
    'tuple' : _rv_parse_tuple,
    ...
}

Then your code would look like:

def ev_expression(line):
    opfunc = op_funcs[line['operator']]
    return opfunc(line)

EDIT

Okay, after your updates I added a MySet class to your code. This will format the way you want, and otherwise pretend to be a set.

import json
import re

class MySet:
    def __init__(self, *args):
        self._set = set(*args)

    def __contains__(self, x):
        return x in self._set

    def __repr__(self):
        return str(self)

    def __str__(self):
        return '{' + ', '.join((str(x) for x in self._set)) + '}'

dictat = {}
dicvalue = {}

def parse_declaration(valinfo):
    tree = valinfo['declared-variable']
    re.match ("x", valinfo['declared-variable'])
    value = parse_rvalue(valinfo['value'])
    if valinfo['declared-variable'] not in dictat.keys():
        dictat.update({valinfo['declared-variable']:(value)})
    dicvalue.update({tree: (value)})
    return ('let ',tree ,value)

def _rv_parse_apply_function(valinfo):
    assert valinfo['operator'] == 'apply-function'
    args = [parse_rvalue(a) for a in valinfo['arguments']]
    return "apply_function(" + ', '.join((str(a) for a in args)) + ")"

def _rv_parse_equal(valinfo):
    assert valinfo['operator']=='equal'
    args = [parse_rvalue(a) for a in valinfo['arguments']]
    return int(args[0] == args[1])

def _rv_parse_is_function(valinfo):
    assert valinfo['operator'] == 'is-function'
    args = [parse_rvalue(a) for a in valinfo['arguments']]
    return "is_function(" + ', '.join((str(a) for a in args)) + ")"

def _rv_parse_set(valinfo):
    assert valinfo['operator'] == 'set'
    args = [parse_rvalue(a) for a in valinfo['arguments']]
    try:
        #return set(args)
        return MySet(args)
    except:
        return args

def _rv_parse_tuple(valinfo):
    assert valinfo['operator']== 'tuple'
    args = [parse_rvalue(b) for b in valinfo['arguments']]
    return (tuple(x for x in args))

def _rv_parse_member(valinfo):
    assert valinfo['operator']=='member'
    args = [parse_rvalue(a) for a in valinfo['arguments']]
    return int(args[0] in args[1])

_rv_parser = {
    "apply-function": _rv_parse_apply_function,
    "equal":          _rv_parse_equal,
    "is-function":    _rv_parse_is_function,
    "set":            _rv_parse_set,
    "tuple":          _rv_parse_tuple,
    "member":         _rv_parse_member,
}

def parse_rvalue(valinfo):
#    try:
        if type(valinfo) is int:
            return valinfo
        elif type(valinfo) is set:
            return valinfo
        elif 'operator' in valinfo:
            opfunc = _rv_parser[valinfo['operator']]
            return opfunc(valinfo)
        elif 'variable' in valinfo:
            if valinfo['variable'] not in dictat.keys():
                return 'undefined'
            if valinfo['variable'] in dictat.keys():
                return dictat[valinfo['variable']]
#    except TypeError:
#        return ('be ', valinfo)


def parse_json(data):
    declaration_list = data['declaration-list']
    for i in declaration_list:
        parse_declaration(i)

    for i in sorted(dicvalue, key=lambda s: int(s[1:])):
        if i is not None:
            temp = str(dicvalue[i])
            print "let", i, "be", temp

if __name__ == "__main__":
    jsoninput = open("input.json").read()
    data = json.loads(jsoninput)
    parse_json(data)

Upvotes: 2

Related Questions