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.
6 """Generates a syntax tree from a Mojo IDL file."""
12 # Try to load the ply module, if not, then assume it is in the third_party
15 # Disable lint check which fails to find the ply module.
16 # pylint: disable=F0401
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
28 from mojo_lexer import Lexer
31 def ListFromConcat(*items):
32 """Generate list by concatenating inputs"""
37 if type(item) is not type([]):
47 def __init__(self, lexer):
48 self.tokens = lexer.tokens
54 p[0] = ListFromConcat(p[1], p[2])
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]))
63 def p_module(self, p):
64 """module : MODULE NAME LBRACE definitions RBRACE"""
65 p[0] = ('MODULE', p[2], p[4])
67 def p_definitions(self, p):
68 """definitions : definition definitions
71 p[0] = ListFromConcat(p[1], p[2])
73 def p_definition(self, p):
74 """definition : struct
79 def p_attribute_section(self, p):
80 """attribute_section : LBRACKET attributes RBRACKET
85 def p_attributes(self, p):
86 """attributes : attribute
87 | attribute COMMA attributes
90 p[0] = ListFromConcat(p[1])
92 p[0] = ListFromConcat(p[1], p[3])
94 def p_attribute(self, p):
95 """attribute : NAME EQUALS expression
97 p[0] = ('ATTRIBUTE', p[1], p[3])
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])
103 def p_struct_body(self, p):
104 """struct_body : field struct_body
108 p[0] = ListFromConcat(p[1], p[2])
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])
114 def p_default(self, p):
115 """default : EQUALS expression
116 | EQUALS expression_object
121 def p_interface(self, p):
122 """interface : attribute_section INTERFACE NAME LBRACE interface_body \
124 p[0] = ('INTERFACE', p[3], p[1], p[5])
126 def p_interface_body(self, p):
127 """interface_body : method interface_body
128 | enum interface_body
131 p[0] = ListFromConcat(p[1], p[2])
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])
137 def p_parameters(self, p):
138 """parameters : parameter
139 | parameter COMMA parameters
144 p[0] = ListFromConcat(p[1])
146 p[0] = ListFromConcat(p[1], p[3])
148 def p_parameter(self, p):
149 """parameter : typename NAME ordinal"""
150 p[0] = ('PARAM', p[1], p[2], p[3])
152 def p_typename(self, p):
153 """typename : basictypename
157 def p_basictypename(self, p):
158 """basictypename : NAME
161 | specializedhandle"""
165 p[0] = p[1] + '.' + p[3]
167 def p_specializedhandle(self, p):
168 """specializedhandle : HANDLE LT specializedhandlename GT"""
169 p[0] = "handle<" + p[3] + ">"
171 def p_specializedhandlename(self, p):
172 """specializedhandlename : DATA_PIPE_CONSUMER
177 def p_array(self, p):
178 """array : basictypename LBRACKET RBRACKET"""
181 def p_ordinal(self, p):
188 """enum : ENUM NAME LBRACE enum_fields RBRACE SEMI"""
189 p[0] = ('ENUM', p[2], p[4])
191 def p_enum_fields(self, p):
192 """enum_fields : enum_field
193 | enum_field COMMA enum_fields
196 p[0] = ListFromConcat(p[1])
198 p[0] = ListFromConcat(p[1], p[3])
200 def p_enum_field(self, p):
202 | NAME EQUALS expression"""
204 p[0] = ('ENUM_FIELD', p[1], None)
206 p[0] = ('ENUM_FIELD', p[1], p[3])
210 def p_expression_object(self, p):
211 """expression_object : expression_array
212 | LBRACE expression_object_elements RBRACE """
216 p[0] = ('OBJECT', p[2])
218 def p_expression_object_elements(self, p):
219 """expression_object_elements : expression_object
220 | expression_object COMMA expression_object_elements
223 p[0] = ListFromConcat(p[1])
225 p[0] = ListFromConcat(p[1], p[3])
227 def p_expression_array(self, p):
228 """expression_array : expression
229 | LBRACKET expression_array_elements RBRACKET """
233 p[0] = ('ARRAY', p[2])
235 def p_expression_array_elements(self, p):
236 """expression_array_elements : expression_object
237 | expression_object COMMA expression_array_elements
240 p[0] = ListFromConcat(p[1])
242 p[0] = ListFromConcat(p[1], p[3])
244 def p_expression(self, p):
245 """expression : conditional_expression"""
246 p[0] = ('EXPRESSION', p[1])
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:])
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 \
262 p[0] = ListFromConcat(*p[1:])
264 def p_binary_operator(self, p):
265 """binary_operator : TIMES
285 def p_unary_expression(self, p):
286 """unary_expression : primary_expression
287 | unary_operator expression"""
288 p[0] = ListFromConcat(*p[1:])
290 def p_unary_operator(self, p):
291 """unary_operator : PLUS
297 def p_primary_expression(self, p):
298 """primary_expression : constant
300 | LPAREN expression RPAREN"""
301 p[0] = ListFromConcat(*p[1:])
303 def p_identifier(self, p):
306 p[0] = ''.join(p[1:])
308 def p_constant(self, p):
309 """constant : INT_CONST_DEC
318 p[0] = ListFromConcat(*p[1:])
320 def p_error(self, e):
326 parser = Parser(lexer)
328 lex.lex(object=lexer)
329 yacc.yacc(module=parser, debug=0, write_tables=0)
331 tree = yacc.parse(open(filename).read())
336 if len(sys.argv) < 2:
337 print("usage: %s filename" % (sys.argv[0]))
339 tree = Parse(filename=sys.argv[1])
343 if __name__ == '__main__':