Skip to content

Commit

Permalink
idl parser: Update IDL parser to accept interface mixin
Browse files Browse the repository at this point in the history
interface mixin is a new IDL feature, and has a new grammar definition.
This CL updates IDL parser to accept it.
https://heycam.github.io/webidl/#idl-interface-mixins

Bug: 781257
Change-Id: Ibb771007c9147cf868995c80db8afc4ca43b9a74
Reviewed-on: https://chromium-review.googlesource.com/954763
Commit-Queue: Hitoshi Yoshida <peria@chromium.org>
Reviewed-by: Kenichi Ishibashi <bashi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#541753}
  • Loading branch information
peria committed Mar 8, 2018
1 parent acf8568 commit ec53e05
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 19 deletions.
1 change: 1 addition & 0 deletions tools/idl_parser/idl_lexer.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ class IDLLexer(object):
'legacycaller' : 'LEGACYCALLER',
'long' : 'LONG',
'maplike': 'MAPLIKE',
'mixin': 'MIXIN',
'namespace' : 'NAMESPACE',
'Nan' : 'NAN',
'null' : 'NULL',
Expand Down
59 changes: 43 additions & 16 deletions tools/idl_parser/idl_parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,7 @@ def p_Definitions(self, p):
p[0] = ListFromConcat(p[2], p[3])

def p_Definition(self, p):
"""Definition : CallbackOrInterface
"""Definition : CallbackOrInterfaceOrMixin
| Namespace
| Partial
| Dictionary
Expand All @@ -267,28 +267,32 @@ def p_DefinitionError(self, p):
"""Definition : error ';'"""
p[0] = self.BuildError(p, 'Definition')

def p_CallbackOrInterface(self, p):
"""CallbackOrInterface : CALLBACK CallbackRestOrInterface
| Interface"""
if len(p) > 2:
if p[2].GetClass() != 'Callback':
p[2].AddChildren(self.BuildTrue('CALLBACK'))
p[0] = p[2]
else:
p[0] = p[1]
def p_CallbackOrInterfaceOrMixin(self, p):
"""CallbackOrInterfaceOrMixin : CALLBACK CallbackRestOrInterface
| INTERFACE InterfaceOrMixin"""
p[0] = p[2]

def p_CallbackRestOrInterface(self, p):
"""CallbackRestOrInterface : CallbackRest
| Interface"""
| INTERFACE InterfaceRest"""
if len(p) < 3:
p[0] = p[1]
else:
p[2].AddChildren(self.BuildTrue('CALLBACK'))
p[0] = p[2]

def p_InterfaceOrMixin(self, p):
"""InterfaceOrMixin : InterfaceRest
| MixinRest"""
p[0] = p[1]

def p_Interface(self, p):
"""Interface : INTERFACE identifier Inheritance '{' InterfaceMembers '}' ';'"""
p[0] = self.BuildNamed('Interface', p, 2, ListFromConcat(p[3], p[5]))
def p_InterfaceRest(self, p):
"""InterfaceRest : identifier Inheritance '{' InterfaceMembers '}' ';'"""
p[0] = self.BuildNamed('Interface', p, 1, ListFromConcat(p[2], p[4]))

# Error recovery for interface.
def p_InterfaceError(self, p):
"""Interface : INTERFACE identifier Inheritance '{' error"""
def p_InterfaceRestError(self, p):
"""InterfaceRest : identifier Inheritance '{' error"""
p[0] = self.BuildError(p, 'Interface')

def p_Partial(self, p):
Expand Down Expand Up @@ -337,6 +341,29 @@ def p_InterfaceMember(self, p):
| ReadWriteSetlike"""
p[0] = p[1]

def p_MixinRest(self, p):
"""MixinRest : MIXIN identifier '{' MixinMembers '}' ';'"""
p[0] = self.BuildNamed('InterfaceMixin', p, 2, p[4])

def p_MixinMembers(self, p):
"""MixinMembers : ExtendedAttributeList MixinMember MixinMembers
|"""
if len(p) > 1:
p[2].AddChildren(p[1])
p[0] = ListFromConcat(p[2], p[3])

# Error recovery for InterfaceMembers
def p_MixinMembersError(self, p):
"""MixinMembers : error"""
p[0] = self.BuildError(p, 'MixinMembers')

def p_MixinMember(self, p):
"""MixinMember : Const
| Operation
| Stringifier
| ReadonlyMember"""
p[0] = p[1]

def p_Dictionary(self, p):
"""Dictionary : DICTIONARY identifier Inheritance '{' DictionaryMembers '}' ';'"""
p[0] = self.BuildNamed('Dictionary', p, 2, ListFromConcat(p[3], p[5]))
Expand Down
6 changes: 3 additions & 3 deletions tools/idl_parser/idl_parser_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def setUp(self):
os.path.join(os.path.dirname(__file__), 'test_parser'))
self.filenames = glob.glob('%s/*_web.idl' % test_dir)

def _TestNode(self, node):
def _TestNode(self, node, filepath):
comments = node.GetListOf('SpecialComment')
for comment in comments:
check, value = ParseCommentTest(comment.GetName())
Expand All @@ -37,7 +37,7 @@ def _TestNode(self, node):
if check == 'TREE':
quick = '\n'.join(node.Tree())
lineno = node.GetProperty('LINENO')
msg = 'Mismatched tree at line %d:' % lineno
msg = 'Mismatched tree at line %d in %s:' % (lineno, filepath)
msg += '\n\n[EXPECTED]\n%s\n\n[ACTUAL]\n%s\n' % (value, quick)
self.assertEqual(value, quick, msg)

Expand All @@ -49,7 +49,7 @@ def testExpectedNodes(self):
filename)

for node in filenode.GetChildren():
self._TestNode(node)
self._TestNode(node, filename)


class TestImplements(unittest.TestCase):
Expand Down
1 change: 1 addition & 0 deletions tools/idl_parser/test_lexer/keywords.in
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ ITERABLE iterable
LEGACYCALLER legacycaller
LONG long
MAPLIKE maplike
MIXIN mixin
NAN Nan
NULL null
OBJECT object
Expand Down
39 changes: 39 additions & 0 deletions tools/idl_parser/test_parser/interface_web.idl
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,45 @@ partial interface MyIFacePartial { };
/** ERROR Unexpected ":" after identifier "MyIFaceInherit". */
partial interface MyIFaceInherit : Foo {};

/** TREE
*InterfaceMixin(IFaceMixin)
*/
interface mixin IFaceMixin {};

/** ERROR Unexpected ":" after identifier "IFaceMixinInherit". */
interface mixin IFaceMixinInherit : Foo {};

/** ERROR Unexpected keyword "mixin" after keyword "interface". */
partial interface mixin PartialIFaceMixin {};

/** TREE
*InterfaceMixin(IFaceMixin)
* Error(Unexpected keyword "static" after "{".)
*/
interface mixin IFaceMixin {
static attribute integer staticAttribute;
};

/** TREE
*InterfaceMixin(IFaceMixin)
* Const(pi)
* PrimitiveType(double)
* Value() = "3.14159"
* Operation(foo)
* Arguments()
* Type()
* PrimitiveType(void)
* Attribute(bar)
* READONLY: True
* Type()
* StringType(DOMString)
*/
interface mixin IFaceMixin {
const double pi = 3.14159;
void foo();
readonly attribute DOMString bar;
};

/** TREE
*Interface(MyIFaceMissingArgument)
* Operation(foo)
Expand Down

0 comments on commit ec53e05

Please sign in to comment.