blob: c660cdbb9011b35ad263fe979981e57f46ad154e [file] [log] [blame]
Enrico Granata4c43add2017-03-15 18:01:34 -07001#!/usr/bin/env python3
2#
3# Copyright (C) 2017 The Android Open Source Project
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16#
17
18# A parser for enum types defined in HIDL.
19# This script can parse HIDL files and generate a parse tree.
20# To use, import and call parse("path/to/file.hal")
Enrico Granata1ddfdef2017-05-31 11:50:08 -070021# It will return a Python dictionary with three keys:
Enrico Granata4c43add2017-03-15 18:01:34 -070022# - header: an instance of Header
23# - enums: a dictionary of EnumDecl objects by name
Enrico Granata1ddfdef2017-05-31 11:50:08 -070024# - structs: a dictionary of StructDecl objects by name
Enrico Granata4c43add2017-03-15 18:01:34 -070025
26# It requires 'ply' (Python Lex/Yacc).
27
Enrico Granata3e8eeed2017-05-05 15:48:01 -070028from __future__ import print_function
29
Enrico Granata4c43add2017-03-15 18:01:34 -070030import ply
31
Sam Lin3ca52fa2020-09-26 15:04:46 -070032tokens = ('package', 'import', 'enum', 'struct', 'typedef',
Enrico Granata4c43add2017-03-15 18:01:34 -070033 'COLON', 'IDENTIFIER', 'COMMENT', 'NUMBER', 'HEX', 'OR', 'EQUALS',
34 'LPAREN', 'RPAREN', 'LBRACE', 'RBRACE', 'DOT', 'SEMICOLON', 'VERSION',
Enrico Granataa109ed62017-03-28 17:01:32 -070035 'COMMA', 'SHIFT', 'LESSTHAN', 'GREATERTHAN')
Enrico Granata4c43add2017-03-15 18:01:34 -070036
37t_COLON = r':'
38t_NUMBER = r'[0-9]+'
Sam Lin3ca52fa2020-09-26 15:04:46 -070039t_HEX = r'0[x|X][0-9A-Fa-f]+'
Enrico Granata4c43add2017-03-15 18:01:34 -070040t_OR = r'\|'
41t_EQUALS = r'='
42t_LPAREN = r'\('
43t_RPAREN = r'\)'
44t_SHIFT = r'<<'
Enrico Granataa109ed62017-03-28 17:01:32 -070045t_LESSTHAN = r'<'
46t_GREATERTHAN = r'>'
Enrico Granata4c43add2017-03-15 18:01:34 -070047
48def t_COMMENT(t):
49 r'(/\*(.|\n)*?\*/)|(//.*)'
50 pass
51
52t_LBRACE = r'{'
53t_RBRACE = r'}'
54t_DOT = r'\.'
55t_SEMICOLON = r';'
56t_VERSION = r'@[0-9].[0-9]'
57t_COMMA = r','
58t_ignore = ' \n\t'
59
60def t_IDENTIFIER(t):
61 r'[a-zA-Z_][a-zA-Z_0-9]*'
62 if t.value == 'package':
63 t.type = 'package'
64 elif t.value == 'import':
65 t.type = 'import'
66 elif t.value == 'enum':
67 t.type = 'enum'
Enrico Granataa109ed62017-03-28 17:01:32 -070068 elif t.value == 'struct':
69 t.type = 'struct'
Sam Lin3ca52fa2020-09-26 15:04:46 -070070 elif t.value == 'typedef':
71 t.type = 'typedef'
Enrico Granata4c43add2017-03-15 18:01:34 -070072 return t
73
74def t_error(t):
75 t.type = t.value[0]
76 t.value = t.value[0]
77 t.lexer.skip(1)
78 return t
79
80import ply.lex as lex
81lexer = lex.lex()
82
Enrico Granataa109ed62017-03-28 17:01:32 -070083class Typename(object):
84 pass
85
86class SimpleTypename(Typename):
87 def __init__(self, name):
88 self.name = name
89
90 def __str__(self):
91 return self.name
92
93class GenericTypename(Typename):
94 def __init__(self, name, arg):
95 self.name = name
96 self.arg = arg
97
98 def __str__(self):
99 return '%s<%s>' % (self.name, self.arg)
100
Enrico Granata4c43add2017-03-15 18:01:34 -0700101class EnumHeader(object):
102 def __init__(self, name, base):
103 self.name = name
104 self.base = base
105
106 def __str__(self):
107 return '%s%s' % (self.name, ' %s' % self.base if self.base else '')
108
Enrico Granataa109ed62017-03-28 17:01:32 -0700109class StructHeader(object):
110 def __init__(self, name):
111 self.name = name
112
113 def __str__(self):
114 return 'struct %s' % self.name
115
Sam Lin3ca52fa2020-09-26 15:04:46 -0700116class TypedefHeader(object):
117 def __init__(self, name):
118 self.name = name
119
120 def __str__(self):
121 return 'typedef %s' % self.name
122
Enrico Granata4c43add2017-03-15 18:01:34 -0700123class EnumDecl(object):
124 def __init__(self, header, cases):
125 self.header = header
126 self.cases = cases
Enrico Granataa109ed62017-03-28 17:01:32 -0700127 self.fillInValues()
128
129 def fillInValues(self):
130 # if no cases, we're done
131 if len(self.cases) < 1: return
132 # then, if case 0 has no value, set it to 0
133 if self.cases[0].value is None:
134 self.cases[0].value = EnumValueConstant("0")
135 # then for all other cases...
136 for i in range(1,len(self.cases)):
137 # ...if there's no value
138 if self.cases[i].value is None:
139 # set to previous case + 1
140 self.cases[i].value = EnumValueSuccessor(
141 EnumValueLocalRef(self.cases[i-1].name))
Enrico Granata4c43add2017-03-15 18:01:34 -0700142
143 def __str__(self):
144 return '%s {\n%s\n}' % (self.header,
145 '\n'.join(str(x) for x in self.cases))
146
147 def __repr__(self):
148 return self.__str__()
149
Enrico Granataa109ed62017-03-28 17:01:32 -0700150class StructDecl(object):
151 def __init__(self, header, items):
152 self.header = header
153 self.items = items
154
155 def __str__(self):
156 return '%s {\n%s\n}' % (self.header,
157 '\n'.join(str(x) for x in self.items))
158
159 def __repr__(self):
160 return self.__str__()
161
Sam Lin3ca52fa2020-09-26 15:04:46 -0700162class TypedefDecl(object):
163 def __init__(self, header, name):
164 self.header = header
165 self.name = name
166
167 def __str__(self):
168 return '%s {\n%s\n}' % (self.header,
169 self.name)
170
171 def __repr__(self):
172 return self.__str__()
173
Enrico Granataa109ed62017-03-28 17:01:32 -0700174class StructElement(object):
175 pass
176
177class StructElementIVar(StructElement):
178 def __init__(self, typename, name):
179 self.typename = typename
180 self.name = name
181
182 def __str__(self):
183 return '%s %s' % (self.typename, self.name)
184
185class StructElementStruct(StructElement):
186 def __init__(self, struct):
187 self.name = struct.header.name
188 self.struct = struct
189
190 def __str__(self):
191 return self.struct.__str__()
192
Enrico Granata4c43add2017-03-15 18:01:34 -0700193class EnumCase(object):
194 def __init__(self, name, value):
195 self.name = name
196 self.value = value
197
198 def __str__(self):
199 return '%s = %s' % (self.name, self.value)
200
201class PackageID(object):
202 def __init__(self, name, version):
203 self.name = name
204 self.version = version
205
206 def __str__(self):
207 return '%s%s' % (self.name, self.version)
208
209class Package(object):
210 def __init__(self, package):
211 self.package = package
212
213 def __str__(self):
214 return 'package %s' % self.package
215
216class Import(object):
217 def __init__(self, package):
218 self.package = package
219
220 def __str__(self):
221 return 'import %s' % self.package
222
223class Header(object):
224 def __init__(self, package, imports):
225 self.package = package
226 self.imports = imports
227
228 def __str__(self):
229 return str(self.package) + "\n" + \
230 '\n'.join(str(x) for x in self.imports)
231
Enrico Granataa109ed62017-03-28 17:01:32 -0700232class EnumValue(object):
233 def resolve(self, enum, document):
234 pass
235
236class EnumValueConstant(EnumValue):
237 def __init__(self, value):
238 self.value = value
239
240 def __str__(self):
241 return self.value
242
243 def resolve(self, enum, document):
Sam Lin3ca52fa2020-09-26 15:04:46 -0700244 if self.value.lower().startswith("0x"):
Enrico Granataa109ed62017-03-28 17:01:32 -0700245 return int(self.value, 16)
246 else:
247 return int(self.value, 10)
248
249class EnumValueSuccessor(EnumValue):
250 def __init__(self, value):
251 self.value = value
252
253 def __str__(self):
254 return '%s + 1' % self.value
255
256 def resolve(self, enum, document):
257 return self.value.resolve(enum, document) + 1
258
259class EnumValueLocalRef(EnumValue):
260 def __init__(self, ref):
261 self.ref = ref
262
263 def __str__(self):
264 return self.ref
265
266 def resolve(self, enum, document):
267 for case in enum.cases:
268 if case.name == self.ref: return case.value.resolve(enum, document)
269
Scott Randolph4ce965a2017-05-08 15:52:34 -0700270class EnumValueLShift(EnumValue):
Enrico Granataa109ed62017-03-28 17:01:32 -0700271 def __init__(self, base, offset):
272 self.base = base
273 self.offset = offset
274
275 def __str__(self):
276 return '%s << %s' % (self.base, self.offset)
277
278 def resolve(self, enum, document):
279 base = self.base.resolve(enum, document)
280 offset = self.offset.resolve(enum, document)
281 return base << offset
282
283class EnumValueOr(EnumValue):
284 def __init__(self, param1, param2):
285 self.param1 = param1
286 self.param2 = param2
287
288 def __str__(self):
289 return '%s | %s' % (self.param1, self.param2)
290
291 def resolve(self, enum, document):
292 param1 = self.param1.resolve(enum, document)
293 param2 = self.param2.resolve(enum, document)
294 return param1 | param2
295
296class EnumValueExternRef(EnumValue):
297 def __init__(self, where, ref):
298 self.where = where
299 self.ref = ref
300
301 def __str__(self):
302 return '%s:%s' % (self.where, self.ref)
303
304 def resolve(self, enum, document):
305 enum = document['enums'][self.where]
306 return EnumValueLocalRef(self.ref).resolve(enum, document)
307
Sam Lin3ca52fa2020-09-26 15:04:46 -0700308class Typedef(object):
309 def __init__(self, header, name):
310 self.header = header
311 self.name = name
312
313 def __str__(self):
314 return 'typedef %s %s' % (self.typename, self.name)
315
Enrico Granata4c43add2017-03-15 18:01:34 -0700316# Error rule for syntax errors
317def p_error(p):
318 print("Syntax error in input: %s" % p)
Enrico Granataa109ed62017-03-28 17:01:32 -0700319 try:
320 while True:
321 print(p.lexer.next().value, end=' ')
322 except:
323 pass
Enrico Granata4c43add2017-03-15 18:01:34 -0700324
325def p_document(t):
Enrico Granataa109ed62017-03-28 17:01:32 -0700326 'document : header type_decls'
Enrico Granata4c43add2017-03-15 18:01:34 -0700327 enums = {}
Enrico Granataa109ed62017-03-28 17:01:32 -0700328 structs = {}
Sam Lin3ca52fa2020-09-26 15:04:46 -0700329 typedefs = {}
Enrico Granata4c43add2017-03-15 18:01:34 -0700330 for enum in t[2]:
Enrico Granataa109ed62017-03-28 17:01:32 -0700331 if not isinstance(enum, EnumDecl): continue
Enrico Granata4c43add2017-03-15 18:01:34 -0700332 enums[enum.header.name] = enum
Enrico Granataa109ed62017-03-28 17:01:32 -0700333 for struct in t[2]:
334 if not isinstance(struct, StructDecl): continue
335 structs[struct.header.name] = struct
Sam Lin3ca52fa2020-09-26 15:04:46 -0700336 for typedef in t[2]:
337 if not isinstance(typedef, TypedefDecl): continue
338 typedefs[typedef.header.name] = typedef
339
340 t[0] = {'header' : t[1], 'enums' : enums, 'structs' : structs, 'typedefs' : typedef}
Enrico Granata4c43add2017-03-15 18:01:34 -0700341
Enrico Granataa109ed62017-03-28 17:01:32 -0700342def p_type_decls_1(t):
343 'type_decls : type_decl'
Enrico Granata4c43add2017-03-15 18:01:34 -0700344 t[0] = [t[1]]
Enrico Granataa109ed62017-03-28 17:01:32 -0700345def p_type_decls_2(t):
346 'type_decls : type_decls type_decl'
Enrico Granata4c43add2017-03-15 18:01:34 -0700347 t[0] = t[1] + [t[2]]
348
Enrico Granataa109ed62017-03-28 17:01:32 -0700349def p_type_decl_e(t):
350 'type_decl : enum_decl'
351 t[0] = t[1]
352def p_type_decl_s(t):
353 'type_decl : struct_decl'
354 t[0] = t[1]
Sam Lin3ca52fa2020-09-26 15:04:46 -0700355def p_type_decl_t(t):
356 'type_decl : typedef_decl'
357 t[0] = t[1]
Enrico Granataa109ed62017-03-28 17:01:32 -0700358
Enrico Granata4c43add2017-03-15 18:01:34 -0700359def p_enum_cases_1(t):
360 'enum_cases : enum_case'
361 t[0] = [t[1]]
362def p_enum_cases_2(t):
363 'enum_cases : enum_cases COMMA enum_case'
364 t[0] = t[1] + [t[3]]
365
Enrico Granataa109ed62017-03-28 17:01:32 -0700366def p_struct_elements_1(t):
367 'struct_elements : struct_element'
368 t[0] = [t[1]]
369def p_struct_elements_2(t):
370 'struct_elements : struct_elements struct_element'
371 t[0] = t[1] + [t[2]]
372
Enrico Granata4c43add2017-03-15 18:01:34 -0700373def p_enum_base_1(t):
374 'enum_base : VERSION COLON COLON IDENTIFIER'
375 t[0] = '%s::%s' % (t[1], t[4])
376def p_enum_base_2(t):
377 'enum_base : IDENTIFIER'
378 t[0] = t[1]
379
Sam Lin3ca52fa2020-09-26 15:04:46 -0700380def p_typedef_name(t):
381 'typedef_name : IDENTIFIER'
382 t[0] = t[1]
383
Enrico Granataa109ed62017-03-28 17:01:32 -0700384def p_struct_header(t):
385 'struct_header : struct IDENTIFIER'
386 t[0] = StructHeader(t[2])
387
Enrico Granata4c43add2017-03-15 18:01:34 -0700388def p_enum_header_1(t):
389 'enum_header : enum IDENTIFIER'
390 t[0] = EnumHeader(t[2], None)
391def p_enum_header_2(t):
392 'enum_header : enum IDENTIFIER COLON enum_base'
393 t[0] = EnumHeader(t[2], t[4])
394
Sam Lin3ca52fa2020-09-26 15:04:46 -0700395def p_typedef_header(t):
396 'typedef_header : typedef IDENTIFIER'
397 t[0] = TypedefHeader(t[2])
398
Enrico Granataa109ed62017-03-28 17:01:32 -0700399def p_struct_decl(t):
400 'struct_decl : struct_header LBRACE struct_elements RBRACE SEMICOLON'
401 t[0] = StructDecl(t[1], t[3])
402
Enrico Granata4c43add2017-03-15 18:01:34 -0700403def p_enum_decl_1(t):
404 'enum_decl : enum_header LBRACE enum_cases RBRACE SEMICOLON'
405 t[0] = EnumDecl(t[1], t[3])
406def p_enum_decl_2(t):
407 'enum_decl : enum_header LBRACE enum_cases COMMA RBRACE SEMICOLON'
408 t[0] = EnumDecl(t[1], t[3])
409
Sam Lin3ca52fa2020-09-26 15:04:46 -0700410def p_typedef_decl(t):
411 'typedef_decl : typedef_header typedef_name SEMICOLON'
412 t[0] = TypedefDecl(t[1], t[2])
413
Enrico Granata4c43add2017-03-15 18:01:34 -0700414def p_enum_value_1(t):
415 '''enum_value : NUMBER
Enrico Granataa109ed62017-03-28 17:01:32 -0700416 | HEX'''
417 t[0] = EnumValueConstant(t[1])
Enrico Granata4c43add2017-03-15 18:01:34 -0700418def p_enum_value_2(t):
419 'enum_value : enum_value SHIFT NUMBER'
Scott Randolph4ce965a2017-05-08 15:52:34 -0700420 t[0] = EnumValueLShift(t[1], EnumValueConstant(t[3]))
Enrico Granata4c43add2017-03-15 18:01:34 -0700421def p_enum_value_3(t):
422 'enum_value : enum_value OR enum_value'
Enrico Granataa109ed62017-03-28 17:01:32 -0700423 t[0] = EnumValueOr(t[1], t[3])
Enrico Granata4c43add2017-03-15 18:01:34 -0700424def p_enum_value_4(t):
425 'enum_value : LPAREN enum_value RPAREN'
426 t[0] = t[2]
427def p_enum_value_5(t):
428 'enum_value : IDENTIFIER COLON IDENTIFIER'
Enrico Granataa109ed62017-03-28 17:01:32 -0700429 t[0] = EnumValueExternRef(t[1],t[3])
430def p_enum_value_6(t):
431 'enum_value : IDENTIFIER'
432 t[0] = EnumValueLocalRef(t[1])
Enrico Granata4c43add2017-03-15 18:01:34 -0700433
Enrico Granataa109ed62017-03-28 17:01:32 -0700434def p_typename_v(t):
435 'typename : IDENTIFIER'
436 t[0] = SimpleTypename(t[1])
437def p_typename_g(t):
438 'typename : IDENTIFIER LESSTHAN IDENTIFIER GREATERTHAN'
439 t[0] = GenericTypename(t[1], t[3])
440
441def p_struct_element_ivar(t):
442 'struct_element : typename IDENTIFIER SEMICOLON'
443 t[0] = StructElementIVar(t[1], t[2])
444
445def p_struct_element_struct(t):
446 'struct_element : struct_decl'
447 t[0] = StructElementStruct(t[1])
448
449def p_enum_case_v(t):
Enrico Granata4c43add2017-03-15 18:01:34 -0700450 'enum_case : IDENTIFIER EQUALS enum_value'
451 t[0] = EnumCase(t[1], t[3])
Enrico Granataa109ed62017-03-28 17:01:32 -0700452def p_enum_case_b(t):
453 'enum_case : IDENTIFIER'
454 t[0] = EnumCase(t[1], None)
Enrico Granata4c43add2017-03-15 18:01:34 -0700455
456def p_header_1(t):
457 'header : package_decl'
458 t[0] = Header(t[1], [])
459
460def p_header_2(t):
461 'header : package_decl import_decls'
462 t[0] = Header(t[1], t[2])
463
464def p_import_decls_1(t):
465 'import_decls : import_decl'
466 t[0] = [t[1]]
467
468def p_import_decls_2(t):
469 'import_decls : import_decls import_decl'
470 t[0] = t[1] + [t[2]]
471
472def p_package_decl(t):
473 'package_decl : package package_ID SEMICOLON'
474 t[0] = Package(t[2])
475
476def p_import_decl(t):
477 'import_decl : import package_ID SEMICOLON'
478 t[0] = Import(t[2])
479
480def p_package_ID(t):
481 'package_ID : dotted_identifier VERSION'
482 t[0] = PackageID(t[1], t[2])
483
484def p_dotted_identifier_1(t):
485 'dotted_identifier : IDENTIFIER'
486 t[0] = t[1]
487def p_dotted_identifier_2(t):
488 'dotted_identifier : dotted_identifier DOT IDENTIFIER'
489 t[0] = t[1] + '.' + t[3]
490
491class SilentLogger(object):
492 def warning(*args):
493 pass
Sam Lin3ca52fa2020-09-26 15:04:46 -0700494 def error(*args):
495 print(args)
Enrico Granata4c43add2017-03-15 18:01:34 -0700496
497import ply.yacc as yacc
498parser = yacc.yacc(debug=False, write_tables=False, errorlog=SilentLogger())
499import sys
500
501def parse(filename):
502 return parser.parse(open(filename, 'r').read())