OLD | NEW |
| (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 | |
13 # Try to load the ply module, if not, then assume it is in the third_party | |
14 # directory. | |
15 try: | |
16 # Disable lint check which fails to find the ply module. | |
17 # pylint: disable=F0401 | |
18 from ply import lex | |
19 from ply import yacc | |
20 except ImportError: | |
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 | |
26 from ply import lex | |
27 from ply import yacc | |
28 | |
29 | |
30 def ListFromConcat(*items): | |
31 """Generate list by concatenating inputs""" | |
32 itemsout = [] | |
33 for item in items: | |
34 if item is None: | |
35 continue | |
36 if type(item) is not type([]): | |
37 itemsout.append(item) | |
38 else: | |
39 itemsout.extend(item) | |
40 | |
41 return itemsout | |
42 | |
43 | |
44 class Lexer(object): | |
45 | |
46 # This field is required by lex to specify the complete list of valid tokens. | |
47 tokens = ( | |
48 'NAME', | |
49 'NUMBER', | |
50 | |
51 'ARRAY', | |
52 'ORDINAL', | |
53 | |
54 'MODULE', | |
55 'STRUCT', | |
56 'INTERFACE', | |
57 'VOID', | |
58 | |
59 'LCURLY', | |
60 'RCURLY', | |
61 'LPAREN', | |
62 'RPAREN', | |
63 'LBRACKET', | |
64 'RBRACKET', | |
65 'COMMA', | |
66 'SEMICOLON', | |
67 'EQUALS', | |
68 ) | |
69 | |
70 t_LCURLY = r'{' | |
71 t_RCURLY = r'}' | |
72 t_LPAREN = r'\(' | |
73 t_RPAREN = r'\)' | |
74 t_LBRACKET = r'\[' | |
75 t_RBRACKET = r'\]' | |
76 t_COMMA = r',' | |
77 t_SEMICOLON = r';' | |
78 t_EQUALS = r'=' | |
79 t_NAME = r'[a-zA-Z_][a-zA-Z0-9_]*' | |
80 t_ARRAY = r'[a-zA-Z_][a-zA-Z0-9_]*\[\]' | |
81 t_NUMBER = r'\d+' | |
82 t_ORDINAL = r'@[0-9]*' | |
83 | |
84 def t_MODULE(self, t): | |
85 r'module' | |
86 return t | |
87 | |
88 def t_STRUCT(self, t): | |
89 r'struct' | |
90 return t | |
91 | |
92 def t_INTERFACE(self, t): | |
93 r'interface' | |
94 return t | |
95 | |
96 def t_VOID(self, t): | |
97 r'void' | |
98 return t | |
99 | |
100 # Ignore C and C++ style comments | |
101 def t_COMMENT(self, t): | |
102 r'(/\*(.|\n)*?\*/)|(//.*(\n[ \t]*//.*)*)' | |
103 pass | |
104 | |
105 # Ignored characters | |
106 t_ignore = " \t" | |
107 | |
108 def t_newline(self, t): | |
109 r'\n+' | |
110 t.lexer.lineno += t.value.count("\n") | |
111 | |
112 def t_error(self, t): | |
113 print("Illegal character '%s'" % t.value[0]) | |
114 t.lexer.skip(1) | |
115 | |
116 | |
117 class Parser(object): | |
118 | |
119 def __init__(self, lexer): | |
120 self.tokens = lexer.tokens | |
121 | |
122 def p_module(self, p): | |
123 """module : MODULE NAME LCURLY definitions RCURLY""" | |
124 p[0] = ('MODULE', p[2], p[4]) | |
125 | |
126 def p_definitions(self, p): | |
127 """definitions : definition definitions | |
128 |""" | |
129 if len(p) > 1: | |
130 p[0] = ListFromConcat(p[1], p[2]) | |
131 | |
132 def p_definition(self, p): | |
133 """definition : struct | |
134 | interface""" | |
135 p[0] = p[1] | |
136 | |
137 def p_attribute_section(self, p): | |
138 """attribute_section : LBRACKET attributes RBRACKET | |
139 | """ | |
140 if len(p) > 3: | |
141 p[0] = p[2] | |
142 | |
143 def p_attributes(self, p): | |
144 """attributes : attribute | |
145 | attribute COMMA attributes | |
146 | """ | |
147 if len(p) == 2: | |
148 p[0] = ListFromConcat(p[1]) | |
149 elif len(p) > 3: | |
150 p[0] = ListFromConcat(p[1], p[3]) | |
151 | |
152 def p_attribute(self, p): | |
153 """attribute : NAME EQUALS NUMBER | |
154 | NAME EQUALS NAME""" | |
155 p[0] = ('ATTRIBUTE', p[1], p[3]) | |
156 | |
157 def p_struct(self, p): | |
158 """struct : attribute_section STRUCT NAME LCURLY fields RCURLY SEMICOLON""" | |
159 p[0] = ('STRUCT', p[3], p[1], p[5]) | |
160 | |
161 def p_fields(self, p): | |
162 """fields : field fields | |
163 |""" | |
164 if len(p) > 1: | |
165 p[0] = ListFromConcat(p[1], p[2]) | |
166 | |
167 def p_field(self, p): | |
168 """field : typename NAME ordinal SEMICOLON""" | |
169 p[0] = ('FIELD', p[1], p[2], p[3]) | |
170 | |
171 def p_interface(self, p): | |
172 """interface : attribute_section INTERFACE NAME LCURLY methods RCURLY SEMICO
LON""" | |
173 p[0] = ('INTERFACE', p[3], p[1], p[5]) | |
174 | |
175 def p_methods(self, p): | |
176 """methods : method methods | |
177 | """ | |
178 if len(p) > 1: | |
179 p[0] = ListFromConcat(p[1], p[2]) | |
180 | |
181 def p_method(self, p): | |
182 """method : VOID NAME LPAREN parameters RPAREN ordinal SEMICOLON""" | |
183 p[0] = ('METHOD', p[2], p[4], p[6]) | |
184 | |
185 def p_parameters(self, p): | |
186 """parameters : parameter | |
187 | parameter COMMA parameters | |
188 | """ | |
189 if len(p) == 1: | |
190 p[0] = [] | |
191 elif len(p) == 2: | |
192 p[0] = ListFromConcat(p[1]) | |
193 elif len(p) > 3: | |
194 p[0] = ListFromConcat(p[1], p[3]) | |
195 | |
196 def p_parameter(self, p): | |
197 """parameter : typename NAME ordinal""" | |
198 p[0] = ('PARAM', p[1], p[2], p[3]) | |
199 | |
200 def p_typename(self, p): | |
201 """typename : NAME | |
202 | ARRAY""" | |
203 p[0] = p[1] | |
204 | |
205 def p_ordinal(self, p): | |
206 """ordinal : ORDINAL | |
207 | """ | |
208 if len(p) > 1: | |
209 p[0] = p[1] | |
210 | |
211 def p_error(self, e): | |
212 print('error: %s'%e) | |
213 | |
214 | |
215 def Parse(filename): | |
216 lexer = Lexer() | |
217 parser = Parser(lexer) | |
218 | |
219 lex.lex(object=lexer) | |
220 yacc.yacc(module=parser, debug=0, write_tables=0) | |
221 | |
222 tree = yacc.parse(open(filename).read()) | |
223 return tree | |
224 | |
225 | |
226 def Main(): | |
227 if len(sys.argv) < 2: | |
228 print("usage: %s filename" % (sys.argv[0])) | |
229 sys.exit(1) | |
230 tree = Parse(filename=sys.argv[1]) | |
231 print(tree) | |
232 | |
233 | |
234 if __name__ == '__main__': | |
235 Main() | |
OLD | NEW |