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."""
13 # Try to load the ply module, if not, then assume it is in the third_party
16 # Disable lint check which fails to find the ply module.
17 # pylint: disable=F0401
21 module_path, module_name = os.path.split(__file__)
22 third_party = os.path.join(
23 module_path, os.pardir, os.pardir, os.pardir, os.pardir, 'third_party')
24 sys.path.append(third_party)
25 # pylint: disable=F0401
30 def ListFromConcat(*items):
31 """Generate list by concatenating inputs"""
36 if type(item) is not type([]):
46 # This field is required by lex to specify the complete list of valid tokens.
79 t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*'
80 t_ARRAY = r'[a-zA-Z_][a-zA-Z0-9_]*\[\]'
82 t_ORDINAL = r'@[0-9]*'
84 def t_MODULE(self, t):
88 def t_STRUCT(self, t):
92 def t_INTERFACE(self, t):
100 # Ignore C and C++ style comments
101 def t_COMMENT(self, t):
102 r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)'
108 def t_newline(self, t):
110 t.lexer.lineno += t.value.count("\n")
112 def t_error(self, t):
113 print("Illegal character '%s'" % t.value[0])
117 class Parser(object):
119 def __init__(self, lexer):
120 self.tokens = lexer.tokens
122 def p_module(self, p):
123 """module : MODULE NAME LCURLY definitions RCURLY"""
124 p[0] = ('MODULE', p[2], p[4])
126 def p_definitions(self, p):
127 """definitions : definition definitions
130 p[0] = ListFromConcat(p[1], p[2])
132 def p_definition(self, p):
133 """definition : struct
137 def p_attribute_section(self, p):
138 """attribute_section : LBRACKET attributes RBRACKET
143 def p_attributes(self, p):
144 """attributes : attribute
145 | attribute COMMA attributes
148 p[0] = ListFromConcat(p[1])
150 p[0] = ListFromConcat(p[1], p[3])
152 def p_attribute(self, p):
153 """attribute : NAME EQUALS NUMBER"""
154 p[0] = ('ATTRIBUTE', p[1], p[3])
156 def p_struct(self, p):
157 """struct : attribute_section STRUCT NAME LCURLY fields RCURLY SEMICOLON"""
158 p[0] = ('STRUCT', p[3], p[1], p[5])
160 def p_fields(self, p):
161 """fields : field fields
164 p[0] = ListFromConcat(p[1], p[2])
166 def p_field(self, p):
167 """field : typename NAME ordinal SEMICOLON"""
168 p[0] = ('FIELD', p[1], p[2], p[3])
170 def p_interface(self, p):
171 """interface : INTERFACE NAME LCURLY methods RCURLY SEMICOLON"""
172 p[0] = ('INTERFACE', p[2], p[4])
174 def p_methods(self, p):
175 """methods : method methods
178 p[0] = ListFromConcat(p[1], p[2])
180 def p_method(self, p):
181 """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON"""
182 p[0] = ('METHOD', p[2], p[4], p[6])
184 def p_parameters(self, p):
185 """parameters : parameter
186 | parameter COMMA parameters
191 p[0] = ListFromConcat(p[1], p[3])
193 def p_parameter(self, p):
194 """parameter : typename NAME ordinal"""
195 p[0] = ('PARAM', p[1], p[2], p[3])
197 def p_typename(self, p):
202 def p_ordinal(self, p):
208 def p_error(self, e):
214 parser = Parser(lexer)
216 lex.lex(object=lexer)
217 yacc.yacc(module=parser, debug=0, write_tables=0)
219 tree = yacc.parse(open(filename).read())
224 if len(sys.argv) < 2:
225 print("usage: %s filename" % (sys.argv[0]))
227 tree = Parse(filename=sys.argv[1])
231 if __name__ == '__main__':