Index: ppapi/generators/idl_parser.py |
=================================================================== |
--- ppapi/generators/idl_parser.py (revision 163185) |
+++ ppapi/generators/idl_parser.py (working copy) |
@@ -35,6 +35,7 @@ |
from idl_node import IDLAttribute, IDLFile, IDLNode |
from idl_option import GetOption, Option, ParseOptions |
from idl_lint import Lint |
+from idl_visitor import IDLVisitor |
from ply import lex |
from ply import yacc |
@@ -242,6 +243,7 @@ |
| namespace top_list |
| struct_block top_list |
| typedef_decl top_list |
+ | bad_decl top_list |
| """ |
if len(p) > 2: |
p[0] = ListFromConcat(p[1], p[2]) |
@@ -252,6 +254,11 @@ |
"""top_list : error top_list""" |
p[0] = p[2] |
+ # Recover from error and continue parsing at the next top match. |
+ def p_bad_decl(self, p): |
+ """bad_decl : modifiers SYMBOL error '}' ';'""" |
+ p[0] = [] |
+ |
# |
# Modifier List |
# |
@@ -443,6 +450,11 @@ |
p[0] = self.BuildProduction('Describe', p, 2, children) |
if self.parse_debug: DumpReduction('describe_block', p) |
+ # Recover from describe error and continue parsing at the next top match. |
+ def p_describe_error(self, p): |
+ """describe_list : error describe_list""" |
+ p[0] = [] |
+ |
def p_describe_list(self, p): |
"""describe_list : modifiers SYMBOL ';' describe_list |
| modifiers ENUM ';' describe_list |
@@ -453,10 +465,6 @@ |
Type = self.BuildNamed('Type', p, 2, p[1]) |
p[0] = ListFromConcat(Type, p[4]) |
- def p_describe_error(self, p): |
- """describe_list : error describe_list""" |
- p[0] = p[2] |
- |
# |
# Constant Values (integer, value) |
# |
@@ -648,6 +656,15 @@ |
p[0] = self.BuildNamed('Enum', p, 3, ListFromConcat(p[1], p[5])) |
if self.parse_debug: DumpReduction('enum_block', p) |
+ # Recover from enum error and continue parsing at the next top match. |
+ def p_enum_errorA(self, p): |
+ """enum_block : modifiers ENUM error '{' enum_list '}' ';'""" |
+ p[0] = [] |
+ |
+ def p_enum_errorB(self, p): |
+ """enum_block : modifiers ENUM error ';'""" |
+ p[0] = [] |
+ |
def p_enum_list(self, p): |
"""enum_list : modifiers SYMBOL '=' expression enum_cont |
| modifiers SYMBOL enum_cont""" |
@@ -743,6 +760,10 @@ |
p[0] = self.BuildNamed('Interface', p, 3, ListFromConcat(p[1], p[5])) |
if self.parse_debug: DumpReduction('interface_block', p) |
+ def p_interface_error(self, p): |
+ """interface_block : modifiers INTERFACE error '{' interface_list '}' ';'""" |
+ p[0] = [] |
+ |
def p_interface_list(self, p): |
"""interface_list : member_function ';' interface_list |
| """ |
@@ -750,9 +771,6 @@ |
p[0] = ListFromConcat(p[1], p[3]) |
if self.parse_debug: DumpReduction('interface_list', p) |
- def p_interface_error(self, p): |
- """interface_list : error interface_list""" |
- p[0] = p[2] |
# |
# Struct |
@@ -766,15 +784,17 @@ |
p[0] = self.BuildNamed('Struct', p, 3, children) |
if self.parse_debug: DumpReduction('struct_block', p) |
+ # Recover from struct error and continue parsing at the next top match. |
+ def p_struct_error(self, p): |
+ """enum_block : modifiers STRUCT error '{' struct_list '}' ';'""" |
+ p[0] = [] |
+ |
def p_struct_list(self, p): |
"""struct_list : member_attribute ';' struct_list |
| member_function ';' struct_list |
|""" |
if len(p) > 1: p[0] = ListFromConcat(p[1], p[3]) |
- def p_struct_error(self, p): |
- """struct_list : error struct_list""" |
- p[0] = p[2] |
# |
# Parser Errors |
@@ -1103,6 +1123,60 @@ |
InfoOut.Log("Passed namespace test.") |
return errs |
+ |
+ |
+def FindVersionError(releases, node): |
+ err_cnt = 0 |
+ if node.IsA('Interface', 'Struct'): |
+ comment_list = [] |
+ comment = node.GetOneOf('Comment') |
+ if comment: |
+ print comment.GetName() |
+ if comment and comment.GetName()[:4] == 'REL:': |
+ comment_list = comment.GetName()[5:].strip().split(' ') |
+ print comment_list |
+ |
+ if len(comment_list) != len(releases): |
+ node.Error("Mismatch size of releases: %s vs %s." % ( |
+ comment_list, releases)) |
+ err_cnt += 1 |
+ else: |
+ first_list = [node.first_release[rel] for rel in releases] |
+ if first_list != comment_list: |
+ node.Error("Mismatch in releases: %s vs %s." % ( |
+ comment_list, first_list)) |
+ err_cnt += 1 |
+ |
+ for child in node.GetChildren(): |
+ err_cnt += FindVersionError(releases, child) |
+ return err_cnt |
+ |
+ |
+def TestVersionFiles(filter): |
+ idldir = os.path.split(sys.argv[0])[0] |
+ idldir = os.path.join(idldir, 'test_version', '*.idl') |
+ filenames = glob.glob(idldir) |
+ testnames = [] |
+ |
+ for filename in filenames: |
+ if filter and filename not in filter: continue |
+ testnames.append(filename) |
+ |
+ # If we have no files to test, then skip this test |
+ if not testnames: |
+ InfoOut.Log('No files to test for version.') |
+ return 0 |
+ |
+ ast = ParseFiles(testnames) |
+ errs = FindVersionError(ast.releases, ast) |
+ |
+ if errs: |
+ ErrOut.Log("Failed version test.") |
+ else: |
+ InfoOut.Log("Passed version test.") |
+ return errs |
+ |
+ |
default_dirs = ['.', 'trusted', 'dev', 'private'] |
def ParseFiles(filenames): |
parser = IDLParser() |
@@ -1140,6 +1214,7 @@ |
if GetOption('test'): |
errs = TestErrorFiles(filenames) |
errs = TestNamespaceFiles(filenames) |
+ errs = TestVersionFiles(filenames) |
if errs: |
ErrOut.Log("Parser failed with %d errors." % errs) |
return -1 |
@@ -1156,3 +1231,4 @@ |
if __name__ == '__main__': |
sys.exit(Main(sys.argv[1:])) |
+ |