Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(651)

Side by Side Diff: ppapi/generators/idl_parser.py

Issue 7272043: Update Lexer/Parser to support '#inline' and 'label' (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « ppapi/generators/idl_lexer.py ('k') | ppapi/generators/test_cgen/interface.idl » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/python 1 #!/usr/bin/python
2 # 2 #
3 # Copyright (c) 2011 The Chromium Authors. All rights reserved. 3 # Copyright (c) 2011 The Chromium Authors. All rights reserved.
4 # Use of this source code is governed by a BSD-style license that can be 4 # Use of this source code is governed by a BSD-style license that can be
5 # found in the LICENSE file. 5 # found in the LICENSE file.
6 6
7 """ Parser for PPAPI IDL """ 7 """ Parser for PPAPI IDL """
8 8
9 # 9 #
10 # IDL Parser 10 # IDL Parser
(...skipping 11 matching lines...) Expand all
22 # to a new item. The new item can provide a match for parent patterns. 22 # to a new item. The new item can provide a match for parent patterns.
23 # In this way an AST is built (reduced) depth first. 23 # In this way an AST is built (reduced) depth first.
24 24
25 25
26 import getopt 26 import getopt
27 import glob 27 import glob
28 import os.path 28 import os.path
29 import re 29 import re
30 import sys 30 import sys
31 31
32 from idl_ast import IDLAst
32 from idl_log import ErrOut, InfoOut, WarnOut 33 from idl_log import ErrOut, InfoOut, WarnOut
33 from idl_lexer import IDLLexer 34 from idl_lexer import IDLLexer
34 from idl_node import IDLAttribute, IDLAst, IDLNode 35 from idl_node import IDLAttribute, IDLFile, IDLNode
35 from idl_option import GetOption, Option, ParseOptions 36 from idl_option import GetOption, Option, ParseOptions
36 37
37 from ply import lex 38 from ply import lex
38 from ply import yacc 39 from ply import yacc
39 40
40 Option('build_debug', 'Debug tree building.') 41 Option('build_debug', 'Debug tree building.')
41 Option('parse_debug', 'Debug parse reduction steps.') 42 Option('parse_debug', 'Debug parse reduction steps.')
42 Option('token_debug', 'Debug token generation.') 43 Option('token_debug', 'Debug token generation.')
43 Option('dump_tree', 'Dump the tree.') 44 Option('dump_tree', 'Dump the tree.')
44 Option('srcdir', 'Working directory', default='.') 45 Option('srcroot', 'Working directory.', default='')
45 46 Option('wcomment', 'Disable warning for missing comment.')
47 Option('wenum', 'Disable warning for missing enum value.')
46 48
47 # 49 #
48 # ERROR_REMAP 50 # ERROR_REMAP
49 # 51 #
50 # Maps the standard error formula into a more friendly error message. 52 # Maps the standard error formula into a more friendly error message.
51 # 53 #
52 ERROR_REMAP = { 54 ERROR_REMAP = {
53 'Unexpected ")" after "(".' : 'Empty argument list.', 55 'Unexpected ")" after "(".' : 'Empty argument list.',
54 'Unexpected ")" after ",".' : 'Missing argument.', 56 'Unexpected ")" after ",".' : 'Missing argument.',
55 'Unexpected "}" after ",".' : 'Trailing comma in block.', 57 'Unexpected "}" after ",".' : 'Trailing comma in block.',
56 'Unexpected "}" after "{".' : 'Unexpected empty block.', 58 'Unexpected "}" after "{".' : 'Unexpected empty block.',
57 'Unexpected comment "/*" after "}".' : 'Unexpected trailing comment.', 59 'Unexpected comment after "}".' : 'Unexpected trailing comment.',
58 'Unexpected "{" after keyword "enum".' : 'Enum missing name.', 60 'Unexpected "{" after keyword "enum".' : 'Enum missing name.',
59 'Unexpected "{" after keyword "struct".' : 'Struct missing name.', 61 'Unexpected "{" after keyword "struct".' : 'Struct missing name.',
60 'Unexpected "{" after keyword "interface".' : 'Interface missing name.', 62 'Unexpected "{" after keyword "interface".' : 'Interface missing name.',
61 } 63 }
62 64
63 # DumpReduction 65 # DumpReduction
64 # 66 #
65 # Prints out the set of items which matched a particular pattern and the 67 # Prints out the set of items which matched a particular pattern and the
66 # new item or set it was reduced to. 68 # new item or set it was reduced to.
67 def DumpReduction(cls, p): 69 def DumpReduction(cls, p):
68 if p[0] is None: 70 if p[0] is None:
69 InfoOut.Log("OBJ: %s(%d) - None\n" % (cls, len(p))) 71 InfoOut.Log("OBJ: %s(%d) - None\n" % (cls, len(p)))
72 InfoOut.Log(" [%s]\n" % [str(x) for x in p[1:]])
70 else: 73 else:
71 out = "" 74 out = ""
72 for index in range(len(p) - 1): 75 for index in range(len(p) - 1):
73 out += " >%s< " % str(p[index + 1]) 76 out += " >%s< " % str(p[index + 1])
74 InfoOut.Log("OBJ: %s(%d) - %s : %s\n" % (cls, len(p), str(p[0]), out)) 77 InfoOut.Log("OBJ: %s(%d) - %s : %s\n" % (cls, len(p), str(p[0]), out))
75 78
76 79
77 # CopyToList 80 # CopyToList
78 # 81 #
79 # Takes an input item, list, or None, and returns a new list of that set. 82 # Takes an input item, list, or None, and returns a new list of that set.
(...skipping 23 matching lines...) Expand all
103 106
104 107
105 # TokenTypeName 108 # TokenTypeName
106 # 109 #
107 # Generate a string which has the type and value of the token. 110 # Generate a string which has the type and value of the token.
108 def TokenTypeName(t): 111 def TokenTypeName(t):
109 if t.type == 'SYMBOL': return 'symbol %s' % t.value 112 if t.type == 'SYMBOL': return 'symbol %s' % t.value
110 if t.type in ['HEX', 'INT', 'OCT', 'FLOAT']: 113 if t.type in ['HEX', 'INT', 'OCT', 'FLOAT']:
111 return 'value %s' % t.value 114 return 'value %s' % t.value
112 if t.type == 'STRING' : return 'string "%s"' % t.value 115 if t.type == 'STRING' : return 'string "%s"' % t.value
113 if t.type == 'COMMENT' : return 'comment "%s"' % t.value[:2] 116 if t.type == 'COMMENT' : return 'comment'
114 if t.type == t.value: return '"%s"' % t.value 117 if t.type == t.value: return '"%s"' % t.value
115 return 'keyword "%s"' % t.value 118 return 'keyword "%s"' % t.value
116 119
117 120
118 # StageResult
119 #
120 # The result object stores the result of parsing stage.
121 #
122 class StageResult(object):
123 def __init__(self, name, out, errs):
124 self.name = name
125 self.out = out
126 self.errs = errs
127
128
129 # 121 #
130 # IDL Parser 122 # IDL Parser
131 # 123 #
132 # The Parser inherits the from the Lexer to provide PLY with the tokenizing 124 # The Parser inherits the from the Lexer to provide PLY with the tokenizing
133 # definitions. Parsing patterns are encoded as function where p_<name> is 125 # definitions. Parsing patterns are encoded as function where p_<name> is
134 # is called any time a patern matching the function documentation is found. 126 # is called any time a patern matching the function documentation is found.
135 # Paterns are expressed in the form of: 127 # Paterns are expressed in the form of:
136 # """ <new item> : <item> .... 128 # """ <new item> : <item> ....
137 # | <item> ....""" 129 # | <item> ...."""
138 # 130 #
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
192 # ext_attr_list 184 # ext_attr_list
193 # attr_arg_list 185 # attr_arg_list
194 # *integer, value 186 # *integer, value
195 # *param_list 187 # *param_list
196 # *typeref 188 # *typeref
197 # 189 #
198 # top_list 190 # top_list
199 # describe_block 191 # describe_block
200 # describe_list 192 # describe_list
201 # enum_block 193 # enum_block
202 # enum_type 194 # enum_item
203 # interface_block 195 # interface_block
196 # member
197 # label_block
198 # label_item
204 # struct_block 199 # struct_block
205 # member 200 # member
206 # typedef_decl 201 # typedef_decl
207 # typedef_data 202 # typedef_data
208 # typedef_func 203 # typedef_func
209 # 204 #
210 # (* sub matches found at multiple levels and are not truly children of top) 205 # (* sub matches found at multiple levels and are not truly children of top)
211 # 206 #
212 # We force all input files to start with two comments. The first comment is a 207 # We force all input files to start with two comments. The first comment is a
213 # Copyright notice followed by a set of file wide Extended Attributes, followed 208 # Copyright notice followed by a set of file wide Extended Attributes, followed
214 # by the file comment and finally by file level patterns. 209 # by the file comment and finally by file level patterns.
215 # 210 #
216 # Find the Copyright, File comment, and optional file wide attributes. We 211 # Find the Copyright, File comment, and optional file wide attributes. We
217 # use a match with COMMENT instead of comments to force the token to be 212 # use a match with COMMENT instead of comments to force the token to be
218 # present. The extended attributes and the top_list become siblings which 213 # present. The extended attributes and the top_list become siblings which
219 # in turn are children of the file object created from the results of top. 214 # in turn are children of the file object created from the results of top.
220 def p_top(self, p): 215 def p_top(self, p):
221 """top : COMMENT COMMENT ext_attr_block top_list""" 216 """top : COMMENT COMMENT ext_attr_block top_list"""
222 217
223 Copyright = self.BuildProduction('Copyright', p, 1, None) 218 Copyright = self.BuildComment('Copyright', p, 1)
224 Filedoc = self.BuildProduction('Comment', p, 2, None) 219 Filedoc = self.BuildComment('Comment', p, 2)
225 220
226 p[0] = ListFromConcat(Copyright, Filedoc, p[3], p[4]) 221 p[0] = ListFromConcat(Copyright, Filedoc, p[3], p[4])
227 if self.parse_debug: DumpReduction('top', p) 222 if self.parse_debug: DumpReduction('top', p)
228 223
229 # Build a list of top level items. 224 # Build a list of top level items.
230 def p_top_list(self, p): 225 def p_top_list(self, p):
231 """top_list : describe_block top_list 226 """top_list : describe_block top_list
232 | enum_block top_list 227 | enum_block top_list
228 | inline top_list
233 | interface_block top_list 229 | interface_block top_list
230 | label_block top_list
234 | struct_block top_list 231 | struct_block top_list
235 | typedef_def top_list 232 | typedef_decl top_list
236 | """ 233 | """
237 if len(p) > 2: 234 if len(p) > 2:
238 p[0] = ListFromConcat(p[1], p[2]) 235 p[0] = ListFromConcat(p[1], p[2])
239 if self.parse_debug: DumpReduction('top_list', p) 236 if self.parse_debug: DumpReduction('top_list', p)
240 237
241 # Recover from error and continue parsing at the next top match. 238 # Recover from error and continue parsing at the next top match.
242 def p_top_error(self, p): 239 def p_top_error(self, p):
243 """top_list : error top_list""" 240 """top_list : error top_list"""
244 p[0] = p[2] 241 p[0] = p[2]
245 242
246 # 243 #
247 # Modifier List 244 # Modifier List
248 # 245 #
249 # 246 #
250 def p_modifiers(self, p): 247 def p_modifiers(self, p):
251 """modifiers : comments ext_attr_block""" 248 """modifiers : comments ext_attr_block"""
252 p[0] = ListFromConcat(p[1], p[2]) 249 p[0] = ListFromConcat(p[1], p[2])
253 if self.parse_debug: DumpReduction('modifiers', p) 250 if self.parse_debug: DumpReduction('modifiers', p)
254 251
255 # 252 #
256 # Comments 253 # Comments
257 # 254 #
258 # Comments are optional list of C style comment objects. Comments are returned 255 # Comments are optional list of C style comment objects. Comments are returned
259 # as a list or None. 256 # as a list or None.
260 # 257 #
261 def p_comments(self, p): 258 def p_comments(self, p):
262 """comments : COMMENT comments 259 """comments : COMMENT comments
263 | """ 260 | """
264 if len(p) > 1: 261 if len(p) > 1:
265 child = self.BuildProduction('Comment', p, 1, None) 262 child = self.BuildComment('Comment', p, 1)
266 p[0] = ListFromConcat(child, p[2]) 263 p[0] = ListFromConcat(child, p[2])
267 if self.parse_debug: DumpReduction('comments', p) 264 if self.parse_debug: DumpReduction('comments', p)
268 else: 265 else:
269 if self.parse_debug: DumpReduction('no comments', p) 266 if self.parse_debug: DumpReduction('no comments', p)
270 267
268
271 # 269 #
270 # Inline
271 #
272 # Inline blocks define option code to be emitted based on language tag,
273 # in the form of:
274 # #inline <LANGUAGE>
275 # <CODE>
276 # #endinl
277 #
278 def p_inline(self, p):
279 """inline : modifiers INLINE"""
280 words = p[2].split()
281 name = self.BuildAttribute('NAME', words[1])
282 lines = p[2].split('\n')
283 value = self.BuildAttribute('VALUE', '\n'.join(lines[1:-1]) + '\n')
284 children = ListFromConcat(name, value, p[1])
285 p[0] = self.BuildProduction('Inline', p, 2, children)
286 if self.parse_debug: DumpReduction('inline', p)
287
272 # Extended Attributes 288 # Extended Attributes
273 # 289 #
274 # Extended Attributes denote properties which will be applied to a node in the 290 # Extended Attributes denote properties which will be applied to a node in the
275 # AST. A list of extended attributes are denoted by a brackets '[' ... ']' 291 # AST. A list of extended attributes are denoted by a brackets '[' ... ']'
276 # enclosing a comma separated list of extended attributes in the form of: 292 # enclosing a comma separated list of extended attributes in the form of:
277 # 293 #
278 # Name 294 # Name
279 # Name=HEX | INT | OCT | FLOAT 295 # Name=HEX | INT | OCT | FLOAT
280 # Name="STRING" 296 # Name="STRING"
281 # Name=Function(arg ...) 297 # Name=Function(arg ...)
282 # TODO(noelallen) -Not currently supported: 298 # TODO(noelallen) -Not currently supported:
283 # ** Name(arg ...) ... 299 # ** Name(arg ...) ...
284 # ** Name=Scope::Value 300 # ** Name=Scope::Value
285 # 301 #
286 # Extended Attributes are returned as a list or None. 302 # Extended Attributes are returned as a list or None.
287 303
288 def p_ext_attr_block(self, p): 304 def p_ext_attr_block(self, p):
289 """ext_attr_block : '[' ext_attr_list ']' 305 """ext_attr_block : '[' ext_attr_list ']'
290 | """ 306 | """
291 if len(p) > 1: 307 if len(p) > 1:
292 p[0] = p[2] 308 p[0] = p[2]
293 if self.parse_debug: DumpReduction('ext_attr_block', p) 309 if self.parse_debug: DumpReduction('ext_attr_block', p)
294 else: 310 else:
295 if self.parse_debug: DumpReduction('no ext_attr_block', p) 311 if self.parse_debug: DumpReduction('no ext_attr_block', p)
296 312
297 def p_ext_attr_list(self, p): 313 def p_ext_attr_list(self, p):
298 """ext_attr_list : SYMBOL '=' value ext_attr_cont 314 """ext_attr_list : SYMBOL '=' SYMBOL ext_attr_cont
299 | SYMBOL '(' attr_arg_list ')' ext_attr_cont 315 | SYMBOL '=' value ext_attr_cont
300 | SYMBOL ext_attr_cont """ 316 | SYMBOL '=' SYMBOL param_list ext_attr_cont
301 if len(p) == 3: 317 | SYMBOL ext_attr_cont"""
302 p[0] = ListFromConcat(self.BuildExtAttribute(p[1], 'True'), p[2]) 318 # If there are 4 tokens plus a return slot, this must be in the form
319 # SYMBOL = SYMBOL|value ext_attr_cont
303 if len(p) == 5: 320 if len(p) == 5:
304 p[0] = ListFromConcat(self.BuildExtAttribute(p[1], p[3]), p[4]) 321 p[0] = ListFromConcat(self.BuildAttribute(p[1], p[3]), p[4])
305 if len(p) == 6: 322 # If there are 5 tokens plus a return slot, this must be in the form
306 p[0] = ListFromConcat(self.BuildExtAttribute(p[1], p[3]), p[5]) 323 # SYMBOL = SYMBOL (param_list) ext_attr_cont
324 elif len(p) == 6:
325 member = self.BuildNamed('Member', p, 3, [p[4]])
326 p[0] = ListFromConcat(self.BuildAttribute(p[1], member), p[5])
327 # Otherwise, this must be: SYMBOL ext_attr_cont
328 else:
329 p[0] = ListFromConcat(self.BuildAttribute(p[1], 'True'), p[2])
307 if self.parse_debug: DumpReduction('ext_attribute_list', p) 330 if self.parse_debug: DumpReduction('ext_attribute_list', p)
308 331
309 def p_ext_attr_cont(self, p): 332 def p_ext_attr_cont(self, p):
310 """ext_attr_cont : ',' ext_attr_list 333 """ext_attr_cont : ',' ext_attr_list
311 |""" 334 |"""
312 if len(p) > 1: p[0] = p[2] 335 if len(p) > 1: p[0] = p[2]
313 if self.parse_debug: DumpReduction('ext_attribute_cont', p) 336 if self.parse_debug: DumpReduction('ext_attribute_cont', p)
314 337
315 def p_attr_arg_list(self, p): 338 def p_ext_attr_func(self, p):
339 """ext_attr_list : SYMBOL '(' attr_arg_list ')' ext_attr_cont"""
340 p[0] = ListFromConcat(self.BuildAttribute(p[1] + '()', p[3]), p[5])
341 if self.parse_debug: DumpReduction('attr_arg_func', p)
342
343 def p_ext_attr_arg_list(self, p):
316 """attr_arg_list : SYMBOL attr_arg_cont 344 """attr_arg_list : SYMBOL attr_arg_cont
317 | value attr_arg_cont """ 345 | value attr_arg_cont"""
318 p[0] = ','.join(ListFromConcat(p[1], p[2])) 346 p[0] = ListFromConcat(p[1], p[2])
319 if self.parse_debug: DumpReduction('attr_arg_list', p)
320 347
321 def p_attr_arg_cont(self, p): 348 def p_attr_arg_cont(self, p):
322 """attr_arg_cont : ',' attr_arg_list 349 """attr_arg_cont : ',' attr_arg_list
323 | """ 350 | """
351 if self.parse_debug: DumpReduction('attr_arg_cont', p)
324 if len(p) > 1: p[0] = p[2] 352 if len(p) > 1: p[0] = p[2]
325 if self.parse_debug: DumpReduction('attr_arg_cont', p)
326 353
327 def p_attr_arg_error(self, p): 354 def p_attr_arg_error(self, p):
328 """attr_arg_cont : error attr_arg_cont""" 355 """attr_arg_cont : error attr_arg_cont"""
329 p[0] = p[2] 356 p[0] = p[2]
330 if self.parse_debug: DumpReduction('attr_arg_error', p) 357 if self.parse_debug: DumpReduction('attr_arg_error', p)
331 358
332 359
333 # 360 #
334 # Describe 361 # Describe
335 # 362 #
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
368 """value : FLOAT 395 """value : FLOAT
369 | HEX 396 | HEX
370 | INT 397 | INT
371 | OCT 398 | OCT
372 | STRING""" 399 | STRING"""
373 p[0] = p[1] 400 p[0] = p[1]
374 if self.parse_debug: DumpReduction('value', p) 401 if self.parse_debug: DumpReduction('value', p)
375 402
376 def p_value_lshift(self, p): 403 def p_value_lshift(self, p):
377 """value : integer LSHIFT INT""" 404 """value : integer LSHIFT INT"""
378 p[0] = "(%s << %s)" % (p[1], p[3]) 405 p[0] = "%s << %s" % (p[1], p[3])
379 if self.parse_debug: DumpReduction('value', p) 406 if self.parse_debug: DumpReduction('value', p)
380 407
381 # Integers are numbers which may not be floats used in cases like array sizes. 408 # Integers are numbers which may not be floats used in cases like array sizes.
382 def p_integer(self, p): 409 def p_integer(self, p):
383 """integer : HEX 410 """integer : HEX
384 | INT 411 | INT
385 | OCT""" 412 | OCT"""
386 p[0] = p[1] 413 p[0] = p[1]
414 if self.parse_debug: DumpReduction('integer', p)
415
416 # Numbers are integers or floats.
417 def p_number(self, p):
418 """number : FLOAT
419 | HEX
420 | INT
421 | OCT"""
422 p[0] = p[1]
423 if self.parse_debug: DumpReduction('number', p)
424
425 def p_number_lshift(self, p):
426 """number : integer LSHIFT INT"""
427 p[0] = "%s << %s" % (p[1], p[3])
428 if self.parse_debug: DumpReduction('number_lshift', p)
429
430 #
431 # Array List
432 #
433 # Defined a list of array sizes (if any).
434 #
435 def p_arrays(self, p):
436 """arrays : '[' ']' arrays
437 | '[' integer ']' arrays
438 | """
439 # If there are 3 tokens plus a return slot it is an unsized array
440 if len(p) == 4:
441 array = self.BuildProduction('Array', p, 1)
442 p[0] = ListFromConcat(array, p[3])
443 # If there are 4 tokens plus a return slot it is a fixed array
444 elif len(p) == 5:
445 count = self.BuildAttribute('FIXED', p[2])
446 array = self.BuildProduction('Array', p, 2, [count])
447 p[0] = ListFromConcat(array, p[4])
448 # If there is only a return slot, do not fill it for this terminator.
449 elif len(p) == 1: return
450 if self.parse_debug: DumpReduction('arrays', p)
387 451
388 # 452 #
389 # Parameter List 453 # Parameter List
390 # 454 #
391 # A parameter list is a collection of arguments which are passed to a 455 # A parameter list is a collection of arguments which are passed to a
392 # function. 456 # function.
393 # 457 #
394 def p_param_list(self, p): 458 def p_param_list(self, p):
395 """param_list : param_item param_cont 459 """param_list : '(' param_item param_cont ')'
396 | """ 460 | '(' ')' """
397 if len(p) > 1: 461 if len(p) > 3:
398 args = ListFromConcat(p[1], p[2]) 462 args = ListFromConcat(p[2], p[3])
399 else: 463 else:
400 args = [] 464 args = []
401 p[0] = self.BuildProduction('Callspec', p, -1, args) 465 p[0] = self.BuildProduction('Callspec', p, 1, args)
402 if self.parse_debug: DumpReduction('param_list', p) 466 if self.parse_debug: DumpReduction('param_list', p)
403 467
404 def p_param_item(self, p): 468 def p_param_item(self, p):
405 """param_item : modifiers typeref SYMBOL param_cont""" 469 """param_item : modifiers SYMBOL arrays SYMBOL"""
406 children = ListFromConcat(p[1], p[2]) 470 typeref = self.BuildAttribute('TYPEREF', p[2])
407 param = self.BuildProduction('Param', p, 3, children) 471 children = ListFromConcat(p[1],typeref, p[3])
408 p[0] = ListFromConcat(param, p[4]) 472 p[0] = self.BuildNamed('Param', p, 4, children)
409 if self.parse_debug: DumpReduction('param_item', p) 473 if self.parse_debug: DumpReduction('param_item', p)
410 474
411 def p_param_cont(self, p): 475 def p_param_cont(self, p):
412 """param_cont : ',' param_item param_cont 476 """param_cont : ',' param_item param_cont
413 | """ 477 | """
414 if len(p) > 1: 478 if len(p) > 1:
415 p[0] = p[2] 479 p[0] = ListFromConcat(p[2], p[3])
416 if self.parse_debug: DumpReduction('param_cont', p) 480 if self.parse_debug: DumpReduction('param_cont', p)
417 481
418 def p_param_error(self, p): 482 def p_param_error(self, p):
419 """param_cont : error param_cont""" 483 """param_cont : error param_cont"""
420 p[0] = p[2] 484 p[0] = p[2]
421 485
422 #
423 # Typeref
424 #
425 # A typeref is a reference to a type definition. The type definition may
426 # be a built in such as int32_t or a defined type such as an enum, or
427 # struct, or typedef. Part of the reference to the type is how it is
428 # used, such as directly, a fixed size array, or unsized (pointer). The
429 # reference is reduced and becomes a property of the parent Node.
430 #
431 def p_typeref_data(self, p):
432 """typeref : SYMBOL typeref_arrays"""
433
434 Type = self.BuildExtAttribute('TYPEREF', p[1])
435 p[0] = ListFromConcat(Type, p[2])
436 if self.parse_debug: DumpReduction('typeref', p)
437
438 def p_typeref_arrays(self, p):
439 """typeref_arrays : '[' ']' typeref_arrays
440 | '[' integer ']' typeref_arrays
441 | """
442 if len(p) == 1: return
443 if len(p) == 5:
444 count = self.BuildExtAttribute('FIXED', p[2])
445 array = self.BuildProduction('Array', p, 2, ListFromConcat(p[4], count))
446 else:
447 array = self.BuildProduction('Array', p, 1, p[3])
448
449 p[0] = [array]
450 if self.parse_debug: DumpReduction('arrays', p)
451 486
452 # 487 #
453 # Typedef 488 # Typedef
454 # 489 #
455 # A typedef creates a new referencable type. The tyepdef can specify an array 490 # A typedef creates a new referencable type. The tyepdef can specify an array
456 # definition as well as a function declaration. 491 # definition as well as a function declaration.
457 # 492 #
458 def p_typedef_data(self, p): 493 def p_typedef_data(self, p):
459 """typedef_def : modifiers TYPEDEF typeref SYMBOL ';' """ 494 """typedef_decl : modifiers TYPEDEF SYMBOL SYMBOL ';' """
460 p[0] = self.BuildProduction('Typedef', p, 4, ListFromConcat(p[1], p[3])) 495 typeref = self.BuildAttribute('TYPEREF', p[3])
496 children = ListFromConcat(p[1], typeref)
497 p[0] = self.BuildNamed('Typedef', p, 4, children)
461 if self.parse_debug: DumpReduction('typedef_data', p) 498 if self.parse_debug: DumpReduction('typedef_data', p)
462 499
500 def p_typedef_array(self, p):
501 """typedef_decl : modifiers TYPEDEF SYMBOL arrays SYMBOL ';' """
502 typeref = self.BuildAttribute('TYPEREF', p[3])
503 children = ListFromConcat(p[1], typeref, p[4])
504 p[0] = self.BuildNamed('Typedef', p, 5, children)
505 if self.parse_debug: DumpReduction('typedef_array', p)
506
463 def p_typedef_func(self, p): 507 def p_typedef_func(self, p):
464 """typedef_def : modifiers TYPEDEF typeref SYMBOL '(' param_list ')' ';'""" 508 """typedef_decl : modifiers TYPEDEF SYMBOL SYMBOL param_list ';' """
465 children = ListFromConcat(p[1], p[3], p[6]) 509 typeref = self.BuildAttribute('TYPEREF', p[3])
466 p[0] = self.BuildProduction('Typedef', p, 4, children) 510 children = ListFromConcat(p[1], typeref, p[5])
511 p[0] = self.BuildNamed('Typedef', p, 4, children)
467 if self.parse_debug: DumpReduction('typedef_func', p) 512 if self.parse_debug: DumpReduction('typedef_func', p)
468 513
469 # 514 #
470 # Enumeration 515 # Enumeration
471 # 516 #
472 # An enumeration is a set of named integer constants. An enumeration 517 # An enumeration is a set of named integer constants. An enumeration
473 # is valid type which can be referenced in other definitions. 518 # is valid type which can be referenced in other definitions.
474 # 519 #
475 def p_enum_block(self, p): 520 def p_enum_block(self, p):
476 """enum_block : modifiers ENUM SYMBOL '{' enum_list '}' ';'""" 521 """enum_block : modifiers ENUM SYMBOL '{' enum_list '}' ';'"""
477 Type = self.BuildExtAttribute('TYPEREF', 'enum') 522 p[0] = self.BuildNamed('Enum', p, 3, ListFromConcat(p[1], p[5]))
478 p[0] = self.BuildProduction('Enum', p, 3, ListFromConcat(Type, p[1], p[5]))
479 if self.parse_debug: DumpReduction('enum_block', p) 523 if self.parse_debug: DumpReduction('enum_block', p)
480 524
481 def p_enum_list(self, p): 525 def p_enum_list(self, p):
482 """enum_list : comments SYMBOL '=' value enum_cont""" 526 """enum_list : modifiers SYMBOL '=' number enum_cont
483 val = self.BuildExtAttribute('VALUE', p[4]) 527 | modifiers SYMBOL enum_cont"""
484 enum = self.BuildProduction('EnumItem', p, 2, ListFromConcat(val, p[1])) 528 if len(p) > 4:
485 p[0] = ListFromConcat(enum, p[5]) 529 val = self.BuildAttribute('VALUE', p[4])
530 enum = self.BuildNamed('EnumItem', p, 2, ListFromConcat(val, p[1]))
531 p[0] = ListFromConcat(enum, p[5])
532 else:
533 enum = self.BuildNamed('EnumItem', p, 2, p[1])
534 p[0] = ListFromConcat(enum, p[3])
486 if self.parse_debug: DumpReduction('enum_list', p) 535 if self.parse_debug: DumpReduction('enum_list', p)
487 536
488 def p_enum_cont(self, p): 537 def p_enum_cont(self, p):
489 """enum_cont : ',' enum_list 538 """enum_cont : ',' enum_list
490 |""" 539 |"""
491 if len(p) > 1: p[0] = p[2] 540 if len(p) > 1: p[0] = p[2]
492 if self.parse_debug: DumpReduction('enum_cont', p) 541 if self.parse_debug: DumpReduction('enum_cont', p)
493 542
494 def p_enum_cont_error(self, p): 543 def p_enum_cont_error(self, p):
495 """enum_cont : error enum_cont""" 544 """enum_cont : error enum_cont"""
496 p[0] = p[2] 545 p[0] = p[2]
497 if self.parse_debug: DumpReduction('enum_error', p) 546 if self.parse_debug: DumpReduction('enum_error', p)
498 547
499 548
500 # 549 #
550 # Label
551 #
552 # A label is a special kind of enumeration which allows us to go from a
553 # set of labels
554 #
555 def p_label_block(self, p):
556 """label_block : modifiers LABEL SYMBOL '{' label_list '}' ';'"""
557 p[0] = self.BuildNamed('Label', p, 3, ListFromConcat(p[1], p[5]))
558 if self.parse_debug: DumpReduction('label_block', p)
559
560 def p_label_list(self, p):
561 """label_list : modifiers SYMBOL '=' FLOAT label_cont"""
562 val = self.BuildAttribute('VALUE', p[4])
563 label = self.BuildNamed('LabelItem', p, 2, ListFromConcat(val, p[1]))
564 p[0] = ListFromConcat(label, p[5])
565 if self.parse_debug: DumpReduction('label_list', p)
566
567 def p_label_cont(self, p):
568 """label_cont : ',' label_list
569 |"""
570 if len(p) > 1: p[0] = p[2]
571 if self.parse_debug: DumpReduction('label_cont', p)
572
573 def p_label_cont_error(self, p):
574 """label_cont : error label_cont"""
575 p[0] = p[2]
576 if self.parse_debug: DumpReduction('label_error', p)
577
578
579 #
580 # Members
581 #
582 # A member attribute or function of a struct or interface.
583 #
584 def p_member_attribute(self, p):
585 """member_attribute : modifiers SYMBOL SYMBOL """
586 typeref = self.BuildAttribute('TYPEREF', p[2])
587 children = ListFromConcat(p[1], typeref)
588 p[0] = self.BuildNamed('Member', p, 3, children)
589 if self.parse_debug: DumpReduction('attribute', p)
590
591 def p_member_attribute_array(self, p):
592 """member_attribute : modifiers SYMBOL arrays SYMBOL """
593 typeref = self.BuildAttribute('TYPEREF', p[2])
594 children = ListFromConcat(p[1], typeref, p[3])
595 p[0] = self.BuildNamed('Member', p, 4, children)
596 if self.parse_debug: DumpReduction('attribute', p)
597
598 def p_member_function(self, p):
599 """member_function : modifiers SYMBOL SYMBOL param_list"""
600 typeref = self.BuildAttribute('TYPEREF', p[2])
601 children = ListFromConcat(p[1], typeref, p[4])
602 p[0] = self.BuildNamed('Member', p, 3, children)
603 if self.parse_debug: DumpReduction('function', p)
604
605 #
501 # Interface 606 # Interface
502 # 607 #
503 # An interface is a named collection of functions. 608 # An interface is a named collection of functions.
504 # 609 #
505 def p_interface_block(self, p): 610 def p_interface_block(self, p):
506 """interface_block : modifiers INTERFACE SYMBOL '{' member_list '}' ';'""" 611 """interface_block : modifiers INTERFACE SYMBOL '{' interface_list '}' ';'"" "
507 p[0] = self.BuildProduction('Interface', p, 3, ListFromConcat(p[1], p[5])) 612 p[0] = self.BuildNamed('Interface', p, 3, ListFromConcat(p[1], p[5]))
508 if self.parse_debug: DumpReduction('interface_block', p) 613 if self.parse_debug: DumpReduction('interface_block', p)
509 614
510 def p_member_list(self, p): 615 def p_interface_list(self, p):
511 """member_list : member_function member_list 616 """interface_list : member_function ';' interface_list
512 | """ 617 | """
513 if len(p) > 1 : 618 if len(p) > 1 :
514 p[0] = ListFromConcat(p[1], p[2]) 619 p[0] = ListFromConcat(p[1], p[3])
515 if self.parse_debug: DumpReduction('member_list', p) 620 if self.parse_debug: DumpReduction('interface_list', p)
516 621
517 def p_member_function(self, p): 622 def p_interface_error(self, p):
518 """member_function : modifiers typeref SYMBOL '(' param_list ')' ';'""" 623 """interface_list : error interface_list"""
519 children = ListFromConcat(p[1], p[2], p[5])
520 p[0] = self.BuildProduction('Function', p, 3, children)
521 if self.parse_debug: DumpReduction('member_function', p)
522
523 def p_member_error(self, p):
524 """member_list : error member_list"""
525 p[0] = p[2] 624 p[0] = p[2]
526 625
527 # 626 #
528 # Struct 627 # Struct
529 # 628 #
530 # A struct is a named collection of members which in turn reference other 629 # A struct is a named collection of members which in turn reference other
531 # types. The struct is a referencable type. 630 # types. The struct is a referencable type.
532 # 631 #
533 def p_struct_block(self, p): 632 def p_struct_block(self, p):
534 """struct_block : modifiers STRUCT SYMBOL '{' struct_list '}' ';'""" 633 """struct_block : modifiers STRUCT SYMBOL '{' struct_list '}' ';'"""
535 Type = self.BuildExtAttribute('TYPEREF', 'struct') 634 children = ListFromConcat(p[1], p[5])
536 children = ListFromConcat(Type, p[1], p[5]) 635 p[0] = self.BuildNamed('Struct', p, 3, children)
537 p[0] = self.BuildProduction('Struct', p, 3, children)
538 if self.parse_debug: DumpReduction('struct_block', p) 636 if self.parse_debug: DumpReduction('struct_block', p)
539 637
540 def p_struct_list(self, p): 638 def p_struct_list(self, p):
541 """struct_list : modifiers typeref SYMBOL ';' struct_list 639 """struct_list : member_attribute ';' struct_list
542 | """ 640 | member_function ';' struct_list
543 if len(p) > 1: 641 |"""
544 member = self.BuildProduction('Member', p, 3, ListFromConcat(p[1], p[2])) 642 if len(p) > 1: p[0] = ListFromConcat(p[1], p[3])
545 p[0] = ListFromConcat(member, p[5])
546 if self.parse_debug: DumpReduction('struct_list', p)
547 643
548 644 def p_struct_error(self, p):
549 645 """struct_list : error struct_list"""
646 p[0] = p[2]
550 647
551 # 648 #
552 # Parser Errors 649 # Parser Errors
553 # 650 #
554 # p_error is called whenever the parser can not find a pattern match for 651 # p_error is called whenever the parser can not find a pattern match for
555 # a set of items from the current state. The p_error function defined here 652 # a set of items from the current state. The p_error function defined here
556 # is triggered logging an error, and parsing recover happens as the 653 # is triggered logging an error, and parsing recover happens as the
557 # p_<type>_error functions defined above are called. This allows the parser 654 # p_<type>_error functions defined above are called. This allows the parser
558 # to continue so as to capture more than one error per file. 655 # to continue so as to capture more than one error per file.
559 # 656 #
(...skipping 14 matching lines...) Expand all
574 pos = self.last.lexpos 671 pos = self.last.lexpos
575 msg = "Unexpected end of file after %s." % TokenTypeName(self.last) 672 msg = "Unexpected end of file after %s." % TokenTypeName(self.last)
576 self.yaccobj.restart() 673 self.yaccobj.restart()
577 674
578 # Attempt to remap the error to a friendlier form 675 # Attempt to remap the error to a friendlier form
579 if msg in ERROR_REMAP: 676 if msg in ERROR_REMAP:
580 msg = ERROR_REMAP[msg] 677 msg = ERROR_REMAP[msg]
581 678
582 # Log the error 679 # Log the error
583 ErrOut.LogLine(filename, lineno, pos, msg) 680 ErrOut.LogLine(filename, lineno, pos, msg)
584 self.parse_errors += 1
585 681
586 def Warn(self, node, msg): 682 def Warn(self, node, msg):
587 WarnOut.LogLine(node.filename, node.lineno, node.pos, msg) 683 WarnOut.LogLine(node.filename, node.lineno, node.pos, msg)
588 self.parse_warnings += 1 684 self.parse_warnings += 1
589 685
590 def __init__(self): 686 def __init__(self):
591 IDLLexer.__init__(self) 687 IDLLexer.__init__(self)
592 self.yaccobj = yacc.yacc(module=self, tabmodule=None, debug=False, 688 self.yaccobj = yacc.yacc(module=self, tabmodule=None, debug=False,
593 optimize=0, write_tables=0) 689 optimize=0, write_tables=0)
594 690
(...skipping 17 matching lines...) Expand all
612 InfoOut.Log("TOKEN %s(%s)" % (tok.type, tok.value)) 708 InfoOut.Log("TOKEN %s(%s)" % (tok.type, tok.value))
613 return tok 709 return tok
614 710
615 # 711 #
616 # VerifyProduction 712 # VerifyProduction
617 # 713 #
618 # Once the node is built, we will check for certain types of issues 714 # Once the node is built, we will check for certain types of issues
619 # 715 #
620 def VerifyProduction(self, node): 716 def VerifyProduction(self, node):
621 comment = node.GetOneOf('Comment') 717 comment = node.GetOneOf('Comment')
622 if node.cls in ['Interface', 'Struct', 'Function'] and not comment: 718 if node.cls in ['Interface', 'Struct', 'Member'] and not comment:
623 self.Warn(node, 'Missing comment for %s.' % node) 719 if not GetOption('wcomment') and not node.GetProperty('wcomment'):
624 if node.cls in ['Param']: 720 self.Warn(node, 'Missing comment for %s.' % node)
721 elif node.cls in ['EnumItem'] and not node.GetProperty('VALUE'):
722 if not GetOption('wenum'):
723 self.Warn(node, 'Missing value for enumeration %s.' % node)
724 elif node.cls in ['Param']:
625 found = False; 725 found = False;
626 for form in ['in', 'inout', 'out']: 726 for form in ['in', 'inout', 'out']:
627 if node.GetProperty(form): found = True 727 if node.GetProperty(form): found = True
628 if not found: self.Warn(node, 'Missing argument type: [in|out|inout]') 728 if not found: self.Warn(node, 'Missing argument type: [in|out|inout]')
629 729
630 730
631 # 731 #
632 # BuildProduction 732 # BuildProduction
633 # 733 #
634 # Production is the set of items sent to a grammar rule resulting in a new 734 # Production is the set of items sent to a grammar rule resulting in a new
635 # item being returned. 735 # item being returned.
636 # 736 #
637 # p - Is the Yacc production object containing the stack of items 737 # p - Is the Yacc production object containing the stack of items
638 # index - Index into the production of the name for the item being produced. 738 # index - Index into the production of the name for the item being produced.
639 # cls - The type of item being producted 739 # cls - The type of item being producted
640 # childlist - The children of the new item 740 # childlist - The children of the new item
641 def BuildProduction(self, cls, p, index, childlist): 741 def BuildProduction(self, cls, p, index, childlist=None):
642 name = p[index] 742 if not childlist: childlist = []
643 filename = self.lexobj.filename 743 filename = self.lexobj.filename
644 lineno = p.lineno(index) 744 lineno = p.lineno(index)
645 pos = p.lexpos(index) 745 pos = p.lexpos(index)
746 out = IDLNode(cls, filename, lineno, pos, childlist)
646 if self.build_debug: 747 if self.build_debug:
647 InfoOut.Log("Building %s(%s)" % (cls, name)) 748 InfoOut.Log("Building %s" % out)
648 out = IDLNode(cls, name, filename, lineno, pos, childlist)
649 self.VerifyProduction(out) 749 self.VerifyProduction(out)
650 return out 750 return out
651 751
752 def BuildNamed(self, cls, p, index, childlist=None):
753 if not childlist: childlist = []
754 childlist.append(self.BuildAttribute('NAME', p[index]))
755 return self.BuildProduction(cls, p, index, childlist)
756
757 def BuildComment(self, cls, p, index):
758 name = p[index]
759
760 # Remove comment markers
761 if name[:2] == '//':
762 # For C++ style, remove the preceding '//'
763 form = 'cc'
764 name = name[2:].rstrip()
765 else:
766 # For C style, remove ending '*/''
767 form = 'c'
768 lines = []
769 for line in name[:-2].split('\n'):
770 # Remove characters until start marker for this line '*' if found
771 # otherwise it should be blank.
772 offs = line.find('*')
773 if offs >= 0:
774 line = line[offs + 1:].rstrip()
775 else:
776 line = ''
777 lines.append(line)
778 name = '\n'.join(lines)
779
780 childlist = [self.BuildAttribute('NAME', name),
781 self.BuildAttribute('FORM', form)]
782 return self.BuildProduction(cls, p, index, childlist)
783
652 # 784 #
653 # BuildExtAttribute 785 # BuildAttribute
654 # 786 #
655 # An ExtendedAttribute is a special production that results in a property 787 # An ExtendedAttribute is a special production that results in a property
656 # which is applied to the adjacent item. Attributes have no children and 788 # which is applied to the adjacent item. Attributes have no children and
657 # instead represent key/value pairs. 789 # instead represent key/value pairs.
658 # 790 #
659 def BuildExtAttribute(self, name, value): 791 def BuildAttribute(self, key, val):
660 if self.build_debug: 792 return IDLAttribute(key, val)
661 InfoOut.Log("Adding ExtAttribute %s = %s" % (name, str(value))) 793
662 out = IDLAttribute(name, value)
663 return out
664 794
665 # 795 #
666 # ParseData 796 # ParseData
667 # 797 #
668 # Attempts to parse the current data loaded in the lexer. 798 # Attempts to parse the current data loaded in the lexer.
669 # 799 #
670 def ParseData(self, data, filename='<Internal>'): 800 def ParseData(self, data, filename='<Internal>'):
671 self.SetData(filename, data) 801 self.SetData(filename, data)
672 try: 802 try:
673 self.parse_errors = 0 803 self.parse_errors = 0
674 self.parse_warnings = 0 804 self.parse_warnings = 0
675 return self.yaccobj.parse(lexer=self) 805 return self.yaccobj.parse(lexer=self)
676 806
677 except lex.LexError as le: 807 except lex.LexError as le:
678 ErrOut.Log(str(le)) 808 ErrOut.Log(str(le))
679 return [] 809 return []
680 810
681 # 811 #
682 # ParseFile 812 # ParseFile
683 # 813 #
684 # Loads a new file into the lexer and attemps to parse it. 814 # Loads a new file into the lexer and attemps to parse it.
685 # 815 #
686 def ParseFile(self, filename): 816 def ParseFile(self, filename):
687 loadname = os.path.join(GetOption('srcdir'), filename) 817 data = open(filename).read()
688 data = open(loadname).read()
689 if self.verbose: 818 if self.verbose:
690 InfoOut.Log("Parsing %s" % filename) 819 InfoOut.Log("Parsing %s" % filename)
691 try: 820 try:
692 out = self.ParseData(data, filename) 821 out = self.ParseData(data, filename)
693 return StageResult(filename, out, self.parse_errors) 822
823 # If we have a src root specified, remove it from the path
824 srcroot = GetOption('srcroot')
825 if srcroot and filename.find(srcroot) == 0:
826 filename = filename[len(srcroot) + 1:]
827 return IDLFile(filename, out, self.parse_errors)
694 828
695 except Exception as e: 829 except Exception as e:
696 ErrOut.LogLine(filename, self.last.lineno, self.last.lexpos, 830 ErrOut.LogLine(filename, self.last.lineno, self.last.lexpos,
697 'Internal parsing error - %s.' % str(e)) 831 'Internal parsing error - %s.' % str(e))
698 raise 832 raise
699 return StageResult(filename, [], self.parse_errors)
700 833
701 834
702 835
703 # 836 #
704 # Flatten Tree 837 # Flatten Tree
705 # 838 #
706 # Flattens the tree of IDLNodes for use in testing. 839 # Flattens the tree of IDLNodes for use in testing.
707 # 840 #
708 def FlattenTree(node): 841 def FlattenTree(node):
709 add_self = False 842 add_self = False
710 out = [] 843 out = []
711 for cls in node.children.keys(): 844 for child in node.children:
712 if cls == 'Comment': 845 if child.IsA('Comment'):
713 add_self = True 846 add_self = True
714 else: 847 else:
715 for c in node.children[cls]: 848 out.extend(FlattenTree(child))
716 out.extend(FlattenTree(c))
717 849
718 if add_self: 850 if add_self:
719 out = [str(node)] + out 851 out = [str(node)] + out
720 return out 852 return out
721 853
722 854
723 def TestErrors(filename, nodelist): 855 def TestErrors(filename, filenode):
856 nodelist = filenode.GetChildren()
857
724 lexer = IDLLexer() 858 lexer = IDLLexer()
725 data = open(filename).read() 859 data = open(filename).read()
726 lexer.SetData(filename, data) 860 lexer.SetData(filename, data)
727 861
728 pass_comments = [] 862 pass_comments = []
729 fail_comments = [] 863 fail_comments = []
730 while True: 864 while True:
731 tok = lexer.lexobj.token() 865 tok = lexer.lexobj.token()
732 if tok == None: break 866 if tok == None: break
733 if tok.type == 'COMMENT': 867 if tok.type == 'COMMENT':
734 args = tok.value.split() 868 args = tok.value[3:-3].split()
735 if args[1] == 'OK': 869 if args[0] == 'OK':
736 pass_comments.append((tok.lineno, ' '.join(args[2:-1]))) 870 pass_comments.append((tok.lineno, ' '.join(args[1:])))
737 else: 871 else:
738 if args[1] == 'FAIL': 872 if args[0] == 'FAIL':
739 fail_comments.append((tok.lineno, ' '.join(args[2:-1]))) 873 fail_comments.append((tok.lineno, ' '.join(args[1:])))
740 obj_list = [] 874 obj_list = []
741 for node in nodelist: 875 for node in nodelist:
742 obj_list.extend(FlattenTree(node)) 876 obj_list.extend(FlattenTree(node))
743 877
744 errors = 0 878 errors = 0
745 879
746 # 880 #
747 # Check for expected successes 881 # Check for expected successes
748 # 882 #
749 obj_cnt = len(obj_list) 883 obj_cnt = len(obj_list)
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
790 err_list = [] 924 err_list = []
791 return errors 925 return errors
792 926
793 927
794 def TestFile(parser, filename): 928 def TestFile(parser, filename):
795 # Capture errors instead of reporting them so we can compare them 929 # Capture errors instead of reporting them so we can compare them
796 # with the expected errors. 930 # with the expected errors.
797 ErrOut.SetConsole(False) 931 ErrOut.SetConsole(False)
798 ErrOut.SetCapture(True) 932 ErrOut.SetCapture(True)
799 933
800 result = parser.ParseFile(filename) 934 filenode = parser.ParseFile(filename)
801 935
802 # Renable output 936 # Renable output
803 ErrOut.SetConsole(True) 937 ErrOut.SetConsole(True)
804 ErrOut.SetCapture(False) 938 ErrOut.SetCapture(False)
805 939
806 # Compare captured errors 940 # Compare captured errors
807 return TestErrors(filename, result.out) 941 return TestErrors(filename, filenode)
808 942
809 943
810 def TestErrorFiles(): 944 def TestErrorFiles(filter):
811 idldir = os.path.split(sys.argv[0])[0] 945 idldir = os.path.split(sys.argv[0])[0]
812 idldir = os.path.join(idldir, 'test_parser', '*.idl') 946 idldir = os.path.join(idldir, 'test_parser', '*.idl')
813 filenames = glob.glob(idldir) 947 filenames = glob.glob(idldir)
814 parser = IDLParser() 948 parser = IDLParser()
815 total_errs = 0 949 total_errs = 0
816 for filename in filenames: 950 for filename in filenames:
951 if filter and filename not in filter: continue
817 errs = TestFile(parser, filename) 952 errs = TestFile(parser, filename)
818 if errs: 953 if errs:
819 ErrOut.Log("%s test failed with %d error(s)." % (filename, errs)) 954 ErrOut.Log("%s test failed with %d error(s)." % (filename, errs))
820 total_errs += errs 955 total_errs += errs
821 956
822 if total_errs: 957 if total_errs:
823 ErrOut.Log("Failed parsing test.") 958 ErrOut.Log("Failed parsing test.")
824 else: 959 else:
825 InfoOut.Log("Passed parsing test.") 960 InfoOut.Log("Passed parsing test.")
826 return total_errs 961 return total_errs
827 962
828 def TestNamespaceFiles(): 963 def TestNamespaceFiles(filter):
829 idldir = os.path.split(sys.argv[0])[0] 964 idldir = os.path.split(sys.argv[0])[0]
830 idldir = os.path.join(idldir, 'test_namespace', '*.idl') 965 idldir = os.path.join(idldir, 'test_namespace', '*.idl')
831 filenames = glob.glob(idldir) 966 filenames = glob.glob(idldir)
967 testnames = []
968
969 for filename in filenames:
970 if filter and filename not in filter: continue
971 testnames.append(filename)
972
973 # If we have no files to test, then skip this test
974 if not testnames:
975 InfoOut.Log('No files to test for namespace.')
976 return 0
832 977
833 InfoOut.SetConsole(False) 978 InfoOut.SetConsole(False)
834 result = ParseFiles(filenames) 979 ast = ParseFiles(testnames)
835 InfoOut.SetConsole(True) 980 InfoOut.SetConsole(True)
836 981
837 if result.errs: 982 errs = ast.GetProperty('ERRORS')
983 if errs:
838 ErrOut.Log("Failed namespace test.") 984 ErrOut.Log("Failed namespace test.")
839 else: 985 else:
840 InfoOut.Log("Passed namespace test.") 986 InfoOut.Log("Passed namespace test.")
841 return result.errs 987 return errs
842 988
843 989
844 def ParseFiles(filenames): 990 def ParseFiles(filenames):
845 parser = IDLParser() 991 parser = IDLParser()
846 filenodes = [] 992 filenodes = []
847 errors = 0 993 errors = 0
848 994
849 for filename in filenames: 995 for filename in filenames:
850 result = parser.ParseFile(filename) 996 filenode = parser.ParseFile(filename)
851 if result.errs: 997 filenodes.append(filenode)
852 ErrOut.Log("%d error(s) parsing %s." % (result.errs, filename)) 998 if GetOption('verbose'):
853 errors += result.errs
854 else:
855 InfoOut.Log("Parsed %s." % filename) 999 InfoOut.Log("Parsed %s." % filename)
856 filenode = IDLNode('File', filename, filename, 1, 0, result.out)
857 filenodes.append(filenode)
858 1000
859 ast = IDLAst(filenodes) 1001 ast = IDLAst(filenodes)
860 1002 if GetOption('dump_tree'): ast.Dump(0)
861 # Build the links 1003 return ast
862 ast.BuildTree(None)
863
864 # Resolve type references
865 errors += ast.Resolve()
866
867 ast.Resolve()
868 return StageResult('Parsing', ast, errors)
869 1004
870 1005
871 def Main(args): 1006 def Main(args):
872 filenames = ParseOptions(args) 1007 filenames = ParseOptions(args)
873 1008
874 # If testing... 1009 # If testing...
875 if GetOption('test'): 1010 if GetOption('test'):
876 errs = TestErrorFiles() 1011 errs = TestErrorFiles(filenames)
877 errs = TestNamespaceFiles() 1012 errs = TestNamespaceFiles(filenames)
878 if errs: 1013 if errs:
879 ErrOut.Log("Parser failed with %d errors." % errs) 1014 ErrOut.Log("Parser failed with %d errors." % errs)
880 return -1 1015 return -1
881 return 0 1016 return 0
882 1017
883 # Otherwise, build the AST 1018 # Otherwise, build the AST
884 result = ParseFiles(filenames) 1019 ast = ParseFiles(filenames)
885 if GetOption('dump_tree'): 1020 errs = ast.GetProperty('ERRORS')
886 result.out.Dump(0) 1021 if errs:
887 if result.errs: 1022 ErrOut.Log('Found %d error(s).' % errs);
888 ErrOut.Log('Found %d error(s).' % result.errors);
889 InfoOut.Log("%d files processed." % len(filenames)) 1023 InfoOut.Log("%d files processed." % len(filenames))
890 return result.errs 1024 return errs
891 1025
892 if __name__ == '__main__': 1026 if __name__ == '__main__':
893 sys.exit(Main(sys.argv[1:])) 1027 sys.exit(Main(sys.argv[1:]))
894 1028
OLDNEW
« no previous file with comments | « ppapi/generators/idl_lexer.py ('k') | ppapi/generators/test_cgen/interface.idl » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698