OLD | NEW |
1 # Copyright 2014 The Chromium Authors. All rights reserved. | 1 # Copyright 2014 The Chromium Authors. All rights reserved. |
2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
4 | 4 |
5 """Generates a syntax tree from a Mojo IDL file.""" | 5 """Generates a syntax tree from a Mojo IDL file.""" |
6 | 6 |
7 import imp | 7 import imp |
8 import os.path | 8 import os.path |
9 import sys | 9 import sys |
10 | 10 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
64 # | 64 # |
65 # It's also possible to have a function handling multiple rules with different | 65 # It's also possible to have a function handling multiple rules with different |
66 # left-hand-sides. We do not do this. | 66 # left-hand-sides. We do not do this. |
67 # | 67 # |
68 # See http://www.dabeaz.com/ply/ply.html#ply_nn25 for more details. | 68 # See http://www.dabeaz.com/ply/ply.html#ply_nn25 for more details. |
69 | 69 |
70 # TODO(vtl): Get rid of the braces in the module "statement". (Consider | 70 # TODO(vtl): Get rid of the braces in the module "statement". (Consider |
71 # renaming "module" -> "package".) Then we'll be able to have a single rule | 71 # renaming "module" -> "package".) Then we'll be able to have a single rule |
72 # for root (by making module "optional"). | 72 # for root (by making module "optional"). |
73 def p_root_1(self, p): | 73 def p_root_1(self, p): |
74 """root : import_list module LBRACE definition_list RBRACE""" | 74 """root : """ |
75 p[0] = ast.Mojom(p[2], p[1], p[4]) | 75 p[0] = ast.Mojom(None, ast.ImportList(), []) |
76 | 76 |
77 def p_root_2(self, p): | 77 def p_root_2(self, p): |
78 """root : import_list definition_list""" | 78 """root : root module""" |
79 p[0] = ast.Mojom(None, p[1], p[2]) | 79 if p[1].module is not None: |
| 80 raise ParseError(self.filename, |
| 81 "Multiple \"module\" statements not allowed:", |
| 82 p[2].lineno, snippet=self._GetSnippet(p[2].lineno)) |
| 83 if p[1].import_list.items or p[1].definition_list: |
| 84 raise ParseError( |
| 85 self.filename, |
| 86 "\"module\" statements must precede imports and definitions:", |
| 87 p[2].lineno, snippet=self._GetSnippet(p[2].lineno)) |
| 88 p[0] = p[1] |
| 89 p[0].module = p[2] |
80 | 90 |
81 def p_import_list_1(self, p): | 91 def p_root_3(self, p): |
82 """import_list : """ | 92 """root : root import""" |
83 p[0] = ast.ImportList() | 93 if p[1].definition_list: |
| 94 raise ParseError(self.filename, |
| 95 "\"import\" statements must precede definitions:", |
| 96 p[2].lineno, snippet=self._GetSnippet(p[2].lineno)) |
| 97 p[0] = p[1] |
| 98 p[0].import_list.Append(p[2]) |
84 | 99 |
85 def p_import_list_2(self, p): | 100 def p_root_4(self, p): |
86 """import_list : import_list import""" | 101 """root : root definition""" |
87 p[0] = p[1] | 102 p[0] = p[1] |
88 p[0].Append(p[2]) | 103 p[0].definition_list.append(p[2]) |
89 | 104 |
90 def p_import(self, p): | 105 def p_import(self, p): |
91 """import : IMPORT STRING_LITERAL SEMI""" | 106 """import : IMPORT STRING_LITERAL SEMI""" |
92 # 'eval' the literal to strip the quotes. | 107 # 'eval' the literal to strip the quotes. |
93 # TODO(vtl): This eval is dubious. We should unquote/unescape ourselves. | 108 # TODO(vtl): This eval is dubious. We should unquote/unescape ourselves. |
94 p[0] = ast.Import(eval(p[2])) | 109 p[0] = ast.Import(eval(p[2]), filename=self.filename, lineno=p.lineno(2)) |
95 | 110 |
96 def p_module(self, p): | 111 def p_module(self, p): |
97 """module : attribute_section MODULE identifier_wrapped """ | 112 """module : attribute_section MODULE identifier_wrapped SEMI""" |
98 p[0] = ast.Module(p[3], p[1], filename=self.filename, lineno=p.lineno(2)) | 113 p[0] = ast.Module(p[3], p[1], filename=self.filename, lineno=p.lineno(2)) |
99 | 114 |
100 def p_definition_list(self, p): | |
101 """definition_list : definition definition_list | |
102 | """ | |
103 if len(p) > 1: | |
104 p[0] = p[2] | |
105 p[0].insert(0, p[1]) | |
106 else: | |
107 p[0] = [] | |
108 | |
109 def p_definition(self, p): | 115 def p_definition(self, p): |
110 """definition : struct | 116 """definition : struct |
111 | interface | 117 | interface |
112 | enum | 118 | enum |
113 | const""" | 119 | const""" |
114 p[0] = p[1] | 120 p[0] = p[1] |
115 | 121 |
116 def p_attribute_section_1(self, p): | 122 def p_attribute_section_1(self, p): |
117 """attribute_section : """ | 123 """attribute_section : """ |
118 p[0] = None | 124 p[0] = None |
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
264 p[0] = "handle<" + p[3] + ">" | 270 p[0] = "handle<" + p[3] + ">" |
265 | 271 |
266 def p_array(self, p): | 272 def p_array(self, p): |
267 """array : ARRAY LANGLE typename RANGLE""" | 273 """array : ARRAY LANGLE typename RANGLE""" |
268 p[0] = p[3] + "[]" | 274 p[0] = p[3] + "[]" |
269 | 275 |
270 def p_fixed_array(self, p): | 276 def p_fixed_array(self, p): |
271 """fixed_array : ARRAY LANGLE typename COMMA INT_CONST_DEC RANGLE""" | 277 """fixed_array : ARRAY LANGLE typename COMMA INT_CONST_DEC RANGLE""" |
272 value = int(p[5]) | 278 value = int(p[5]) |
273 if value == 0 or value > _MAX_ARRAY_SIZE: | 279 if value == 0 or value > _MAX_ARRAY_SIZE: |
274 raise ParseError(self.filename, "Fixed array size %d invalid" % value, | 280 raise ParseError(self.filename, "Fixed array size %d invalid:" % value, |
275 lineno=p.lineno(5), | 281 lineno=p.lineno(5), |
276 snippet=self._GetSnippet(p.lineno(5))) | 282 snippet=self._GetSnippet(p.lineno(5))) |
277 p[0] = p[3] + "[" + p[5] + "]" | 283 p[0] = p[3] + "[" + p[5] + "]" |
278 | 284 |
279 def p_associative_array(self, p): | 285 def p_associative_array(self, p): |
280 """associative_array : MAP LANGLE identifier COMMA typename RANGLE""" | 286 """associative_array : MAP LANGLE identifier COMMA typename RANGLE""" |
281 p[0] = p[5] + "{" + p[3] + "}" | 287 p[0] = p[5] + "{" + p[3] + "}" |
282 | 288 |
283 def p_interfacerequest(self, p): | 289 def p_interfacerequest(self, p): |
284 """interfacerequest : identifier AMP""" | 290 """interfacerequest : identifier AMP""" |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
379 | 385 |
380 def Parse(source, filename): | 386 def Parse(source, filename): |
381 lexer = Lexer(filename) | 387 lexer = Lexer(filename) |
382 parser = Parser(lexer, source, filename) | 388 parser = Parser(lexer, source, filename) |
383 | 389 |
384 lex.lex(object=lexer) | 390 lex.lex(object=lexer) |
385 yacc.yacc(module=parser, debug=0, write_tables=0) | 391 yacc.yacc(module=parser, debug=0, write_tables=0) |
386 | 392 |
387 tree = yacc.parse(source) | 393 tree = yacc.parse(source) |
388 return tree | 394 return tree |
OLD | NEW |