0

I have text files that are in this format:

   BFrame.make()
      Frame.make_bbox()
         BBox.__init__(arg1=x, arg2=y, arg3=z)
         : None
         BBox.make()
           BBox.chk_pre()
           : None
         : (1,1,2,2)
      : None
      ExConfig.__init__(filename=None)
        ExConfig.setParam()
            ExConfig.setfromKey(AUTO=[0.0, 0.0])
                 ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])])
                 : None
            : None
        : [returns a list of paramaters]
        ExConfig.getKwList()
            : [('A_THR', 3.0), ('B_THICK', 24),]
      : None
    etc..
   :Frame

What you see above is a call hierarchy.

The indents show which methods have been called or are calling.

Any lines that begins with ':' shows a return value of a method.

My problem is how to parse the text files and and represent this as a call hierarchy tree where each node is a method called. We attach attributes to each Node which are the args passed to that method.

2 Answers 2

1

Looks like you need a real parser here, since this is not a trivial format.

Many methods for writing parsers in Python exist. See, for example, PLY. Another is PyParsing.

Alternatively, maybe Python Call Graph is what you really need?

Sign up to request clarification or add additional context in comments.

1 Comment

Something similar to pyCallGraph but for specific classes/methods. Our logging is done during run-time so called methods called are logged.
1

Here's my shot at this:

a = """BFrame.make()
      Frame.make_bbox()
         BBox.__init__(arg1=x, arg2=y, arg3=z)
         : None
         BBox.make()
           BBox.chk_pre()
           : None
         : (1,1,2,2)
      : None
      ExConfig.__init__(filename=None)
        ExConfig.setParam()
            ExConfig.setfromKey(AUTO=[0.0, 0.0])
                 ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])])
                 : None
            : None
        : [returns a list of paramaters]
        ExConfig.getKwList()
            : [('A_THR', 3.0), ('B_THICK', 24),]
      : None
   :Frame"""

b = [ line.strip() for line in a.split("\n") ]

stck1 = []
stck2 = []

while b:
    add_v = b.pop(0)
    if add_v[0] != ':':
        stck1.append(add_v)
    else:
        if stck2:
            mx = max([x[0] for x in stck2])
        else:
            mx = 0
        if len(stck1) < mx:
            calls = []
            while stck2 and stck2[-1][0] == mx:            
                calls.append(stck2.pop())
            stck2.append([len(stck1), stck1.pop(), add_v, calls[::-1]])
        else:
            stck2.append([len(stck1), stck1.pop(), add_v])

which gives you this:

>>> pprint.pprint(stck2, width=5)
[[1,
  'BFrame.make()',
  ':Frame',
  [[2,
    'Frame.make_bbox()',
    ': None',
    [[3,
      'BBox.__init__(arg1=x, arg2=y, arg3=z)',
      ': None'],
     [3,
      'BBox.make()',
      ': (1,1,2,2)',
      [[4,
        'BBox.chk_pre()',
        ': None']]]]],
   [2,
    'ExConfig.__init__(filename=None)',
    ': None',
    [[3,
      'ExConfig.setParam()',
      ': [returns a list of paramaters]',
      [[4,
        'ExConfig.setfromKey(AUTO=[0.0, 0.0])',
        ': None',
        [[5,
          "ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])])",
          ': None']]]]],
     [3,
      'ExConfig.getKwList()',
      ": [('A_THR', 3.0), ('B_THICK', 24),]"]]]]]]
>>> 

Nested [ hierarchy_level, call, result, children_calls ], where children are structured the same as their parents.

one way to format:

>>> def pretty(X):
...     if len(X)==4:
...         print '\t'*X[0], X[1], 'returns', X[2]
...         print '\t'*X[0], 'children:'
...         for child in X[3]:
...             pretty(child)
...     else:
...         print '\t'*X[0], X[1], 'returns', X[2]
...         print '\t'*X[0], 'no children'
... 
>>> pretty(stck2[0])
    BFrame.make() returns :Frame
    children:
        Frame.make_bbox() returns : None
        children:
            BBox.__init__(arg1=x, arg2=y, arg3=z) returns : None
            no children
            BBox.make() returns : (1,1,2,2)
            children:
                BBox.chk_pre() returns : None
                no children
        ExConfig.__init__(filename=None) returns : None
        children:
            ExConfig.setParam() returns : [returns a list of paramaters]
            children:
                ExConfig.setfromKey(AUTO=[0.0, 0.0]) returns : None
                children:
                    ExConfig.setFromList([('PHOT', [2.5, 3.5]), ('BV', [0.0, 0.0])]) returns : None
                    no children
            ExConfig.getKwList() returns : [('A_THR', 3.0), ('B_THICK', 24),]
            no children
>>> 

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.