OLD | NEW |
---|---|
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import collections | 7 import collections |
8 import re | 8 import re |
9 import optparse | 9 import optparse |
10 import os | 10 import os |
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
117 DirectiveSet.prefix_to_strip_key) | 117 DirectiveSet.prefix_to_strip_key) |
118 | 118 |
119 | 119 |
120 class HeaderParser(object): | 120 class HeaderParser(object): |
121 single_line_comment_re = re.compile(r'\s*//') | 121 single_line_comment_re = re.compile(r'\s*//') |
122 multi_line_comment_start_re = re.compile(r'\s*/\*') | 122 multi_line_comment_start_re = re.compile(r'\s*/\*') |
123 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') | 123 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') |
124 enum_end_re = re.compile(r'^\s*}\s*;\.*$') | 124 enum_end_re = re.compile(r'^\s*}\s*;\.*$') |
125 generator_directive_re = re.compile( | 125 generator_directive_re = re.compile( |
126 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') | 126 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') |
127 multi_line_generator_directive_start_re = re.compile( | |
128 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]*)\\$') | |
129 multi_line_directive_continuation_re = re.compile( | |
130 r'^\s*//\s+([\.\w]+)\\$') | |
131 multi_line_directive_end_re = re.compile( | |
132 r'^\s*//\s+([\.\w]*)$') | |
127 | 133 |
128 optional_class_or_struct_re = r'(class|struct)?' | 134 optional_class_or_struct_re = r'(class|struct)?' |
129 enum_name_re = r'(\w+)' | 135 enum_name_re = r'(\w+)' |
130 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' | 136 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' |
131 enum_start_re = re.compile(r'^\s*enum\s+' + optional_class_or_struct_re + | 137 enum_start_re = re.compile(r'^\s*enum\s+' + optional_class_or_struct_re + |
132 '\s*' + enum_name_re + '\s*' + optional_fixed_type_re + '\s*{\s*$') | 138 '\s*' + enum_name_re + '\s*' + optional_fixed_type_re + '\s*{\s*$') |
133 | 139 |
134 def __init__(self, lines): | 140 def __init__(self, lines, path=None): |
135 self._lines = lines | 141 self._lines = lines |
142 self._path = path | |
136 self._enum_definitions = [] | 143 self._enum_definitions = [] |
137 self._in_enum = False | 144 self._in_enum = False |
138 self._current_definition = None | 145 self._current_definition = None |
139 self._generator_directives = DirectiveSet() | 146 self._generator_directives = DirectiveSet() |
147 self._multi_line_generator_directive = None | |
140 | 148 |
141 def ParseDefinitions(self): | 149 def ParseDefinitions(self): |
142 for line in self._lines: | 150 for line in self._lines: |
143 self._ParseLine(line) | 151 self._ParseLine(line) |
144 return self._enum_definitions | 152 return self._enum_definitions |
145 | 153 |
146 def _ParseLine(self, line): | 154 def _ParseLine(self, line): |
147 if not self._in_enum: | 155 if not self._in_enum: |
148 self._ParseRegularLine(line) | 156 self._ParseRegularLine(line) |
149 else: | 157 else: |
150 self._ParseEnumLine(line) | 158 self._ParseEnumLine(line) |
151 | 159 |
152 def _ParseEnumLine(self, line): | 160 def _ParseEnumLine(self, line): |
153 if HeaderParser.single_line_comment_re.match(line): | 161 if HeaderParser.single_line_comment_re.match(line): |
154 return | 162 return |
155 if HeaderParser.multi_line_comment_start_re.match(line): | 163 if HeaderParser.multi_line_comment_start_re.match(line): |
156 raise Exception('Multi-line comments in enums are not supported.') | 164 raise Exception('Multi-line comments in enums are not supported in ' + |
165 self._path) | |
157 enum_end = HeaderParser.enum_end_re.match(line) | 166 enum_end = HeaderParser.enum_end_re.match(line) |
158 enum_entry = HeaderParser.enum_line_re.match(line) | 167 enum_entry = HeaderParser.enum_line_re.match(line) |
159 if enum_end: | 168 if enum_end: |
160 self._ApplyGeneratorDirectives() | 169 self._ApplyGeneratorDirectives() |
161 self._current_definition.Finalize() | 170 self._current_definition.Finalize() |
162 self._enum_definitions.append(self._current_definition) | 171 self._enum_definitions.append(self._current_definition) |
163 self._in_enum = False | 172 self._in_enum = False |
164 elif enum_entry: | 173 elif enum_entry: |
165 enum_key = enum_entry.groups()[0] | 174 enum_key = enum_entry.groups()[0] |
166 enum_value = enum_entry.groups()[2] | 175 enum_value = enum_entry.groups()[2] |
167 self._current_definition.AppendEntry(enum_key, enum_value) | 176 self._current_definition.AppendEntry(enum_key, enum_value) |
168 | 177 |
169 def _ApplyGeneratorDirectives(self): | 178 def _ApplyGeneratorDirectives(self): |
170 self._generator_directives.UpdateDefinition(self._current_definition) | 179 self._generator_directives.UpdateDefinition(self._current_definition) |
171 self._generator_directives = DirectiveSet() | 180 self._generator_directives = DirectiveSet() |
172 | 181 |
173 def _ParseRegularLine(self, line): | 182 def _ParseRegularLine(self, line): |
174 enum_start = HeaderParser.enum_start_re.match(line) | 183 enum_start = HeaderParser.enum_start_re.match(line) |
jbudorick
2015/01/09 16:39:17
nit: you don't need to run these three regexes if
mkosiba (inactive)
2015/01/09 17:09:57
Done.
| |
175 generator_directive = HeaderParser.generator_directive_re.match(line) | 184 generator_directive = HeaderParser.generator_directive_re.match(line) |
176 if enum_start: | 185 multi_line_generator_directive_start = ( |
186 HeaderParser.multi_line_generator_directive_start_re.match(line)) | |
187 | |
188 if self._multi_line_generator_directive: | |
189 multi_line_directive_continuation = ( | |
190 HeaderParser.multi_line_directive_continuation_re.match(line)) | |
191 multi_line_directive_end = ( | |
192 HeaderParser.multi_line_directive_end_re.match(line)) | |
193 | |
194 if multi_line_directive_continuation: | |
195 value_cont = multi_line_directive_continuation.groups()[0] | |
196 self._multi_line_generator_directive[1].append(value_cont) | |
197 elif multi_line_directive_end: | |
198 directive_name = self._multi_line_generator_directive[0] | |
199 directive_value = "".join(self._multi_line_generator_directive[1]) | |
200 directive_value += multi_line_directive_end.groups()[0] | |
201 self._multi_line_generator_directive = None | |
202 self._generator_directives.Update(directive_name, directive_value) | |
203 else: | |
204 raise Exception('Malformed multi-line directive declaration in ' + | |
205 self._path) | |
206 elif generator_directive: | |
207 directive_name = generator_directive.groups()[0] | |
208 directive_value = generator_directive.groups()[1] | |
209 self._generator_directives.Update(directive_name, directive_value) | |
210 elif multi_line_generator_directive_start: | |
211 directive_name = multi_line_generator_directive_start.groups()[0] | |
212 directive_value = multi_line_generator_directive_start.groups()[1] | |
213 self._multi_line_generator_directive = (directive_name, [directive_value]) | |
214 elif enum_start: | |
177 if self._generator_directives.empty: | 215 if self._generator_directives.empty: |
178 return | 216 return |
179 self._current_definition = EnumDefinition( | 217 self._current_definition = EnumDefinition( |
180 original_enum_name=enum_start.groups()[1], | 218 original_enum_name=enum_start.groups()[1], |
181 fixed_type=enum_start.groups()[3]) | 219 fixed_type=enum_start.groups()[3]) |
182 self._in_enum = True | 220 self._in_enum = True |
183 elif generator_directive: | |
184 directive_name = generator_directive.groups()[0] | |
185 directive_value = generator_directive.groups()[1] | |
186 self._generator_directives.Update(directive_name, directive_value) | |
187 | |
188 | 221 |
189 def GetScriptName(): | 222 def GetScriptName(): |
190 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) | 223 script_components = os.path.abspath(sys.argv[0]).split(os.path.sep) |
191 build_index = script_components.index('build') | 224 build_index = script_components.index('build') |
192 return os.sep.join(script_components[build_index:]) | 225 return os.sep.join(script_components[build_index:]) |
193 | 226 |
194 | 227 |
195 def DoGenerate(options, source_paths): | 228 def DoGenerate(options, source_paths): |
196 output_paths = [] | 229 output_paths = [] |
197 for source_path in source_paths: | 230 for source_path in source_paths: |
198 enum_definitions = DoParseHeaderFile(source_path) | 231 enum_definitions = DoParseHeaderFile(source_path) |
199 for enum_definition in enum_definitions: | 232 for enum_definition in enum_definitions: |
200 package_path = enum_definition.enum_package.replace('.', os.path.sep) | 233 package_path = enum_definition.enum_package.replace('.', os.path.sep) |
201 file_name = enum_definition.class_name + '.java' | 234 file_name = enum_definition.class_name + '.java' |
202 output_path = os.path.join(options.output_dir, package_path, file_name) | 235 output_path = os.path.join(options.output_dir, package_path, file_name) |
203 output_paths.append(output_path) | 236 output_paths.append(output_path) |
204 if not options.print_output_only: | 237 if not options.print_output_only: |
205 build_utils.MakeDirectory(os.path.dirname(output_path)) | 238 build_utils.MakeDirectory(os.path.dirname(output_path)) |
206 DoWriteOutput(source_path, output_path, enum_definition) | 239 DoWriteOutput(source_path, output_path, enum_definition) |
207 return output_paths | 240 return output_paths |
208 | 241 |
209 | 242 |
210 def DoParseHeaderFile(path): | 243 def DoParseHeaderFile(path): |
211 with open(path) as f: | 244 with open(path) as f: |
212 return HeaderParser(f.readlines()).ParseDefinitions() | 245 return HeaderParser(f.readlines(), path).ParseDefinitions() |
213 | 246 |
214 | 247 |
215 def GenerateOutput(source_path, enum_definition): | 248 def GenerateOutput(source_path, enum_definition): |
216 template = Template(""" | 249 template = Template(""" |
217 // Copyright 2014 The Chromium Authors. All rights reserved. | 250 // Copyright 2014 The Chromium Authors. All rights reserved. |
218 // Use of this source code is governed by a BSD-style license that can be | 251 // Use of this source code is governed by a BSD-style license that can be |
219 // found in the LICENSE file. | 252 // found in the LICENSE file. |
220 | 253 |
221 // This file is autogenerated by | 254 // This file is autogenerated by |
222 // ${SCRIPT_NAME} | 255 // ${SCRIPT_NAME} |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 | 311 |
279 output_paths = DoGenerate(options, args) | 312 output_paths = DoGenerate(options, args) |
280 | 313 |
281 if options.assert_files_list: | 314 if options.assert_files_list: |
282 AssertFilesList(output_paths, options.assert_files_list) | 315 AssertFilesList(output_paths, options.assert_files_list) |
283 | 316 |
284 return " ".join(output_paths) | 317 return " ".join(output_paths) |
285 | 318 |
286 if __name__ == '__main__': | 319 if __name__ == '__main__': |
287 DoMain(sys.argv[1:]) | 320 DoMain(sys.argv[1:]) |
OLD | NEW |