Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / mojo / public / bindings / pylib / parse / mojo_parser.py
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"""
33   itemsout = []
34   for item in items:
35     if item is None:
36       continue
37     if type(item) is not type([]):
38       itemsout.append(item)
39     else:
40       itemsout.extend(item)
41
42   return itemsout
43
44
45 class Parser(object):
46
47   def __init__(self, lexer):
48     self.tokens = lexer.tokens
49
50   def p_root(self, p):
51     """root : import root
52             | module"""
53     if len(p) > 2:
54       p[0] = ListFromConcat(p[1], p[2])
55     else:
56       p[0] = [p[1]]
57
58   def p_import(self, p):
59     """import : IMPORT STRING_LITERAL"""
60     # 'eval' the literal to strip the quotes.
61     p[0] = ('IMPORT', eval(p[2]))
62
63   def p_module(self, p):
64     """module : MODULE NAME LBRACE definitions RBRACE"""
65     p[0] = ('MODULE', p[2], p[4])
66
67   def p_definitions(self, p):
68     """definitions : definition definitions
69                    | """
70     if len(p) > 1:
71       p[0] = ListFromConcat(p[1], p[2])
72
73   def p_definition(self, p):
74     """definition : struct
75                   | interface
76                   | enum"""
77     p[0] = p[1]
78
79   def p_attribute_section(self, p):
80     """attribute_section : LBRACKET attributes RBRACKET
81                          | """
82     if len(p) > 3:
83       p[0] = p[2]
84
85   def p_attributes(self, p):
86     """attributes : attribute
87                   | attribute COMMA attributes
88                   | """
89     if len(p) == 2:
90       p[0] = ListFromConcat(p[1])
91     elif len(p) > 3:
92       p[0] = ListFromConcat(p[1], p[3])
93
94   def p_attribute(self, p):
95     """attribute : NAME EQUALS expression
96                  | NAME EQUALS NAME"""
97     p[0] = ('ATTRIBUTE', p[1], p[3])
98
99   def p_struct(self, p):
100     """struct : attribute_section STRUCT NAME LBRACE struct_body RBRACE SEMI"""
101     p[0] = ('STRUCT', p[3], p[1], p[5])
102
103   def p_struct_body(self, p):
104     """struct_body : field struct_body
105                    | enum struct_body
106                    | """
107     if len(p) > 1:
108       p[0] = ListFromConcat(p[1], p[2])
109
110   def p_field(self, p):
111     """field : typename NAME default ordinal SEMI"""
112     p[0] = ('FIELD', p[1], p[2], p[4], p[3])
113
114   def p_default(self, p):
115     """default : EQUALS expression
116                | EQUALS expression_object
117                | """
118     if len(p) > 2:
119       p[0] = p[2]
120
121   def p_interface(self, p):
122     """interface : attribute_section INTERFACE NAME LBRACE interface_body \
123                        RBRACE SEMI"""
124     p[0] = ('INTERFACE', p[3], p[1], p[5])
125
126   def p_interface_body(self, p):
127     """interface_body : method interface_body
128                       | enum interface_body
129                       | """
130     if len(p) > 1:
131       p[0] = ListFromConcat(p[1], p[2])
132
133   def p_method(self, p):
134     """method : VOID NAME LPAREN parameters RPAREN ordinal SEMI"""
135     p[0] = ('METHOD', p[2], p[4], p[6])
136
137   def p_parameters(self, p):
138     """parameters : parameter
139                   | parameter COMMA parameters
140                   | """
141     if len(p) == 1:
142       p[0] = []
143     elif len(p) == 2:
144       p[0] = ListFromConcat(p[1])
145     elif len(p) > 3:
146       p[0] = ListFromConcat(p[1], p[3])
147
148   def p_parameter(self, p):
149     """parameter : typename NAME ordinal"""
150     p[0] = ('PARAM', p[1], p[2], p[3])
151
152   def p_typename(self, p):
153     """typename : basictypename
154                 | array"""
155     p[0] = p[1]
156
157   def p_basictypename(self, p):
158     """basictypename : NAME
159                      | HANDLE
160                      | NAME DOT NAME
161                      | specializedhandle"""
162     if len(p) == 2:
163       p[0] = p[1]
164     else:
165       p[0] = p[1] + '.' + p[3]
166
167   def p_specializedhandle(self, p):
168     """specializedhandle : HANDLE LT specializedhandlename GT"""
169     p[0] = "handle<" + p[3] + ">"
170
171   def p_specializedhandlename(self, p):
172     """specializedhandlename : DATA_PIPE_CONSUMER
173                              | DATA_PIPE_PRODUCER
174                              | MESSAGE_PIPE"""
175     p[0] = p[1]
176
177   def p_array(self, p):
178     """array : basictypename LBRACKET RBRACKET"""
179     p[0] = p[1] + "[]"
180
181   def p_ordinal(self, p):
182     """ordinal : ORDINAL
183                | """
184     if len(p) > 1:
185       p[0] = p[1]
186
187   def p_enum(self, p):
188     """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI"""
189     p[0] = ('ENUM', p[2], p[4])
190
191   def p_enum_fields(self, p):
192     """enum_fields : enum_field
193                    | enum_field COMMA enum_fields
194                    | """
195     if len(p) == 2:
196       p[0] = ListFromConcat(p[1])
197     elif len(p) > 3:
198       p[0] = ListFromConcat(p[1], p[3])
199
200   def p_enum_field(self, p):
201     """enum_field : NAME
202                   | NAME EQUALS expression"""
203     if len(p) == 2:
204       p[0] = ('ENUM_FIELD', p[1], None)
205     else:
206       p[0] = ('ENUM_FIELD', p[1], p[3])
207
208   ### Expressions ###
209
210   def p_expression_object(self, p):
211     """expression_object : expression_array
212                          | LBRACE expression_object_elements RBRACE """
213     if len(p) < 3:
214       p[0] = p[1]
215     else:
216       p[0] = ('OBJECT', p[2])
217
218   def p_expression_object_elements(self, p):
219     """expression_object_elements : expression_object
220                                   | expression_object COMMA expression_object_elements
221                                   | """
222     if len(p) == 2:
223       p[0] = ListFromConcat(p[1])
224     elif len(p) > 3:
225       p[0] = ListFromConcat(p[1], p[3])
226
227   def p_expression_array(self, p):
228     """expression_array : expression
229                         | LBRACKET expression_array_elements RBRACKET """
230     if len(p) < 3:
231       p[0] = p[1]
232     else:
233       p[0] = ('ARRAY', p[2])
234
235   def p_expression_array_elements(self, p):
236     """expression_array_elements : expression_object
237                                  | expression_object COMMA expression_array_elements
238                                  | """
239     if len(p) == 2:
240       p[0] = ListFromConcat(p[1])
241     elif len(p) > 3:
242       p[0] = ListFromConcat(p[1], p[3])
243
244   def p_expression(self, p):
245     """expression : conditional_expression"""
246     p[0] = ('EXPRESSION', p[1])
247
248   def p_conditional_expression(self, p):
249     """conditional_expression : binary_expression
250                               | binary_expression CONDOP expression COLON \
251                                     conditional_expression"""
252     # Just pass the arguments through. I don't think it's possible to preserve
253     # the spaces of the original, so just put a single space between them.
254     p[0] = ListFromConcat(*p[1:])
255
256   # PLY lets us specify precedence of operators, but since we don't actually
257   # evaluate them, we don't need that here.
258   def p_binary_expression(self, p):
259     """binary_expression : unary_expression
260                          | binary_expression binary_operator \
261                                binary_expression"""
262     p[0] = ListFromConcat(*p[1:])
263
264   def p_binary_operator(self, p):
265     """binary_operator : TIMES
266                        | DIVIDE
267                        | MOD
268                        | PLUS
269                        | MINUS
270                        | RSHIFT
271                        | LSHIFT
272                        | LT
273                        | LE
274                        | GE
275                        | GT
276                        | EQ
277                        | NE
278                        | AND
279                        | OR
280                        | XOR
281                        | LAND
282                        | LOR"""
283     p[0] = p[1]
284
285   def p_unary_expression(self, p):
286     """unary_expression : primary_expression
287                         | unary_operator expression"""
288     p[0] = ListFromConcat(*p[1:])
289
290   def p_unary_operator(self, p):
291     """unary_operator : PLUS
292                       | MINUS
293                       | NOT
294                       | LNOT"""
295     p[0] = p[1]
296
297   def p_primary_expression(self, p):
298     """primary_expression : constant
299                           | identifier
300                           | LPAREN expression RPAREN"""
301     p[0] = ListFromConcat(*p[1:])
302
303   def p_identifier(self, p):
304     """identifier : NAME
305                   | NAME DOT NAME"""
306     p[0] = ''.join(p[1:])
307
308   def p_constant(self, p):
309     """constant : INT_CONST_DEC
310                 | INT_CONST_OCT
311                 | INT_CONST_HEX
312                 | FLOAT_CONST
313                 | HEX_FLOAT_CONST
314                 | CHAR_CONST
315                 | WCHAR_CONST
316                 | STRING_LITERAL
317                 | WSTRING_LITERAL"""
318     p[0] = ListFromConcat(*p[1:])
319
320   def p_error(self, e):
321     print('error: %s'%e)
322
323
324 def Parse(filename):
325   lexer = Lexer()
326   parser = Parser(lexer)
327
328   lex.lex(object=lexer)
329   yacc.yacc(module=parser, debug=0, write_tables=0)
330
331   tree = yacc.parse(open(filename).read())
332   return tree
333
334
335 def Main():
336   if len(sys.argv) < 2:
337     print("usage: %s filename" % (sys.argv[0]))
338     sys.exit(1)
339   tree = Parse(filename=sys.argv[1])
340   print(tree)
341
342
343 if __name__ == '__main__':
344   Main()