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

Side by Side Diff: mojo/public/bindings/pylib/parse/mojo_parser.py

Issue 226263002: Mojo: Move mojo/public/bindings to mojo/public/tools/bindings. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebased Created 6 years, 8 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
(Empty)
1 #!/usr/bin/env python
2 # Copyright 2013 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5
6 """Generates a syntax tree from a Mojo IDL file."""
7
8
9 import sys
10 import os.path
11
12 # Try to load the ply module, if not, then assume it is in the third_party
13 # directory.
14 try:
15 # Disable lint check which fails to find the ply module.
16 # pylint: disable=F0401
17 from ply import lex
18 from ply import yacc
19 except ImportError:
20 module_path, module_name = os.path.split(__file__)
21 third_party = os.path.join(module_path, os.pardir, os.pardir, os.pardir,
22 os.pardir, os.pardir, 'third_party')
23 sys.path.append(third_party)
24 # pylint: disable=F0401
25 from ply import lex
26 from ply import yacc
27
28 from mojo_lexer import Lexer
29
30
31 def _ListFromConcat(*items):
32 """Generate list by concatenating inputs (note: only concatenates lists, not
33 tuples or other iterables)."""
34 itemsout = []
35 for item in items:
36 if item is None:
37 continue
38 if type(item) is not type([]):
39 itemsout.append(item)
40 else:
41 itemsout.extend(item)
42 return itemsout
43
44
45 class ParseError(Exception):
46
47 def __init__(self, filename, lineno=None, snippet=None, bad_char=None,
48 eof=False):
49 self.filename = filename
50 self.lineno = lineno
51 self.snippet = snippet
52 self.bad_char = bad_char
53 self.eof = eof
54
55 def __str__(self):
56 return "%s: Error: Unexpected end of file" % self.filename if self.eof \
57 else "%s:%d: Error: Unexpected %r:\n%s" % (
58 self.filename, self.lineno + 1, self.bad_char, self.snippet)
59
60 def __repr__(self):
61 return str(self)
62
63
64 class Parser(object):
65
66 def __init__(self, lexer, source, filename):
67 self.tokens = lexer.tokens
68 self.source = source
69 self.filename = filename
70
71 def p_root(self, p):
72 """root : import root
73 | module
74 | definitions"""
75 if len(p) > 2:
76 p[0] = _ListFromConcat(p[1], p[2])
77 else:
78 if p[1][0] != 'MODULE':
79 p[0] = [('MODULE', '', p[1])]
80 else:
81 p[0] = [p[1]]
82
83 def p_import(self, p):
84 """import : IMPORT STRING_LITERAL"""
85 # 'eval' the literal to strip the quotes.
86 p[0] = ('IMPORT', eval(p[2]))
87
88 def p_module(self, p):
89 """module : MODULE NAME LBRACE definitions RBRACE"""
90 p[0] = ('MODULE', p[2], p[4])
91
92 def p_definitions(self, p):
93 """definitions : definition definitions
94 | """
95 if len(p) > 1:
96 p[0] = _ListFromConcat(p[1], p[2])
97
98 def p_definition(self, p):
99 """definition : struct
100 | interface
101 | enum"""
102 p[0] = p[1]
103
104 def p_attribute_section(self, p):
105 """attribute_section : LBRACKET attributes RBRACKET
106 | """
107 if len(p) > 3:
108 p[0] = p[2]
109
110 def p_attributes(self, p):
111 """attributes : attribute
112 | attribute COMMA attributes
113 | """
114 if len(p) == 2:
115 p[0] = _ListFromConcat(p[1])
116 elif len(p) > 3:
117 p[0] = _ListFromConcat(p[1], p[3])
118
119 def p_attribute(self, p):
120 """attribute : NAME EQUALS expression
121 | NAME EQUALS NAME"""
122 p[0] = ('ATTRIBUTE', p[1], p[3])
123
124 def p_struct(self, p):
125 """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI"""
126 p[0] = ('STRUCT', p[3], p[1], p[5])
127
128 def p_struct_body(self, p):
129 """struct_body : field struct_body
130 | enum struct_body
131 | """
132 if len(p) > 1:
133 p[0] = _ListFromConcat(p[1], p[2])
134
135 def p_field(self, p):
136 """field : typename NAME default ordinal SEMI"""
137 p[0] = ('FIELD', p[1], p[2], p[4], p[3])
138
139 def p_default(self, p):
140 """default : EQUALS expression
141 | EQUALS expression_object
142 | """
143 if len(p) > 2:
144 p[0] = p[2]
145
146 def p_interface(self, p):
147 """interface : attribute_section INTERFACE NAME LBRACE interface_body \
148 RBRACE SEMI"""
149 p[0] = ('INTERFACE', p[3], p[1], p[5])
150
151 def p_interface_body(self, p):
152 """interface_body : method interface_body
153 | enum interface_body
154 | """
155 if len(p) > 1:
156 p[0] = _ListFromConcat(p[1], p[2])
157
158 def p_response(self, p):
159 """response : RESPONSE LPAREN parameters RPAREN
160 | """
161 if len(p) > 3:
162 p[0] = p[3]
163
164 def p_method(self, p):
165 """method : NAME ordinal LPAREN parameters RPAREN response SEMI"""
166 p[0] = ('METHOD', p[1], p[4], p[2], p[6])
167
168 def p_parameters(self, p):
169 """parameters : parameter
170 | parameter COMMA parameters
171 | """
172 if len(p) == 1:
173 p[0] = []
174 elif len(p) == 2:
175 p[0] = _ListFromConcat(p[1])
176 elif len(p) > 3:
177 p[0] = _ListFromConcat(p[1], p[3])
178
179 def p_parameter(self, p):
180 """parameter : typename NAME ordinal"""
181 p[0] = ('PARAM', p[1], p[2], p[3])
182
183 def p_typename(self, p):
184 """typename : basictypename
185 | array"""
186 p[0] = p[1]
187
188 def p_basictypename(self, p):
189 """basictypename : identifier
190 | HANDLE
191 | specializedhandle"""
192 p[0] = p[1]
193
194 def p_specializedhandle(self, p):
195 """specializedhandle : HANDLE LANGLE specializedhandlename RANGLE"""
196 p[0] = "handle<" + p[3] + ">"
197
198 def p_specializedhandlename(self, p):
199 """specializedhandlename : DATA_PIPE_CONSUMER
200 | DATA_PIPE_PRODUCER
201 | MESSAGE_PIPE
202 | SHARED_BUFFER"""
203 p[0] = p[1]
204
205 def p_array(self, p):
206 """array : basictypename LBRACKET RBRACKET"""
207 p[0] = p[1] + "[]"
208
209 def p_ordinal(self, p):
210 """ordinal : ORDINAL
211 | """
212 if len(p) > 1:
213 p[0] = p[1]
214
215 def p_enum(self, p):
216 """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI"""
217 p[0] = ('ENUM', p[2], p[4])
218
219 def p_enum_fields(self, p):
220 """enum_fields : enum_field
221 | enum_field COMMA enum_fields
222 | """
223 if len(p) == 2:
224 p[0] = _ListFromConcat(p[1])
225 elif len(p) > 3:
226 p[0] = _ListFromConcat(p[1], p[3])
227
228 def p_enum_field(self, p):
229 """enum_field : NAME
230 | NAME EQUALS expression"""
231 if len(p) == 2:
232 p[0] = ('ENUM_FIELD', p[1], None)
233 else:
234 p[0] = ('ENUM_FIELD', p[1], p[3])
235
236 ### Expressions ###
237
238 def p_expression_object(self, p):
239 """expression_object : expression_array
240 | LBRACE expression_object_elements RBRACE """
241 if len(p) < 3:
242 p[0] = p[1]
243 else:
244 p[0] = ('OBJECT', p[2])
245
246 def p_expression_object_elements(self, p):
247 """expression_object_elements : expression_object
248 | expression_object COMMA expression_object_el ements
249 | """
250 if len(p) == 2:
251 p[0] = _ListFromConcat(p[1])
252 elif len(p) > 3:
253 p[0] = _ListFromConcat(p[1], p[3])
254
255 def p_expression_array(self, p):
256 """expression_array : expression
257 | LBRACKET expression_array_elements RBRACKET """
258 if len(p) < 3:
259 p[0] = p[1]
260 else:
261 p[0] = ('ARRAY', p[2])
262
263 def p_expression_array_elements(self, p):
264 """expression_array_elements : expression_object
265 | expression_object COMMA expression_array_elem ents
266 | """
267 if len(p) == 2:
268 p[0] = _ListFromConcat(p[1])
269 elif len(p) > 3:
270 p[0] = _ListFromConcat(p[1], p[3])
271
272 # TODO(vtl): This is now largely redundant.
273 def p_expression(self, p):
274 """expression : binary_expression"""
275 p[0] = ('EXPRESSION', p[1])
276
277 # PLY lets us specify precedence of operators, but since we don't actually
278 # evaluate them, we don't need that here.
279 # TODO(vtl): We're going to need to evaluate them.
280 def p_binary_expression(self, p):
281 """binary_expression : unary_expression
282 | binary_expression binary_operator \
283 binary_expression"""
284 p[0] = _ListFromConcat(*p[1:])
285
286 def p_binary_operator(self, p):
287 """binary_operator : TIMES
288 | DIVIDE
289 | MOD
290 | PLUS
291 | MINUS
292 | RSHIFT
293 | LSHIFT
294 | AND
295 | OR
296 | XOR"""
297 p[0] = p[1]
298
299 def p_unary_expression(self, p):
300 """unary_expression : primary_expression
301 | unary_operator expression"""
302 p[0] = _ListFromConcat(*p[1:])
303
304 def p_unary_operator(self, p):
305 """unary_operator : PLUS
306 | MINUS
307 | NOT"""
308 p[0] = p[1]
309
310 def p_primary_expression(self, p):
311 """primary_expression : constant
312 | identifier
313 | LPAREN expression RPAREN"""
314 p[0] = _ListFromConcat(*p[1:])
315
316 def p_identifier(self, p):
317 """identifier : NAME
318 | NAME DOT identifier"""
319 p[0] = ''.join(p[1:])
320
321 def p_constant(self, p):
322 """constant : INT_CONST_DEC
323 | INT_CONST_OCT
324 | INT_CONST_HEX
325 | FLOAT_CONST
326 | CHAR_CONST
327 | STRING_LITERAL"""
328 p[0] = _ListFromConcat(*p[1:])
329
330 def p_error(self, e):
331 if e is None:
332 # Unexpected EOF.
333 # TODO(vtl): Can we figure out what's missing?
334 raise ParseError(self.filename, eof=True)
335
336 lineno = e.lineno + 1
337 snippet = self.source.split('\n')[lineno]
338 raise ParseError(self.filename, lineno=lineno, snippet=snippet,
339 bad_char=e.value)
340
341
342 def Parse(source, filename):
343 lexer = Lexer(filename)
344 parser = Parser(lexer, source, filename)
345
346 lex.lex(object=lexer)
347 yacc.yacc(module=parser, debug=0, write_tables=0)
348
349 tree = yacc.parse(source)
350 return tree
351
352
353 def main(argv):
354 if len(argv) < 2:
355 print "usage: %s filename" % argv[0]
356 return 0
357
358 for filename in argv[1:]:
359 with open(filename) as f:
360 print "%s:" % filename
361 try:
362 print Parse(f.read(), filename)
363 except ParseError, e:
364 print e
365 return 1
366
367 return 0
368
369
370 if __name__ == '__main__':
371 sys.exit(main(sys.argv))
OLDNEW
« no previous file with comments | « mojo/public/bindings/pylib/parse/mojo_lexer_unittest.py ('k') | mojo/public/bindings/pylib/parse/mojo_parser_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698