Home | History | Annotate | Download | only in idl_parser
      1 #!/usr/bin/env python
      2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
      3 # Use of this source code is governed by a BSD-style license that can be
      4 # found in the LICENSE file.
      5 
      6 import sys
      7 
      8 #
      9 # IDL Node
     10 #
     11 # IDL Node defines the IDLAttribute and IDLNode objects which are constructed
     12 # by the parser as it processes the various 'productions'.  The IDLAttribute
     13 # objects are assigned to the IDLNode's property dictionary instead of being
     14 # applied as children of The IDLNodes, so they do not exist in the final tree.
     15 # The AST of IDLNodes is the output from the parsing state and will be used
     16 # as the source data by the various generators.
     17 #
     18 
     19 
     20 #
     21 # CopyToList
     22 #
     23 # Takes an input item, list, or None, and returns a new list of that set.
     24 def CopyToList(item):
     25   # If the item is 'Empty' make it an empty list
     26   if not item:
     27     item = []
     28 
     29   # If the item is not a list
     30   if type(item) is not type([]):
     31     item = [item]
     32 
     33   # Make a copy we can modify
     34   return list(item)
     35 
     36 
     37 # IDLSearch
     38 #
     39 # A temporary object used by the parsing process to hold an Extended Attribute
     40 # which will be passed as a child to a standard IDLNode.
     41 #
     42 class IDLSearch(object):
     43   def __init__(self):
     44     self.depth = 0
     45 
     46   def Enter(self, node):
     47     pass
     48 
     49   def Exit(self, node):
     50     pass
     51 
     52 
     53 # IDLAttribute
     54 #
     55 # A temporary object used by the parsing process to hold an Extended Attribute
     56 # which will be passed as a child to a standard IDLNode.
     57 #
     58 class IDLAttribute(object):
     59   def __init__(self, name, value):
     60     self._cls = 'Property'
     61     self.name = name
     62     self.value = value
     63 
     64   def __str__(self):
     65     return '%s=%s' % (self.name, self.value)
     66 
     67   def GetClass(self):
     68     return self._cls
     69 
     70 #
     71 # IDLNode
     72 #
     73 # This class implements the AST tree, providing the associations between
     74 # parents and children.  It also contains a namepsace and propertynode to
     75 # allow for look-ups.  IDLNode is derived from IDLRelease, so it is
     76 # version aware.
     77 #
     78 class IDLNode(object):
     79   def __init__(self, cls, filename, lineno, pos, children=None):
     80     self._cls = cls
     81     self._properties = {
     82       'ERRORS' : [],
     83       'WARNINGS': [],
     84       'FILENAME': filename,
     85       'LINENO' : lineno,
     86       'POSSITION' : pos,
     87     }
     88 
     89     self._children = []
     90     self._parent = None
     91     self.AddChildren(children)
     92 
     93 #
     94 #
     95 #
     96   # Return a string representation of this node
     97   def __str__(self):
     98     name = self.GetProperty('NAME','')
     99     return '%s(%s)' % (self._cls, name)
    100 
    101   def GetLogLine(self, msg):
    102     filename, lineno = self.GetFileAndLine()
    103     return '%s(%d) : %s\n' % (filename, lineno, msg)
    104 
    105   # Log an error for this object
    106   def Error(self, msg):
    107     self.GetProperty('ERRORS').append(msg)
    108     sys.stderr.write(self.GetLogLine('error: ' + msg))
    109 
    110   # Log a warning for this object
    111   def Warning(self, msg):
    112     self.GetProperty('WARNINGS').append(msg)
    113     sys.stdout.write(self.GetLogLine('warning:' + msg))
    114 
    115   # Return file and line number for where node was defined
    116   def GetFileAndLine(self):
    117     return self.GetProperty('FILENAME'), self.GetProperty('LINENO')
    118 
    119   def GetClass(self):
    120     return self._cls
    121 
    122   def GetName(self):
    123     return self.GetProperty('NAME')
    124 
    125   def GetParent(self):
    126     return self._parent
    127 
    128   def Traverse(self, search, filter_nodes):
    129     if self._cls in filter_nodes:
    130       return ''
    131 
    132     search.Enter(self)
    133     search.depth += 1
    134     for child in self._children:
    135       child.Traverse(search, filter_nodes)
    136     search.depth -= 1
    137     search.Exit(self)
    138 
    139 
    140   def Tree(self, filter_nodes=None, accept_props=None):
    141     class DumpTreeSearch(IDLSearch):
    142       def __init__(self, props):
    143         IDLSearch.__init__(self)
    144         self.out = []
    145         self.props = props
    146 
    147       def Enter(self, node):
    148         tab = ''.rjust(self.depth * 2)
    149         self.out.append(tab + str(node))
    150         if self.props:
    151           proplist = []
    152           for key, value in node.GetProperties().iteritems():
    153             if key in self.props:
    154               proplist.append(tab + '    %s: %s' % (key, str(value)))
    155           if proplist:
    156             self.out.append(tab + '  PROPERTIES')
    157             self.out.extend(proplist)
    158 
    159     if filter_nodes == None:
    160       filter_nodes = ['Comment', 'Copyright']
    161 
    162     search = DumpTreeSearch(accept_props)
    163     self.Traverse(search, filter_nodes)
    164     return search.out
    165 
    166 #
    167 # Search related functions
    168 #
    169   # Check if node is of a given type
    170   def IsA(self, *typelist):
    171     if self._cls in typelist:
    172       return True
    173     return False
    174 
    175   # Get a list of all children
    176   def GetChildren(self):
    177     return self._children
    178 
    179   def GetListOf(self, *keys):
    180     out = []
    181     for child in self.GetChildren():
    182       if child.GetClass() in keys:
    183         out.append(child)
    184     return out
    185 
    186   def GetOneOf(self, *keys):
    187     out = self.GetListOf(*keys)
    188     if out:
    189       return out[0]
    190     return None
    191 
    192   def AddChildren(self, children):
    193     children = CopyToList(children)
    194     for child in children:
    195       if not child:
    196         continue
    197       if type(child) == IDLAttribute:
    198         self.SetProperty(child.name, child.value)
    199         continue
    200       if type(child) == IDLNode:
    201         child._parent = self
    202         self._children.append(child)
    203         continue
    204       raise RuntimeError('Adding child of type %s.\n' % type(child).__name__)
    205 
    206 
    207 #
    208 # Property Functions
    209 #
    210   def SetProperty(self, name, val):
    211     self._properties[name] = val
    212 
    213   def GetProperty(self, name, default=None):
    214     return self._properties.get(name, default)
    215 
    216   def GetProperties(self):
    217     return self._properties
    218