summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-05 17:38:43 +0000
committerasargent@chromium.org <asargent@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-03-05 17:38:43 +0000
commitd01e6ff96b89ad55855f4e29684d059a8798e8f8 (patch)
tree8b43192473c8d5b154357f8bed80d67e94554639
parent00565d06c051fe61fbc707ca89508e8cd441a608 (diff)
downloadchromium_src-d01e6ff96b89ad55855f4e29684d059a8798e8f8.zip
chromium_src-d01e6ff96b89ad55855f4e29684d059a8798e8f8.tar.gz
chromium_src-d01e6ff96b89ad55855f4e29684d059a8798e8f8.tar.bz2
This adds support for a number of features in the current WebIDL spec (http://dev.w3.org/2006/webapi/WebIDL/):
-Callbacks -Dictionaries -static functions in interfaces -optional parameters and dictionary members It also introduces a "namespace" production to the grammar, which is just a named scope surrounding a list of other IDL fragments. Finally, there are a couple of random cleanups. BUG=116636 TEST=existing tests should still work Review URL: https://chromiumcodereview.appspot.com/9388002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@124959 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--ppapi/api/dev/pp_cursor_type_dev.idl3
-rwxr-xr-xppapi/generators/idl_lexer.py20
-rwxr-xr-xppapi/generators/idl_node.py6
-rw-r--r--ppapi/generators/idl_option.py3
-rwxr-xr-xppapi/generators/idl_parser.py117
5 files changed, 119 insertions, 30 deletions
diff --git a/ppapi/api/dev/pp_cursor_type_dev.idl b/ppapi/api/dev/pp_cursor_type_dev.idl
index 7166c2af..08abec3 100644
--- a/ppapi/api/dev/pp_cursor_type_dev.idl
+++ b/ppapi/api/dev/pp_cursor_type_dev.idl
@@ -7,8 +7,7 @@
* This file defines enumerations for cursor types.
*/
-[assert_size(4)]
-[notypedef] enum PP_CursorType_Dev {
+[assert_size(4),notypedef] enum PP_CursorType_Dev {
PP_CURSORTYPE_CUSTOM = -1,
PP_CURSORTYPE_POINTER = 0,
PP_CURSORTYPE_CROSS = 1,
diff --git a/ppapi/generators/idl_lexer.py b/ppapi/generators/idl_lexer.py
index d33414c..d45a4b8 100755
--- a/ppapi/generators/idl_lexer.py
+++ b/ppapi/generators/idl_lexer.py
@@ -55,6 +55,16 @@ class IDLLexer(object):
'STRUCT',
'TYPEDEF',
+ # Extra WebIDL keywords
+ 'CALLBACK',
+ 'DICTIONARY',
+ 'OPTIONAL',
+ 'STATIC',
+
+ # Invented for apps use
+ 'NAMESPACE',
+
+
# Data types
'FLOAT',
'OCT',
@@ -77,11 +87,17 @@ class IDLLexer(object):
'readonly' : 'READONLY',
'struct' : 'STRUCT',
'typedef' : 'TYPEDEF',
+
+ 'callback' : 'CALLBACK',
+ 'dictionary' : 'DICTIONARY',
+ 'optional' : 'OPTIONAL',
+ 'static' : 'STATIC',
+ 'namespace' : 'NAMESPACE',
}
# 'literals' is a value expected by lex which specifies a list of valid
# literal tokens, meaning the token type and token value are identical.
- literals = '"*.(){}[],;:=+-/~|&^'
+ literals = '"*.(){}[],;:=+-/~|&^?'
# Token definitions
#
@@ -116,7 +132,7 @@ class IDLLexer(object):
# A C or C++ style comment: /* xxx */ or //
def t_COMMENT(self, t):
- r'(/\*(.|\n)*?\*/)|(//.*)'
+ r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
self.AddLines(t.value.count('\n'))
return t
diff --git a/ppapi/generators/idl_node.py b/ppapi/generators/idl_node.py
index 0fee3ec..275562c 100755
--- a/ppapi/generators/idl_node.py
+++ b/ppapi/generators/idl_node.py
@@ -132,14 +132,18 @@ class IDLNode(IDLRelease):
tab = ''.rjust(depth * 2)
if is_comment:
+ out.write('%sComment\n' % tab)
for line in self.GetName().split('\n'):
- out.write('%s%s\n' % (tab, line))
+ out.write('%s "%s"\n' % (tab, line))
else:
out.write('%s%s\n' % (tab, self))
properties = self.property_node.GetPropertyList()
if properties:
out.write('%s Properties\n' % tab)
for p in properties:
+ if is_comment and p == 'NAME':
+ # Skip printing the name for comments, since we printed above already
+ continue
out.write('%s %s : %s\n' % (tab, p, self.GetProperty(p)))
for child in self.children:
child.Dump(depth+1, comments=comments, out=out)
diff --git a/ppapi/generators/idl_option.py b/ppapi/generators/idl_option.py
index 714b686..54ac4cf 100644
--- a/ppapi/generators/idl_option.py
+++ b/ppapi/generators/idl_option.py
@@ -60,7 +60,7 @@ def DumpHelp(option=None):
InfoOut.Log('Usage:')
for opt in sorted(OptionMap.keys()):
DumpOption(OptionMap[opt])
-
+ sys.exit(0)
#
# Default IDL options
@@ -70,6 +70,7 @@ def DumpHelp(option=None):
# --test : test this module
#
Option('h', 'Help', callfunc=DumpHelp)
+Option('help', 'Help', callfunc=DumpHelp)
Option('verbose', 'Verbose')
Option('test', 'Test the IDL scripts')
diff --git a/ppapi/generators/idl_parser.py b/ppapi/generators/idl_parser.py
index 45f1021..f1045c3 100755
--- a/ppapi/generators/idl_parser.py
+++ b/ppapi/generators/idl_parser.py
@@ -223,11 +223,14 @@ class IDLParser(IDLLexer):
# Build a list of top level items.
def p_top_list(self, p):
- """top_list : describe_block top_list
+ """top_list : callback_decl top_list
+ | describe_block top_list
+ | dictionary_block top_list
| enum_block top_list
| inline top_list
| interface_block top_list
| label_block top_list
+ | namespace top_list
| struct_block top_list
| typedef_decl top_list
| """
@@ -267,6 +270,44 @@ class IDLParser(IDLLexer):
#
+# Namespace
+#
+# A namespace provides a named scope to an enclosed top_list.
+#
+ def p_namespace(self, p):
+ """namespace : modifiers NAMESPACE namespace_name '{' top_list '}' ';'"""
+ children = ListFromConcat(p[1], p[5])
+ p[0] = self.BuildNamed('Namespace', p, 3, children)
+
+ # We allow namespace names of the form foo.bar.baz.
+ def p_namespace_name(self, p):
+ """namespace_name : SYMBOL
+ | SYMBOL '.' namespace_name"""
+ p[0] = "".join(p[1:])
+
+
+#
+# Dictionary
+#
+# A dictionary contains is a named list of optional and required members.
+#
+ def p_dictionary_block(self, p):
+ """dictionary_block : modifiers DICTIONARY SYMBOL '{' struct_list '}' ';'"""
+ p[0] = self.BuildNamed('Dictionary', p, 3, ListFromConcat(p[5]))
+
+#
+# Callback
+#
+# A callback is essentially a single function declaration (outside of an
+# Interface).
+#
+ def p_callback_decl(self, p):
+ """callback_decl : modifiers CALLBACK SYMBOL '=' SYMBOL param_list ';'"""
+ children = ListFromConcat(p[1], p[6])
+ p[0] = self.BuildNamed('Callback', p, 3, children)
+
+
+#
# Inline
#
# Inline blocks define option code to be emitted based on language tag,
@@ -482,6 +523,19 @@ class IDLParser(IDLLexer):
elif len(p) == 1: return
if self.parse_debug: DumpReduction('arrays', p)
+
+# An identifier is a legal value for a parameter or attribute name. Lots of
+# existing IDL files use "callback" as a parameter/attribute name, so we allow
+# a SYMBOL or the CALLBACK keyword.
+ def p_identifier(self, p):
+ """identifier : SYMBOL
+ | CALLBACK"""
+ p[0] = p[1]
+ # Save the line number of the underlying token (otherwise it gets
+ # discarded), since we use it in the productions with an identifier in
+ # them.
+ p.set_lineno(0, p.lineno(1))
+
#
# Parameter List
#
@@ -499,12 +553,19 @@ class IDLParser(IDLLexer):
if self.parse_debug: DumpReduction('param_list', p)
def p_param_item(self, p):
- """param_item : modifiers SYMBOL arrays SYMBOL"""
- typeref = self.BuildAttribute('TYPEREF', p[2])
- children = ListFromConcat(p[1],typeref, p[3])
- p[0] = self.BuildNamed('Param', p, 4, children)
+ """param_item : modifiers optional SYMBOL arrays identifier"""
+ typeref = self.BuildAttribute('TYPEREF', p[3])
+ children = ListFromConcat(p[1],p[2], typeref, p[4])
+ p[0] = self.BuildNamed('Param', p, 5, children)
if self.parse_debug: DumpReduction('param_item', p)
+ def p_optional(self, p):
+ """optional : OPTIONAL
+ | """
+ if len(p) == 2:
+ p[0] = self.BuildAttribute('OPTIONAL', True)
+
+
def p_param_cont(self, p):
"""param_cont : ',' param_item param_cont
| """
@@ -520,7 +581,7 @@ class IDLParser(IDLLexer):
#
# Typedef
#
-# A typedef creates a new referencable type. The tyepdef can specify an array
+# A typedef creates a new referencable type. The typedef can specify an array
# definition as well as a function declaration.
#
def p_typedef_data(self, p):
@@ -615,26 +676,31 @@ class IDLParser(IDLLexer):
# A member attribute or function of a struct or interface.
#
def p_member_attribute(self, p):
- """member_attribute : modifiers SYMBOL SYMBOL """
- typeref = self.BuildAttribute('TYPEREF', p[2])
- children = ListFromConcat(p[1], typeref)
- p[0] = self.BuildNamed('Member', p, 3, children)
- if self.parse_debug: DumpReduction('attribute', p)
-
- def p_member_attribute_array(self, p):
- """member_attribute : modifiers SYMBOL arrays SYMBOL """
+ """member_attribute : modifiers SYMBOL arrays questionmark identifier"""
typeref = self.BuildAttribute('TYPEREF', p[2])
- children = ListFromConcat(p[1], typeref, p[3])
- p[0] = self.BuildNamed('Member', p, 4, children)
+ children = ListFromConcat(p[1], typeref, p[3], p[4])
+ p[0] = self.BuildNamed('Member', p, 5, children)
if self.parse_debug: DumpReduction('attribute', p)
def p_member_function(self, p):
- """member_function : modifiers SYMBOL SYMBOL param_list"""
- typeref = self.BuildAttribute('TYPEREF', p[2])
- children = ListFromConcat(p[1], typeref, p[4])
- p[0] = self.BuildNamed('Member', p, 3, children)
+ """member_function : modifiers static SYMBOL SYMBOL param_list"""
+ typeref = self.BuildAttribute('TYPEREF', p[3])
+ children = ListFromConcat(p[1], p[2], typeref, p[5])
+ p[0] = self.BuildNamed('Member', p, 4, children)
if self.parse_debug: DumpReduction('function', p)
+ def p_static(self, p):
+ """static : STATIC
+ | """
+ if len(p) == 2:
+ p[0] = self.BuildAttribute('STATIC', True)
+
+ def p_questionmark(self, p):
+ """questionmark : '?'
+ | """
+ if len(p) == 2:
+ p[0] = self.BuildAttribute('OPTIONAL', True)
+
#
# Interface
#
@@ -770,14 +836,17 @@ class IDLParser(IDLLexer):
name = p[index]
# Remove comment markers
+ lines = []
if name[:2] == '//':
- # For C++ style, remove the preceding '//'
+ # For C++ style, remove any leading whitespace and the '//' marker from
+ # each line.
form = 'cc'
- name = name[2:].rstrip()
+ for line in name.split('\n'):
+ start = line.find('//')
+ lines.append(line[start+2:])
else:
# For C style, remove ending '*/''
form = 'c'
- lines = []
for line in name[:-2].split('\n'):
# Remove characters until start marker for this line '*' if found
# otherwise it should be blank.
@@ -787,7 +856,7 @@ class IDLParser(IDLLexer):
else:
line = ''
lines.append(line)
- name = '\n'.join(lines)
+ name = '\n'.join(lines)
childlist = [self.BuildAttribute('NAME', name),
self.BuildAttribute('FORM', form)]