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

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

Powered by Google App Engine
This is Rietveld 408576698