• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
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.
5
6""" Parser for PPAPI IDL """
7
8#
9# IDL Parser
10#
11# The parser is uses the PLY yacc library to build a set of parsing rules based
12# on WebIDL.
13#
14# WebIDL, and WebIDL grammar can be found at:
15#   http://dev.w3.org/2006/webapi/WebIDL/
16# PLY can be found at:
17#   http://www.dabeaz.com/ply/
18#
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.
23#
24
25#
26# Disable check for line length and Member as Function due to how grammar rules
27# are defined with PLY
28#
29# pylint: disable=R0201
30# pylint: disable=C0301
31
32import sys
33
34from idl_ppapi_lexer import IDLPPAPILexer
35from idl_parser import IDLParser, ListFromConcat, ParseFile
36from idl_node import IDLNode
37
38class IDLPPAPIParser(IDLParser):
39#
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
42# productions.
43#
44  # [0] Insert a TOP definition for Copyright and Comments
45  def p_Top(self, p):
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])
50
51#
52#The parser is based on the WebIDL standard.  See:
53# http://www.w3.org/TR/WebIDL/#idl-grammar
54#
55  # [1]
56  def p_Definitions(self, p):
57    """Definitions : ExtendedAttributeList Definition Definitions
58           | """
59    if len(p) > 1:
60      p[2].AddChildren(p[1])
61      p[0] = ListFromConcat(p[2], p[3])
62
63      # [2] Add INLINE definition
64  def p_Definition(self, p):
65    """Definition : CallbackOrInterface
66                  | Struct
67                  | Partial
68                  | Dictionary
69                  | Exception
70                  | Enum
71                  | Typedef
72                  | ImplementsStatement
73                  | Label
74                  | Inline"""
75    p[0] = p[1]
76
77  def p_Inline(self, p):
78    """Inline : INLINE"""
79    words = p[1].split()
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)
85
86#
87# Label
88#
89# A label is a special kind of enumeration which allows us to go from a
90# set of version numbrs to releases
91#
92  def p_Label(self, p):
93    """Label : LABEL identifier '{' LabelList '}' ';'"""
94    p[0] = self.BuildNamed('Label', p, 2, p[4])
95
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])
101
102  def p_LabelCont(self, p):
103    """LabelCont : ',' LabelList
104                 |"""
105    if len(p) > 1:
106      p[0] = p[2]
107
108  def p_LabelContError(self, p):
109    """LabelCont : error LabelCont"""
110    p[0] = p[2]
111
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]))
116
117  def p_StructMembers(self, p):
118    """StructMembers : StructMember StructMembers
119                     |"""
120    if len(p) > 1:
121      p[0] = ListFromConcat(p[1], p[2])
122
123  def p_StructMember(self, p):
124    """StructMember : ExtendedAttributeList Type identifier ';'"""
125    p[0] = self.BuildNamed('Member', p, 3, ListFromConcat(p[1], p[2]))
126
127  # [24]
128  def p_Typedef(self, p):
129    """Typedef : TYPEDEF ExtendedAttributeListNoComments Type identifier ';'"""
130    p[0] = self.BuildNamed('Typedef', p, 4, ListFromConcat(p[2], p[3]))
131
132  # [24.1]
133  def p_TypedefFunc(self, p):
134    """Typedef : TYPEDEF ExtendedAttributeListNoComments ReturnType identifier '(' ArgumentList ')' ';'"""
135    args = self.BuildProduction('Arguments', p, 5, p[6])
136    p[0] = self.BuildNamed('Callback', p, 4, ListFromConcat(p[2], p[3], args))
137
138  # [27]
139  def p_ConstValue(self, p):
140    """ConstValue : integer
141                  | integer LSHIFT integer
142                  | integer RSHIFT integer"""
143    val = str(p[1])
144    if len(p) > 2:
145      val = "%s %s %s" % (p[1], p[2], p[3])
146    p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'integer'),
147                          self.BuildAttribute('VALUE', val))
148
149  def p_ConstValueStr(self, p):
150    """ConstValue : string"""
151    p[0] = ListFromConcat(self.BuildAttribute('TYPE', 'string'),
152                          self.BuildAttribute('VALUE', p[1]))
153
154  # Boolean & Float Literals area already BuildAttributes
155  def p_ConstValueLiteral(self, p):
156    """ConstValue : FloatLiteral
157                  | BooleanLiteral """
158    p[0] = p[1]
159
160  # [21]
161  def p_EnumValueList(self, p):
162    """EnumValueList : EnumValue EnumValues"""
163    p[0] = ListFromConcat(p[1], p[2])
164
165  # [22]
166  def p_EnumValues(self, p):
167    """EnumValues : ',' EnumValue EnumValues
168                  |"""
169    if len(p) > 1:
170      p[0] = ListFromConcat(p[2], p[3])
171
172  def p_EnumValue(self, p):
173    """EnumValue : ExtendedAttributeList identifier
174                 | ExtendedAttributeList identifier '=' ConstValue"""
175    p[0] = self.BuildNamed('EnumItem', p, 2, p[1])
176    if len(p) > 3:
177      p[0].AddChildren(p[4])
178
179  def p_PrimitiveType(self, p):
180    """PrimitiveType : IntegerType
181                     | UnsignedIntegerType
182                     | FloatType
183                     | HandleType
184                     | PointerType"""
185    if type(p[1]) == str:
186      p[0] = self.BuildNamed('PrimitiveType', p, 1)
187    else:
188      p[0] = p[1]
189
190  def p_PointerType(self, p):
191    """PointerType : STR_T
192                   | MEM_T
193                   | CSTR_T
194                   | INTERFACE_T
195                   | NULL"""
196    p[0] = p[1]
197
198  def p_HandleType(self, p):
199    """HandleType : HANDLE_T
200                  | PP_FILEHANDLE"""
201    p[0] = p[1]
202
203  # [66]
204  def p_FloatType(self, p):
205    """FloatType : FLOAT_T
206                 | DOUBLE_T"""
207    p[0] = p[1]
208
209  # [67]
210  def p_UnsignedIntegerType(self, p):
211    """UnsignedIntegerType : UINT8_T
212                           | UINT16_T
213                           | UINT32_T
214                           | UINT64_T"""
215    p[0] = p[1]
216
217
218  # [68]
219  def p_IntegerType(self, p):
220    """IntegerType : CHAR
221                   | INT8_T
222                   | INT16_T
223                   | INT32_T
224                   | INT64_T"""
225    p[0] = p[1]
226
227  # These targets are no longer used
228  def p_OptionalLong(self, p):
229    """ """
230    pass
231
232  def p_UnrestrictedFloatType(self, p):
233    """ """
234    pass
235
236  def p_null(self, p):
237    """ """
238    pass
239
240  # We only support:
241  #    [ identifier ]
242  #    [ identifier = identifier ]
243  #    [ identifier ( ArgumentList )]
244  #    [ identifier ( ValueList )]
245  #    [ identifier = identifier ( ArgumentList )]
246  # [51] map directly to 74-77
247  # [52-54, 56] are unsupported
248  def p_ExtendedAttribute(self, p):
249    """ExtendedAttribute : ExtendedAttributeNoArgs
250                         | ExtendedAttributeArgList
251                         | ExtendedAttributeValList
252                         | ExtendedAttributeIdent
253                         | ExtendedAttributeIdentConst
254                         | ExtendedAttributeNamedArgList"""
255    p[0] = p[1]
256
257  def p_ExtendedAttributeValList(self, p):
258    """ExtendedAttributeValList : identifier '(' ValueList ')'"""
259    arguments = self.BuildProduction('Values', p, 2, p[3])
260    p[0] = self.BuildNamed('ExtAttribute', p, 1, arguments)
261
262  def p_ValueList(self, p):
263    """ValueList : ConstValue ValueListCont"""
264    p[0] = ListFromConcat(p[1], p[2])
265
266  def p_ValueListCont(self, p):
267    """ValueListCont : ValueList
268                     |"""
269    if len(p) > 1:
270      p[0] = p[1]
271
272  # [76]
273  def p_ExtendedAttributeIdentConst(self, p):
274    """ExtendedAttributeIdentConst : identifier '=' ConstValue"""
275    p[0] = self.BuildNamed('ExtAttribute', p, 1, p[3])
276
277
278  def __init__(self, lexer, verbose=False, debug=False, mute_error=False):
279    IDLParser.__init__(self, lexer, verbose, debug, mute_error)
280
281
282def main(argv):
283  nodes = []
284  parser = IDLPPAPIParser(IDLPPAPILexer())
285  errors = 0
286
287  for filename in argv:
288    filenode = ParseFile(parser, filename)
289    if filenode:
290      errors += filenode.GetProperty('ERRORS')
291      nodes.append(filenode)
292
293  ast = IDLNode('AST', '__AST__', 0, 0, nodes)
294
295  print '\n'.join(ast.Tree(accept_props=['PROD', 'TYPE', 'VALUE']))
296  if errors:
297    print '\nFound %d errors.\n' % errors
298
299
300  return errors
301
302
303if __name__ == '__main__':
304  sys.exit(main(sys.argv[1:]))
305