2 # Copyright (c) 2013 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.
6 """ Parser for PPAPI IDL """
11 # The parser is uses the PLY yacc library to build a set of parsing rules based
14 # WebIDL, and WebIDL grammar can be found at:
15 # http://heycam.github.io/webidl/
16 # PLY can be found at:
17 # http://www.dabeaz.com/ply/
19 # The parser generates a tree by recursively matching sets of items against
20 # defined patterns. When a match is made, that set of items is reduced
21 # to a new item. The new item can provide a match for parent patterns.
22 # In this way an AST is built (reduced) depth first.
26 # Disable check for line length and Member as Function due to how grammar rules
27 # are defined with PLY
29 # pylint: disable=R0201
30 # pylint: disable=C0301
34 from idl_ppapi_lexer
import IDLPPAPILexer
35 from idl_parser
import IDLParser
, ListFromConcat
, ParseFile
36 from idl_node
import IDLNode
38 class IDLPPAPIParser(IDLParser
):
40 # We force all input files to start with two comments. The first comment is a
41 # Copyright notice followed by a file comment and finally by file level
44 # [0] Insert a TOP definition for Copyright and Comments
46 """Top : COMMENT COMMENT Definitions"""
47 Copyright
= self
.BuildComment('Copyright', p
, 1)
48 Filedoc
= self
.BuildComment('Comment', p
, 2)
49 p
[0] = ListFromConcat(Copyright
, Filedoc
, p
[3])
52 #The parser is based on the WebIDL standard. See:
53 # http://heycam.github.io/webidl/#idl-grammar
56 def p_Definitions(self
, p
):
57 """Definitions : ExtendedAttributeList Definition Definitions
60 p
[2].AddChildren(p
[1])
61 p
[0] = ListFromConcat(p
[2], p
[3])
63 # [2] Add INLINE definition
64 def p_Definition(self
, p
):
65 """Definition : CallbackOrInterface
77 def p_Inline(self
, p
):
80 name
= self
.BuildAttribute('NAME', words
[1])
81 lines
= p
[1].split('\n')
82 value
= self
.BuildAttribute('VALUE', '\n'.join(lines
[1:-1]) + '\n')
83 children
= ListFromConcat(name
, value
)
84 p
[0] = self
.BuildProduction('Inline', p
, 1, children
)
89 # A label is a special kind of enumeration which allows us to go from a
90 # set of version numbrs to releases
93 """Label : LABEL identifier '{' LabelList '}' ';'"""
94 p
[0] = self
.BuildNamed('Label', p
, 2, p
[4])
96 def p_LabelList(self
, p
):
97 """LabelList : identifier '=' float LabelCont"""
98 val
= self
.BuildAttribute('VALUE', p
[3])
99 label
= self
.BuildNamed('LabelItem', p
, 1, val
)
100 p
[0] = ListFromConcat(label
, p
[4])
102 def p_LabelCont(self
, p
):
103 """LabelCont : ',' LabelList
108 def p_LabelContError(self
, p
):
109 """LabelCont : error LabelCont"""
112 # [5.1] Add "struct" style interface
113 def p_Struct(self
, p
):
114 """Struct : STRUCT identifier Inheritance '{' StructMembers '}' ';'"""
115 p
[0] = self
.BuildNamed('Struct', p
, 2, ListFromConcat(p
[3], p
[5]))
117 def p_StructMembers(self
, p
):
118 """StructMembers : StructMember StructMembers
121 p
[0] = ListFromConcat(p
[1], p
[2])
123 def p_StructMember(self
, p
):
124 """StructMember : ExtendedAttributeList Type identifier ';'"""
125 p
[0] = self
.BuildNamed('Member', p
, 3, ListFromConcat(p
[1], p
[2]))
127 def p_Typedef(self
, p
):
128 """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
129 p
[0] = self
.BuildNamed('Typedef', p
, 4, ListFromConcat(p
[2], p
[3]))
131 def p_TypedefFunc(self
, p
):
132 """Typedef : TYPEDEF ExtendedAttributeListNoComments ReturnType identifier '(' ArgumentList ')' ';'"""
133 args
= self
.BuildProduction('Arguments', p
, 5, p
[6])
134 p
[0] = self
.BuildNamed('Callback', p
, 4, ListFromConcat(p
[2], p
[3], args
))
136 def p_ConstValue(self
, p
):
137 """ConstValue : integer
138 | integer LSHIFT integer
139 | integer RSHIFT integer"""
142 val
= "%s %s %s" % (p
[1], p
[2], p
[3])
143 p
[0] = ListFromConcat(self
.BuildAttribute('TYPE', 'integer'),
144 self
.BuildAttribute('VALUE', val
))
146 def p_ConstValueStr(self
, p
):
147 """ConstValue : string"""
148 p
[0] = ListFromConcat(self
.BuildAttribute('TYPE', 'string'),
149 self
.BuildAttribute('VALUE', p
[1]))
151 # Boolean & Float Literals area already BuildAttributes
152 def p_ConstValueLiteral(self
, p
):
153 """ConstValue : FloatLiteral
157 def p_EnumValueList(self
, p
):
158 """EnumValueList : EnumValue EnumValues"""
159 p
[0] = ListFromConcat(p
[1], p
[2])
161 def p_EnumValues(self
, p
):
162 """EnumValues : ',' EnumValue EnumValues
165 p
[0] = ListFromConcat(p
[2], p
[3])
167 def p_EnumValue(self
, p
):
168 """EnumValue : ExtendedAttributeList identifier
169 | ExtendedAttributeList identifier '=' ConstValue"""
170 p
[0] = self
.BuildNamed('EnumItem', p
, 2, p
[1])
172 p
[0].AddChildren(p
[4])
174 # Omit PromiseType, as it is a JS type.
175 def p_NonAnyType(self
, p
):
176 """NonAnyType : PrimitiveType TypeSuffix
177 | identifier TypeSuffix
178 | SEQUENCE '<' Type '>' Null"""
179 IDLParser
.p_NonAnyType(self
, p
)
181 def p_PrimitiveType(self
, p
):
182 """PrimitiveType : IntegerType
183 | UnsignedIntegerType
187 if type(p
[1]) == str:
188 p
[0] = self
.BuildNamed('PrimitiveType', p
, 1)
192 def p_PointerType(self
, p
):
193 """PointerType : STR_T
200 def p_HandleType(self
, p
):
201 """HandleType : HANDLE_T
205 def p_FloatType(self
, p
):
206 """FloatType : FLOAT_T
210 def p_UnsignedIntegerType(self
, p
):
211 """UnsignedIntegerType : UINT8_T
218 def p_IntegerType(self
, p
):
219 """IntegerType : CHAR
226 # These targets are no longer used
227 def p_OptionalLong(self
, p
):
231 def p_UnrestrictedFloatType(self
, p
):
239 def p_PromiseType(self
, p
):
245 # [ identifier ( ArgumentList )]
246 # [ identifier ( ValueList )]
247 # [ identifier = identifier ]
248 # [ identifier = ( IdentifierList )]
249 # [ identifier = ConstValue ]
250 # [ identifier = identifier ( ArgumentList )]
251 # [51] map directly to 74-77
252 # [52-54, 56] are unsupported
253 def p_ExtendedAttribute(self
, p
):
254 """ExtendedAttribute : ExtendedAttributeNoArgs
255 | ExtendedAttributeArgList
256 | ExtendedAttributeValList
257 | ExtendedAttributeIdent
258 | ExtendedAttributeIdentList
259 | ExtendedAttributeIdentConst
260 | ExtendedAttributeNamedArgList"""
263 def p_ExtendedAttributeValList(self
, p
):
264 """ExtendedAttributeValList : identifier '(' ValueList ')'"""
265 arguments
= self
.BuildProduction('Values', p
, 2, p
[3])
266 p
[0] = self
.BuildNamed('ExtAttribute', p
, 1, arguments
)
268 def p_ValueList(self
, p
):
269 """ValueList : ConstValue ValueListCont"""
270 p
[0] = ListFromConcat(p
[1], p
[2])
272 def p_ValueListCont(self
, p
):
273 """ValueListCont : ValueList
278 def p_ExtendedAttributeIdentConst(self
, p
):
279 """ExtendedAttributeIdentConst : identifier '=' ConstValue"""
280 p
[0] = self
.BuildNamed('ExtAttribute', p
, 1, p
[3])
283 def __init__(self
, lexer
, verbose
=False, debug
=False, mute_error
=False):
284 IDLParser
.__init
__(self
, lexer
, verbose
, debug
, mute_error
)
289 parser
= IDLPPAPIParser(IDLPPAPILexer())
292 for filename
in argv
:
293 filenode
= ParseFile(parser
, filename
)
295 errors
+= filenode
.GetProperty('ERRORS')
296 nodes
.append(filenode
)
298 ast
= IDLNode('AST', '__AST__', 0, 0, nodes
)
300 print '\n'.join(ast
.Tree(accept_props
=['PROD', 'TYPE', 'VALUE']))
302 print '\nFound %d errors.\n' % errors
308 if __name__
== '__main__':
309 sys
.exit(main(sys
.argv
[1:]))