| Index: third_party/chrome/ppapi/generators/idl_propertynode.py
|
| diff --git a/third_party/chrome/ppapi/generators/idl_propertynode.py b/third_party/chrome/ppapi/generators/idl_propertynode.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..33837a3cefa98f90a94249fbb15ded53fefe85df
|
| --- /dev/null
|
| +++ b/third_party/chrome/ppapi/generators/idl_propertynode.py
|
| @@ -0,0 +1,197 @@
|
| +#!/usr/bin/env python
|
| +# Copyright (c) 2012 The Chromium Authors. All rights reserved.
|
| +# Use of this source code is governed by a BSD-style license that can be
|
| +# found in the LICENSE file.
|
| +
|
| +""" Hierarchical property system for IDL AST """
|
| +import re
|
| +import sys
|
| +
|
| +from idl_log import ErrOut, InfoOut, WarnOut
|
| +from idl_option import GetOption, Option, ParseOptions
|
| +
|
| +#
|
| +# IDLPropertyNode
|
| +#
|
| +# A property node is a hierarchically aware system for mapping
|
| +# keys to values, such that a local dictionary is search first,
|
| +# followed by parent dictionaries in order.
|
| +#
|
| +class IDLPropertyNode(object):
|
| + def __init__(self):
|
| + self.parents = []
|
| + self.property_map = {}
|
| +
|
| + def Error(self, msg):
|
| + name = self.GetProperty('NAME', 'Unknown')
|
| + parents = [parent.GetProperty('NAME', '???') for parent in self.parents]
|
| + ErrOut.Log('%s [%s] : %s' % (name, ' '.join(parents), msg))
|
| +
|
| + def AddParent(self, parent):
|
| + assert parent
|
| + self.parents.append(parent)
|
| +
|
| + def SetProperty(self, name, val):
|
| + self.property_map[name] = val
|
| +
|
| + def _GetProperty_(self, name):
|
| + # Check locally for the property, and return it if found.
|
| + prop = self.property_map.get(name, None)
|
| + if prop is not None: return prop
|
| + # If not, seach parents in order
|
| + for parent in self.parents:
|
| + prop = parent.GetProperty(name)
|
| + if prop is not None: return prop
|
| + # Otherwise, it can not be found.
|
| + return None
|
| +
|
| + def GetProperty(self, name, default=None):
|
| + prop = self._GetProperty_(name)
|
| + if prop is None:
|
| + return default
|
| + else:
|
| + return prop
|
| +
|
| + def GetPropertyLocal(self, name, default=None):
|
| + # Search for the property, but only locally, returning the
|
| + # default if not found.
|
| + prop = self.property_map.get(name, default)
|
| + return prop
|
| +
|
| + # Regular expression to parse property keys in a string such that a string
|
| + # "My string $NAME$" will find the key "NAME".
|
| + regex_var = re.compile('(?P<src>[^\\$]+)|(?P<key>\\$\\w+\\$)')
|
| +
|
| + def GetPropertyList(self):
|
| + return self.property_map.keys()
|
| +
|
| + # Recursively expands text keys in the form of $KEY$ with the value
|
| + # of the property of the same name. Since this is done recursively
|
| + # one property can be defined in terms of another.
|
| + def Replace(self, text):
|
| + itr = IDLPropertyNode.regex_var.finditer(text)
|
| + out = ''
|
| + for m in itr:
|
| + (start, stop) = m.span()
|
| + if m.lastgroup == 'src':
|
| + out += text[start:stop]
|
| + if m.lastgroup == 'key':
|
| + key = text[start+1:stop-1]
|
| + val = self.GetProperty(key, None)
|
| + if not val:
|
| + self.Error('No property "%s"' % key)
|
| + out += self.Replace(str(val))
|
| + return out
|
| +
|
| +
|
| +#
|
| +# Testing functions
|
| +#
|
| +
|
| +# Build a property node, setting the properties including a name, and
|
| +# associate the children with this new node.
|
| +#
|
| +def BuildNode(name, props, children=[], parents=[]):
|
| + node = IDLPropertyNode()
|
| + node.SetProperty('NAME', name)
|
| + for prop in props:
|
| + toks = prop.split('=')
|
| + node.SetProperty(toks[0], toks[1])
|
| + for child in children:
|
| + child.AddParent(node)
|
| + for parent in parents:
|
| + node.AddParent(parent)
|
| + return node
|
| +
|
| +def ExpectProp(node, name, val):
|
| + found = node.GetProperty(name)
|
| + if found != val:
|
| + ErrOut.Log('Got property %s expecting %s' % (found, val))
|
| + return 1
|
| + return 0
|
| +
|
| +#
|
| +# Verify property inheritance
|
| +#
|
| +def PropertyTest():
|
| + errors = 0
|
| + left = BuildNode('Left', ['Left=Left'])
|
| + right = BuildNode('Right', ['Right=Right'])
|
| + top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right])
|
| +
|
| + errors += ExpectProp(top, 'Left', 'Top')
|
| + errors += ExpectProp(top, 'Right', 'Top')
|
| +
|
| + errors += ExpectProp(left, 'Left', 'Left')
|
| + errors += ExpectProp(left, 'Right', 'Top')
|
| +
|
| + errors += ExpectProp(right, 'Left', 'Top')
|
| + errors += ExpectProp(right, 'Right', 'Right')
|
| +
|
| + if not errors: InfoOut.Log('Passed PropertyTest')
|
| + return errors
|
| +
|
| +
|
| +def ExpectText(node, text, val):
|
| + found = node.Replace(text)
|
| + if found != val:
|
| + ErrOut.Log('Got replacement %s expecting %s' % (found, val))
|
| + return 1
|
| + return 0
|
| +
|
| +#
|
| +# Verify text replacement
|
| +#
|
| +def ReplaceTest():
|
| + errors = 0
|
| + left = BuildNode('Left', ['Left=Left'])
|
| + right = BuildNode('Right', ['Right=Right'])
|
| + top = BuildNode('Top', ['Left=Top', 'Right=Top'], [left, right])
|
| +
|
| + errors += ExpectText(top, '$Left$', 'Top')
|
| + errors += ExpectText(top, '$Right$', 'Top')
|
| +
|
| + errors += ExpectText(left, '$Left$', 'Left')
|
| + errors += ExpectText(left, '$Right$', 'Top')
|
| +
|
| + errors += ExpectText(right, '$Left$', 'Top')
|
| + errors += ExpectText(right, '$Right$', 'Right')
|
| +
|
| + if not errors: InfoOut.Log('Passed ReplaceTest')
|
| + return errors
|
| +
|
| +
|
| +def MultiParentTest():
|
| + errors = 0
|
| +
|
| + parent1 = BuildNode('parent1', ['PARENT1=parent1', 'TOPMOST=$TOP$'])
|
| + parent2 = BuildNode('parent2', ['PARENT1=parent2', 'PARENT2=parent2'])
|
| + child = BuildNode('child', ['CHILD=child'], parents=[parent1, parent2])
|
| + BuildNode('top', ['TOP=top'], children=[parent1])
|
| +
|
| + errors += ExpectText(child, '$CHILD$', 'child')
|
| + errors += ExpectText(child, '$PARENT1$', 'parent1')
|
| + errors += ExpectText(child, '$PARENT2$', 'parent2')
|
| +
|
| + # Verify recursive resolution
|
| + errors += ExpectText(child, '$TOPMOST$', 'top')
|
| +
|
| + if not errors: InfoOut.Log('Passed MultiParentTest')
|
| + return errors
|
| +
|
| +
|
| +def Main():
|
| + errors = 0
|
| + errors += PropertyTest()
|
| + errors += ReplaceTest()
|
| + errors += MultiParentTest()
|
| +
|
| + if errors:
|
| + ErrOut.Log('IDLNode failed with %d errors.' % errors)
|
| + return -1
|
| + return 0
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(Main())
|
| +
|
|
|