├── .gitignore ├── .travis.yml ├── COPYING ├── MANIFEST.in ├── README.md ├── example ├── parse_expr.py ├── symbols.py └── symbols_visitor.py ├── plyj ├── __init__.py ├── model.py └── parser.py ├── setup.py └── test ├── __init__.py ├── compilation_unit.py ├── expressions.py ├── statements.py └── type_declaration.py /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea/* 2 | *.egg-info 3 | .eggs/ 4 | 5 | *.py[co] 6 | 7 | lextab.py 8 | parsetab.py 9 | parser.out 10 | 11 | .coverage 12 | cover/ 13 | dist/ 14 | build/ 15 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: python 2 | python: 3 | - 2.7 4 | - 3.2 5 | install: pip install ply 6 | script: python setup.py test 7 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright (c) 2012-2015, Werner Hahn 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 1. Redistributions of source code must retain the above copyright notice, 7 | this list of conditions and the following disclaimer. 8 | 2. Redistributions in binary form must reproduce the above copyright notice, 9 | this list of conditions and the following disclaimer in the documentation 10 | and/or other materials provided with the distribution. 11 | 3. The name of the author may not be used to endorse or promote products 12 | derived from this software without specific prior written permission. 13 | 14 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 15 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 18 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 19 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 20 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 21 | INTERRUPTION) HOWEVER CAUSED AND ONANY THEORY OF LIABILITY, WHETHER IN 22 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 23 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 | POSSIBILITY OF SUCH DAMAGE. 25 | 26 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include COPYING 2 | include README.md 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | plyj [![Build Status](https://secure.travis-ci.org/musiKk/plyj.png?branch=master)](http://travis-ci.org/musiKk/plyj) 2 | ==== 3 | 4 | plyj is a Java 7 parser written in Python. It has the awesome [PLY] as its sole dependency. 5 | 6 | Status 7 | ------ 8 | 9 | **plyj is officially in maintenance mode.** For the foreseeable future no new developments will be made by me. As explained below plyj is basically a manual transcription of JDT's grammar. This has served me well in the past but with the Java 8 features JDT's developers did some things I'm unable to reproduce with PLY. I'm not smart enough to do this on my own. Writing parsers is still black magic to me. I am not thrilled by this development. 10 | 11 | Synopsis 12 | -------- 13 | 14 | ```python 15 | import plyj.parser as plyj 16 | 17 | parser = plyj.Parser() 18 | 19 | # parse a compilation unit from a file 20 | tree = parser.parse_file(file('/foo/bar/Baz.java')) 21 | 22 | # parse a compilation unit from a string 23 | tree = parser.parse_string('class Foo { }') 24 | 25 | # parse expression from string 26 | tree = parser.parse_expression('1 / 2 * (float) 3') 27 | 28 | # slightly bigger example: parse from an installed JDK with sources 29 | import zipfile 30 | srczip = zipfile.ZipFile('/usr/lib/jvm/java-6-openjdk/src.zip', mode='r') 31 | info = srczip.getinfo('java/lang/Object.java') 32 | srcfile = srczip.open(info) 33 | tree = parser.parse_file(srcfile) 34 | ``` 35 | 36 | Acknowledgement 37 | --------------- 38 | 39 | plyj is more or less a 1:1 translation of the grammar used in the [Java Development Tools] for Eclipse. 40 | 41 | Completeness 42 | ------------ 43 | 44 | The grammar is complete. There may still be errors left though. It successfully parsed every source file of the Oracle JDK. A lot of bugs were found that way but for all I know there may be many more. Time will tell. 45 | 46 | Contributions 47 | ------------- 48 | 49 | Contributions are always welcome. Depending on the type of work it may 50 | take a little while until I get around to accepting them. 51 | 52 | * commit test that demonstrates a bug (optional) 53 | * commit the fix 54 | * open pull request 55 | 56 | The test is required but does *not* have to be provided by you. If you 57 | do provide it, committing it first shows appropriate messages in the 58 | pull request and makes it easier to accept via Web. 59 | 60 | Performance 61 | ----------- 62 | 63 | A word of caution: Since plyj is pure Python, it is quite slow. Based on my laptop (which has an i7-3517U @ 1.90 GHz) I can present the following numbers (running inside a virtual machine): 64 | 65 | * 619 rules 66 | * 1149 states 67 | * ~3.28 seconds to compile the grammar 68 | * java/util/Collections.java takes ~0.44 seconds to parse (it's quite big though) 69 | 70 | The timings are obviously highly dependent on the used hardware. My old laptop (Core 2 Duo @ 1 GHz) took 17 and 1.8 seconds respectively. 71 | 72 | History 73 | ------- 74 | 75 | ### 0.2 (in development) 76 | 77 | * added `ExpressionStatement` 78 | 79 | ### 0.1 (2014-12-25) - The Christmas Release 80 | 81 | * initial release 82 | * supports complete Java 7 syntax (minus bugs) 83 | 84 | [PLY]: https://github.com/dabeaz/ply 85 | [Java Development Tools]: http://www.eclipse.org/jdt/ 86 | -------------------------------------------------------------------------------- /example/parse_expr.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import sys 4 | 5 | if len(sys.argv) == 1: 6 | print('''usage: parse_expr.py ... 7 | Example: parse_expr.py '1+2' '3' 'j = (int) i + 3' ''') 8 | sys.exit(1) 9 | 10 | import plyj.parser as plyj 11 | 12 | parser = plyj.Parser() 13 | for expr in sys.argv[1:]: 14 | print(parser.parse_expression(expr)) 15 | 16 | -------------------------------------------------------------------------------- /example/symbols.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import sys 4 | import plyj.parser 5 | import plyj.model as m 6 | 7 | p = plyj.parser.Parser() 8 | tree = p.parse_file(sys.argv[1]) 9 | 10 | print('declared types:') 11 | for type_decl in tree.type_declarations: 12 | print(type_decl.name) 13 | if type_decl.extends is not None: 14 | print(' -> extending ' + type_decl.extends.name.value) 15 | if len(type_decl.implements) is not 0: 16 | print(' -> implementing ' + ', '.join([type.name.value for type in type_decl.implements])) 17 | print 18 | 19 | print('fields:') 20 | for field_decl in [decl for decl in type_decl.body if type(decl) is m.FieldDeclaration]: 21 | for var_decl in field_decl.variable_declarators: 22 | if type(field_decl.type) is str: 23 | type_name = field_decl.type 24 | else: 25 | type_name = field_decl.type.name.value 26 | print(' ' + type_name + ' ' + var_decl.variable.name) 27 | 28 | print 29 | print('methods:') 30 | for method_decl in [decl for decl in type_decl.body if type(decl) is m.MethodDeclaration]: 31 | param_strings = [] 32 | for param in method_decl.parameters: 33 | if type(param.type) is str: 34 | param_strings.append(param.type + ' ' + param.variable.name) 35 | else: 36 | param_strings.append(param.type.name.value + ' ' + param.variable.name) 37 | print(' ' + method_decl.name + '(' + ', '.join(param_strings) + ')') 38 | 39 | if method_decl.body is not None: 40 | for statement in method_decl.body: 41 | # note that this misses variables in inner blocks such as for loops 42 | # see symbols_visitor.py for a better way of handling this 43 | if type(statement) is m.VariableDeclaration: 44 | for var_decl in statement.variable_declarators: 45 | if type(statement.type) is str: 46 | type_name = statement.type 47 | else: 48 | type_name = statement.type.name.value 49 | print(' ' + type_name + ' ' + var_decl.variable.name) 50 | -------------------------------------------------------------------------------- /example/symbols_visitor.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import sys 4 | import plyj.parser 5 | import plyj.model as m 6 | 7 | p = plyj.parser.Parser() 8 | tree = p.parse_file(sys.argv[1]) 9 | 10 | class MyVisitor(m.Visitor): 11 | 12 | def __init__(self): 13 | super(MyVisitor, self).__init__() 14 | 15 | self.first_field = True 16 | self.first_method = True 17 | 18 | def visit_ClassDeclaration(self, class_decl): 19 | return self.visit_type_declaration(class_decl) 20 | 21 | def visit_InterfaceDeclaration(self, interface_decl): 22 | return self.visit_type_declaration(interface_decl) 23 | 24 | def visit_type_declaration(self, type_decl): 25 | print(str(type_decl.name)) 26 | if type_decl.extends is not None: 27 | print(' -> extending ' + type_decl.extends.name.value) 28 | if len(type_decl.implements) is not 0: 29 | print(' -> implementing ' + ', '.join([type.name.value for type in type_decl.implements])) 30 | print 31 | 32 | return True 33 | 34 | def visit_FieldDeclaration(self, field_decl): 35 | if self.first_field: 36 | print('fields:') 37 | self.first_field = False 38 | for var_decl in field_decl.variable_declarators: 39 | if type(field_decl.type) is str: 40 | type_name = field_decl.type 41 | else: 42 | type_name = field_decl.type.name.value 43 | print(' ' + type_name + ' ' + var_decl.variable.name) 44 | 45 | def visit_MethodDeclaration(self, method_decl): 46 | if self.first_method: 47 | print 48 | print('methods:') 49 | self.first_method = False 50 | 51 | param_strings = [] 52 | for param in method_decl.parameters: 53 | if type(param.type) is str: 54 | param_strings.append(param.type + ' ' + param.variable.name) 55 | else: 56 | param_strings.append(param.type.name.value + ' ' + param.variable.name) 57 | print(' ' + method_decl.name + '(' + ', '.join(param_strings) + ')') 58 | 59 | return True 60 | 61 | def visit_VariableDeclaration(self, var_declaration): 62 | for var_decl in var_declaration.variable_declarators: 63 | if type(var_declaration.type) is str: 64 | type_name = var_declaration.type 65 | else: 66 | type_name = var_declaration.type.name.value 67 | print(' ' + type_name + ' ' + var_decl.variable.name) 68 | 69 | print('declared types:') 70 | tree.accept(MyVisitor()) 71 | -------------------------------------------------------------------------------- /plyj/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musiKk/plyj/c27d159b2fffe241a2d091e1be3d79790b216732/plyj/__init__.py -------------------------------------------------------------------------------- /plyj/model.py: -------------------------------------------------------------------------------- 1 | # Base node 2 | class SourceElement(object): 3 | ''' 4 | A SourceElement is the base class for all elements that occur in a Java 5 | file parsed by plyj. 6 | ''' 7 | 8 | def __init__(self): 9 | super(SourceElement, self).__init__() 10 | self._fields = [] 11 | 12 | def __repr__(self): 13 | equals = ("{0}={1!r}".format(k, getattr(self, k)) 14 | for k in self._fields) 15 | args = ", ".join(equals) 16 | return "{0}({1})".format(self.__class__.__name__, args) 17 | 18 | def __eq__(self, other): 19 | try: 20 | return self.__dict__ == other.__dict__ 21 | except AttributeError: 22 | return False 23 | 24 | def __ne__(self, other): 25 | return not self == other 26 | 27 | def accept(self, visitor): 28 | """ 29 | default implementation that visit the subnodes in the order 30 | they are stored in self_field 31 | """ 32 | class_name = self.__class__.__name__ 33 | visit = getattr(visitor, 'visit_' + class_name) 34 | if visit(self): 35 | for f in self._fields: 36 | field = getattr(self, f) 37 | if field: 38 | if isinstance(field, list): 39 | for elem in field: 40 | if isinstance(elem, SourceElement): 41 | elem.accept(visitor) 42 | elif isinstance(field, SourceElement): 43 | field.accept(visitor) 44 | getattr(visitor, 'leave_' + class_name)(self) 45 | 46 | 47 | class CompilationUnit(SourceElement): 48 | 49 | def __init__(self, package_declaration=None, import_declarations=None, 50 | type_declarations=None): 51 | super(CompilationUnit, self).__init__() 52 | self._fields = [ 53 | 'package_declaration', 'import_declarations', 'type_declarations'] 54 | if import_declarations is None: 55 | import_declarations = [] 56 | if type_declarations is None: 57 | type_declarations = [] 58 | self.package_declaration = package_declaration 59 | self.import_declarations = import_declarations 60 | self.type_declarations = type_declarations 61 | 62 | class PackageDeclaration(SourceElement): 63 | 64 | def __init__(self, name, modifiers=None): 65 | super(PackageDeclaration, self).__init__() 66 | self._fields = ['name', 'modifiers'] 67 | if modifiers is None: 68 | modifiers = [] 69 | self.name = name 70 | self.modifiers = modifiers 71 | 72 | 73 | class ImportDeclaration(SourceElement): 74 | 75 | def __init__(self, name, static=False, on_demand=False): 76 | super(ImportDeclaration, self).__init__() 77 | self._fields = ['name', 'static', 'on_demand'] 78 | self.name = name 79 | self.static = static 80 | self.on_demand = on_demand 81 | 82 | 83 | class ClassDeclaration(SourceElement): 84 | 85 | def __init__(self, name, body, modifiers=None, type_parameters=None, 86 | extends=None, implements=None): 87 | super(ClassDeclaration, self).__init__() 88 | self._fields = ['name', 'body', 'modifiers', 89 | 'type_parameters', 'extends', 'implements'] 90 | if modifiers is None: 91 | modifiers = [] 92 | if type_parameters is None: 93 | type_parameters = [] 94 | if implements is None: 95 | implements = [] 96 | self.name = name 97 | self.body = body 98 | self.modifiers = modifiers 99 | self.type_parameters = type_parameters 100 | self.extends = extends 101 | self.implements = implements 102 | 103 | class ClassInitializer(SourceElement): 104 | 105 | def __init__(self, block, static=False): 106 | super(ClassInitializer, self).__init__() 107 | self._fields = ['block', 'static'] 108 | self.block = block 109 | self.static = static 110 | 111 | class ConstructorDeclaration(SourceElement): 112 | 113 | def __init__(self, name, block, modifiers=None, type_parameters=None, 114 | parameters=None, throws=None): 115 | super(ConstructorDeclaration, self).__init__() 116 | self._fields = ['name', 'block', 'modifiers', 117 | 'type_parameters', 'parameters', 'throws'] 118 | if modifiers is None: 119 | modifiers = [] 120 | if type_parameters is None: 121 | type_parameters = [] 122 | if parameters is None: 123 | parameters = [] 124 | self.name = name 125 | self.block = block 126 | self.modifiers = modifiers 127 | self.type_parameters = type_parameters 128 | self.parameters = parameters 129 | self.throws = throws 130 | 131 | class EmptyDeclaration(SourceElement): 132 | pass 133 | 134 | class FieldDeclaration(SourceElement): 135 | 136 | def __init__(self, type, variable_declarators, modifiers=None): 137 | super(FieldDeclaration, self).__init__() 138 | self._fields = ['type', 'variable_declarators', 'modifiers'] 139 | if modifiers is None: 140 | modifiers = [] 141 | self.type = type 142 | self.variable_declarators = variable_declarators 143 | self.modifiers = modifiers 144 | 145 | class MethodDeclaration(SourceElement): 146 | 147 | def __init__(self, name, modifiers=None, type_parameters=None, 148 | parameters=None, return_type='void', body=None, abstract=False, 149 | extended_dims=0, throws=None): 150 | super(MethodDeclaration, self).__init__() 151 | self._fields = ['name', 'modifiers', 'type_parameters', 'parameters', 152 | 'return_type', 'body', 'abstract', 'extended_dims', 153 | 'throws'] 154 | if modifiers is None: 155 | modifiers = [] 156 | if type_parameters is None: 157 | type_parameters = [] 158 | if parameters is None: 159 | parameters = [] 160 | self.name = name 161 | self.modifiers = modifiers 162 | self.type_parameters = type_parameters 163 | self.parameters = parameters 164 | self.return_type = return_type 165 | self.body = body 166 | self.abstract = abstract 167 | self.extended_dims = extended_dims 168 | self.throws = throws 169 | 170 | class FormalParameter(SourceElement): 171 | 172 | def __init__(self, variable, type, modifiers=None, vararg=False): 173 | super(FormalParameter, self).__init__() 174 | self._fields = ['variable', 'type', 'modifiers', 'vararg'] 175 | if modifiers is None: 176 | modifiers = [] 177 | self.variable = variable 178 | self.type = type 179 | self.modifiers = modifiers 180 | self.vararg = vararg 181 | 182 | 183 | class Variable(SourceElement): 184 | # I would like to remove this class. In theory, the dimension could be added 185 | # to the type but this means variable declarations have to be changed 186 | # somehow. Consider 'int i, j[];'. In this case there currently is only one 187 | # type with two variable declarators;This closely resembles the source code. 188 | # If the variable is to go away, the type has to be duplicated for every 189 | # variable... 190 | 191 | def __init__(self, name, dimensions=0): 192 | super(Variable, self).__init__() 193 | self._fields = ['name', 'dimensions'] 194 | self.name = name 195 | self.dimensions = dimensions 196 | 197 | 198 | class VariableDeclarator(SourceElement): 199 | 200 | def __init__(self, variable, initializer=None): 201 | super(VariableDeclarator, self).__init__() 202 | self._fields = ['variable', 'initializer'] 203 | self.variable = variable 204 | self.initializer = initializer 205 | 206 | class Throws(SourceElement): 207 | 208 | def __init__(self, types): 209 | super(Throws, self).__init__() 210 | self._fields = ['types'] 211 | self.types = types 212 | 213 | class InterfaceDeclaration(SourceElement): 214 | 215 | def __init__(self, name, modifiers=None, extends=None, type_parameters=None, 216 | body=None): 217 | super(InterfaceDeclaration, self).__init__() 218 | self._fields = [ 219 | 'name', 'modifiers', 'extends', 'type_parameters', 'body'] 220 | if modifiers is None: 221 | modifiers = [] 222 | if extends is None: 223 | extends = [] 224 | if type_parameters is None: 225 | type_parameters = [] 226 | if body is None: 227 | body = [] 228 | self.name = name 229 | self.modifiers = modifiers 230 | self.extends = extends 231 | self.type_parameters = type_parameters 232 | self.body = body 233 | 234 | class EnumDeclaration(SourceElement): 235 | 236 | def __init__(self, name, implements=None, modifiers=None, 237 | type_parameters=None, body=None): 238 | super(EnumDeclaration, self).__init__() 239 | self._fields = [ 240 | 'name', 'implements', 'modifiers', 'type_parameters', 'body'] 241 | if implements is None: 242 | implements = [] 243 | if modifiers is None: 244 | modifiers = [] 245 | if type_parameters is None: 246 | type_parameters = [] 247 | if body is None: 248 | body = [] 249 | self.name = name 250 | self.implements = implements 251 | self.modifiers = modifiers 252 | self.type_parameters = type_parameters 253 | self.body = body 254 | 255 | class EnumConstant(SourceElement): 256 | 257 | def __init__(self, name, arguments=None, modifiers=None, body=None): 258 | super(EnumConstant, self).__init__() 259 | self._fields = ['name', 'arguments', 'modifiers', 'body'] 260 | if arguments is None: 261 | arguments = [] 262 | if modifiers is None: 263 | modifiers = [] 264 | if body is None: 265 | body = [] 266 | self.name = name 267 | self.arguments = arguments 268 | self.modifiers = modifiers 269 | self.body = body 270 | 271 | class AnnotationDeclaration(SourceElement): 272 | 273 | def __init__(self, name, modifiers=None, type_parameters=None, extends=None, 274 | implements=None, body=None): 275 | super(AnnotationDeclaration, self).__init__() 276 | self._fields = [ 277 | 'name', 'modifiers', 'type_parameters', 'extends', 'implements', 278 | 'body'] 279 | if modifiers is None: 280 | modifiers = [] 281 | if type_parameters is None: 282 | type_parameters = [] 283 | if implements is None: 284 | implements = [] 285 | if body is None: 286 | body = [] 287 | self.name = name 288 | self.modifiers = modifiers 289 | self.type_parameters = type_parameters 290 | self.extends = extends 291 | self.implements = implements 292 | self.body = body 293 | 294 | class AnnotationMethodDeclaration(SourceElement): 295 | 296 | def __init__(self, name, type, parameters=None, default=None, 297 | modifiers=None, type_parameters=None, extended_dims=0): 298 | super(AnnotationMethodDeclaration, self).__init__() 299 | self._fields = ['name', 'type', 'parameters', 'default', 300 | 'modifiers', 'type_parameters', 'extended_dims'] 301 | if parameters is None: 302 | parameters = [] 303 | if modifiers is None: 304 | modifiers = [] 305 | if type_parameters is None: 306 | type_parameters = [] 307 | self.name = name 308 | self.type = type 309 | self.parameters = parameters 310 | self.default = default 311 | self.modifiers = modifiers 312 | self.type_parameters = type_parameters 313 | self.extended_dims = extended_dims 314 | 315 | class Annotation(SourceElement): 316 | 317 | def __init__(self, name, members=None, single_member=None): 318 | super(Annotation, self).__init__() 319 | self._fields = ['name', 'members', 'single_member'] 320 | if members is None: 321 | members = [] 322 | self.name = name 323 | self.members = members 324 | self.single_member = single_member 325 | 326 | 327 | class AnnotationMember(SourceElement): 328 | 329 | def __init__(self, name, value): 330 | super(SourceElement, self).__init__() 331 | self._fields = ['name', 'value'] 332 | self.name = name 333 | self.value = value 334 | 335 | 336 | class Type(SourceElement): 337 | 338 | def __init__(self, name, type_arguments=None, enclosed_in=None, 339 | dimensions=0): 340 | super(Type, self).__init__() 341 | self._fields = ['name', 'type_arguments', 'enclosed_in', 'dimensions'] 342 | if type_arguments is None: 343 | type_arguments = [] 344 | self.name = name 345 | self.type_arguments = type_arguments 346 | self.enclosed_in = enclosed_in 347 | self.dimensions = dimensions 348 | 349 | 350 | class Wildcard(SourceElement): 351 | 352 | def __init__(self, bounds=None): 353 | super(Wildcard, self).__init__() 354 | self._fields = ['bounds'] 355 | if bounds is None: 356 | bounds = [] 357 | self.bounds = bounds 358 | 359 | 360 | class WildcardBound(SourceElement): 361 | 362 | def __init__(self, type, extends=False, _super=False): 363 | super(WildcardBound, self).__init__() 364 | self._fields = ['type', 'extends', '_super'] 365 | self.type = type 366 | self.extends = extends 367 | self._super = _super 368 | 369 | 370 | class TypeParameter(SourceElement): 371 | 372 | def __init__(self, name, extends=None): 373 | super(TypeParameter, self).__init__() 374 | self._fields = ['name', 'extends'] 375 | if extends is None: 376 | extends = [] 377 | self.name = name 378 | self.extends = extends 379 | 380 | 381 | class Expression(SourceElement): 382 | 383 | def __init__(self): 384 | super(Expression, self).__init__() 385 | self._fields = [] 386 | 387 | class BinaryExpression(Expression): 388 | 389 | def __init__(self, operator, lhs, rhs): 390 | super(BinaryExpression, self).__init__() 391 | self._fields = ['operator', 'lhs', 'rhs'] 392 | self.operator = operator 393 | self.lhs = lhs 394 | self.rhs = rhs 395 | 396 | class Assignment(BinaryExpression): 397 | pass 398 | 399 | 400 | class Conditional(Expression): 401 | 402 | def __init__(self, predicate, if_true, if_false): 403 | super(self.__class__, self).__init__() 404 | self._fields = ['predicate', 'if_true', 'if_false'] 405 | self.predicate = predicate 406 | self.if_true = if_true 407 | self.if_false = if_false 408 | 409 | class ConditionalOr(BinaryExpression): 410 | pass 411 | 412 | class ConditionalAnd(BinaryExpression): 413 | pass 414 | 415 | class Or(BinaryExpression): 416 | pass 417 | 418 | 419 | class Xor(BinaryExpression): 420 | pass 421 | 422 | 423 | class And(BinaryExpression): 424 | pass 425 | 426 | 427 | class Equality(BinaryExpression): 428 | pass 429 | 430 | 431 | class InstanceOf(BinaryExpression): 432 | pass 433 | 434 | 435 | class Relational(BinaryExpression): 436 | pass 437 | 438 | 439 | class Shift(BinaryExpression): 440 | pass 441 | 442 | 443 | class Additive(BinaryExpression): 444 | pass 445 | 446 | 447 | class Multiplicative(BinaryExpression): 448 | pass 449 | 450 | 451 | class Unary(Expression): 452 | 453 | def __init__(self, sign, expression): 454 | super(Unary, self).__init__() 455 | self._fields = ['sign', 'expression'] 456 | self.sign = sign 457 | self.expression = expression 458 | 459 | 460 | class Cast(Expression): 461 | 462 | def __init__(self, target, expression): 463 | super(Cast, self).__init__() 464 | self._fields = ['target', 'expression'] 465 | self.target = target 466 | self.expression = expression 467 | 468 | 469 | class Statement(SourceElement): 470 | pass 471 | 472 | class Empty(Statement): 473 | pass 474 | 475 | 476 | class Block(Statement): 477 | 478 | def __init__(self, statements=None): 479 | super(Statement, self).__init__() 480 | self._fields = ['statements'] 481 | if statements is None: 482 | statements = [] 483 | self.statements = statements 484 | 485 | def __iter__(self): 486 | for s in self.statements: 487 | yield s 488 | 489 | class VariableDeclaration(Statement, FieldDeclaration): 490 | pass 491 | 492 | class ArrayInitializer(SourceElement): 493 | def __init__(self, elements=None): 494 | super(ArrayInitializer, self).__init__() 495 | self._fields = ['elements'] 496 | if elements is None: 497 | elements = [] 498 | self.elements = elements 499 | 500 | 501 | class MethodInvocation(Expression): 502 | def __init__(self, name, arguments=None, type_arguments=None, target=None): 503 | super(MethodInvocation, self).__init__() 504 | self._fields = ['name', 'arguments', 'type_arguments', 'target'] 505 | if arguments is None: 506 | arguments = [] 507 | if type_arguments is None: 508 | type_arguments = [] 509 | self.name = name 510 | self.arguments = arguments 511 | self.type_arguments = type_arguments 512 | self.target = target 513 | 514 | class IfThenElse(Statement): 515 | 516 | def __init__(self, predicate, if_true=None, if_false=None): 517 | super(IfThenElse, self).__init__() 518 | self._fields = ['predicate', 'if_true', 'if_false'] 519 | self.predicate = predicate 520 | self.if_true = if_true 521 | self.if_false = if_false 522 | 523 | class While(Statement): 524 | 525 | def __init__(self, predicate, body=None): 526 | super(While, self).__init__() 527 | self._fields = ['predicate', 'body'] 528 | self.predicate = predicate 529 | self.body = body 530 | 531 | class For(Statement): 532 | 533 | def __init__(self, init, predicate, update, body): 534 | super(For, self).__init__() 535 | self._fields = ['init', 'predicate', 'update', 'body'] 536 | self.init = init 537 | self.predicate = predicate 538 | self.update = update 539 | self.body = body 540 | 541 | class ForEach(Statement): 542 | 543 | def __init__(self, type, variable, iterable, body, modifiers=None): 544 | super(ForEach, self).__init__() 545 | self._fields = ['type', 'variable', 'iterable', 'body', 'modifiers'] 546 | if modifiers is None: 547 | modifiers = [] 548 | self.type = type 549 | self.variable = variable 550 | self.iterable = iterable 551 | self.body = body 552 | self.modifiers = modifiers 553 | 554 | 555 | class Assert(Statement): 556 | 557 | def __init__(self, predicate, message=None): 558 | super(Assert, self).__init__() 559 | self._fields = ['predicate', 'message'] 560 | self.predicate = predicate 561 | self.message = message 562 | 563 | 564 | class Switch(Statement): 565 | 566 | def __init__(self, expression, switch_cases): 567 | super(Switch, self).__init__() 568 | self._fields = ['expression', 'switch_cases'] 569 | self.expression = expression 570 | self.switch_cases = switch_cases 571 | 572 | class SwitchCase(SourceElement): 573 | 574 | def __init__(self, cases, body=None): 575 | super(SwitchCase, self).__init__() 576 | self._fields = ['cases', 'body'] 577 | if body is None: 578 | body = [] 579 | self.cases = cases 580 | self.body = body 581 | 582 | class DoWhile(Statement): 583 | 584 | def __init__(self, predicate, body=None): 585 | super(DoWhile, self).__init__() 586 | self._fields = ['predicate', 'body'] 587 | self.predicate = predicate 588 | self.body = body 589 | 590 | 591 | class Continue(Statement): 592 | 593 | def __init__(self, label=None): 594 | super(Continue, self).__init__() 595 | self._fields = ['label'] 596 | self.label = label 597 | 598 | 599 | class Break(Statement): 600 | 601 | def __init__(self, label=None): 602 | super(Break, self).__init__() 603 | self._fields = ['label'] 604 | self.label = label 605 | 606 | 607 | class Return(Statement): 608 | 609 | def __init__(self, result=None): 610 | super(Return, self).__init__() 611 | self._fields = ['result'] 612 | self.result = result 613 | 614 | 615 | class Synchronized(Statement): 616 | 617 | def __init__(self, monitor, body): 618 | super(Synchronized, self).__init__() 619 | self._fields = ['monitor', 'body'] 620 | self.monitor = monitor 621 | self.body = body 622 | 623 | 624 | class Throw(Statement): 625 | 626 | def __init__(self, exception): 627 | super(Throw, self).__init__() 628 | self._fields = ['exception'] 629 | self.exception = exception 630 | 631 | 632 | class Try(Statement): 633 | 634 | def __init__(self, block, catches=None, _finally=None, resources=None): 635 | super(Try, self).__init__() 636 | self._fields = ['block', 'catches', '_finally', 'resources'] 637 | if catches is None: 638 | catches = [] 639 | if resources is None: 640 | resources = [] 641 | self.block = block 642 | self.catches = catches 643 | self._finally = _finally 644 | self.resources = resources 645 | 646 | def accept(self, visitor): 647 | if visitor.visit_Try(self): 648 | for s in self.block: 649 | s.accept(visitor) 650 | for c in self.catches: 651 | visitor.visit_Catch(c) 652 | if self._finally: 653 | self._finally.accept(visitor) 654 | 655 | 656 | class Catch(SourceElement): 657 | 658 | def __init__(self, variable, modifiers=None, types=None, block=None): 659 | super(Catch, self).__init__() 660 | self._fields = ['variable', 'modifiers', 'types', 'block'] 661 | if modifiers is None: 662 | modifiers = [] 663 | if types is None: 664 | types = [] 665 | self.variable = variable 666 | self.modifiers = modifiers 667 | self.types = types 668 | self.block = block 669 | 670 | 671 | class Resource(SourceElement): 672 | 673 | def __init__(self, variable, type=None, modifiers=None, initializer=None): 674 | super(Resource, self).__init__() 675 | self._fields = ['variable', 'type', 'modifiers', 'initializer'] 676 | if modifiers is None: 677 | modifiers = [] 678 | self.variable = variable 679 | self.type = type 680 | self.modifiers = modifiers 681 | self.initializer = initializer 682 | 683 | 684 | class ConstructorInvocation(Statement): 685 | """An explicit invocations of a class's constructor. 686 | 687 | This is a variant of either this() or super(), NOT a "new" expression. 688 | """ 689 | 690 | def __init__(self, name, target=None, type_arguments=None, arguments=None): 691 | super(ConstructorInvocation, self).__init__() 692 | self._fields = ['name', 'target', 'type_arguments', 'arguments'] 693 | if type_arguments is None: 694 | type_arguments = [] 695 | if arguments is None: 696 | arguments = [] 697 | self.name = name 698 | self.target = target 699 | self.type_arguments = type_arguments 700 | self.arguments = arguments 701 | 702 | 703 | class InstanceCreation(Expression): 704 | 705 | def __init__(self, type, type_arguments=None, arguments=None, body=None, 706 | enclosed_in=None): 707 | super(InstanceCreation, self).__init__() 708 | self._fields = [ 709 | 'type', 'type_arguments', 'arguments', 'body', 'enclosed_in'] 710 | if type_arguments is None: 711 | type_arguments = [] 712 | if arguments is None: 713 | arguments = [] 714 | if body is None: 715 | body = [] 716 | self.type = type 717 | self.type_arguments = type_arguments 718 | self.arguments = arguments 719 | self.body = body 720 | self.enclosed_in = enclosed_in 721 | 722 | 723 | class FieldAccess(Expression): 724 | 725 | def __init__(self, name, target): 726 | super(FieldAccess, self).__init__() 727 | self._fields = ['name', 'target'] 728 | self.name = name 729 | self.target = target 730 | 731 | 732 | class ArrayAccess(Expression): 733 | 734 | def __init__(self, index, target): 735 | super(ArrayAccess, self).__init__() 736 | self._fields = ['index', 'target'] 737 | self.index = index 738 | self.target = target 739 | 740 | 741 | class ArrayCreation(Expression): 742 | 743 | def __init__(self, type, dimensions=None, initializer=None): 744 | super(ArrayCreation, self).__init__() 745 | self._fields = ['type', 'dimensions', 'initializer'] 746 | if dimensions is None: 747 | dimensions = [] 748 | self.type = type 749 | self.dimensions = dimensions 750 | self.initializer = initializer 751 | 752 | 753 | class Literal(SourceElement): 754 | 755 | def __init__(self, value): 756 | super(Literal, self).__init__() 757 | self._fields = ['value'] 758 | self.value = value 759 | 760 | 761 | class ClassLiteral(SourceElement): 762 | 763 | def __init__(self, type): 764 | super(ClassLiteral, self).__init__() 765 | self._fields = ['type'] 766 | self.type = type 767 | 768 | 769 | class Name(SourceElement): 770 | 771 | def __init__(self, value): 772 | super(Name, self).__init__() 773 | self._fields = ['value'] 774 | self.value = value 775 | 776 | def append_name(self, name): 777 | try: 778 | self.value = self.value + '.' + name.value 779 | except: 780 | self.value = self.value + '.' + name 781 | 782 | 783 | class ExpressionStatement(Statement): 784 | def __init__(self, expression): 785 | super(ExpressionStatement, self).__init__() 786 | self._fields = ['expression'] 787 | self.expression = expression 788 | 789 | 790 | class Visitor(object): 791 | 792 | def __init__(self, verbose=False): 793 | self.verbose = verbose 794 | 795 | def __getattr__(self, name): 796 | if not (name.startswith('visit_') or name.startswith('leave_')): 797 | raise AttributeError('name must start with visit_ or leave_ but was {}' 798 | .format(name)) 799 | 800 | def f(element): 801 | if self.verbose: 802 | msg = 'unimplemented call to {}; ignoring ({})' 803 | print(msg.format(name, element)) 804 | return True 805 | return f 806 | -------------------------------------------------------------------------------- /plyj/parser.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | import ply.lex as lex 4 | import ply.yacc as yacc 5 | from .model import * 6 | 7 | class MyLexer(object): 8 | 9 | keywords = ('this', 'class', 'void', 'super', 'extends', 'implements', 'enum', 'interface', 10 | 'byte', 'short', 'int', 'long', 'char', 'float', 'double', 'boolean', 'null', 11 | 'true', 'false', 12 | 'final', 'public', 'protected', 'private', 'abstract', 'static', 'strictfp', 'transient', 'volatile', 13 | 'synchronized', 'native', 14 | 'throws', 'default', 15 | 'instanceof', 16 | 'if', 'else', 'while', 'for', 'switch', 'case', 'assert', 'do', 17 | 'break', 'continue', 'return', 'throw', 'try', 'catch', 'finally', 'new', 18 | 'package', 'import' 19 | ) 20 | 21 | tokens = [ 22 | 'NAME', 23 | 'NUM', 24 | 'CHAR_LITERAL', 25 | 'STRING_LITERAL', 26 | 'LINE_COMMENT', 'BLOCK_COMMENT', 27 | 28 | 'OR', 'AND', 29 | 'EQ', 'NEQ', 'GTEQ', 'LTEQ', 30 | 'LSHIFT', 'RSHIFT', 'RRSHIFT', 31 | 32 | 'TIMES_ASSIGN', 'DIVIDE_ASSIGN', 'REMAINDER_ASSIGN', 33 | 'PLUS_ASSIGN', 'MINUS_ASSIGN', 'LSHIFT_ASSIGN', 'RSHIFT_ASSIGN', 'RRSHIFT_ASSIGN', 34 | 'AND_ASSIGN', 'OR_ASSIGN', 'XOR_ASSIGN', 35 | 36 | 'PLUSPLUS', 'MINUSMINUS', 37 | 38 | 'ELLIPSIS' 39 | ] + [k.upper() for k in keywords] 40 | literals = '()+-*/=?:,.^|&~!=[]{};<>@%' 41 | 42 | t_NUM = r'\.?[0-9][0-9eE_lLdDa-fA-F.xXpP]*' 43 | t_CHAR_LITERAL = r'\'([^\\\n]|(\\.))*?\'' 44 | t_STRING_LITERAL = r'\"([^\\\n]|(\\.))*?\"' 45 | 46 | t_ignore_LINE_COMMENT = '//.*' 47 | 48 | def t_BLOCK_COMMENT(self, t): 49 | r'/\*(.|\n)*?\*/' 50 | t.lexer.lineno += t.value.count('\n') 51 | 52 | t_OR = r'\|\|' 53 | t_AND = '&&' 54 | 55 | t_EQ = '==' 56 | t_NEQ = '!=' 57 | t_GTEQ = '>=' 58 | t_LTEQ = '<=' 59 | 60 | t_LSHIFT = '<<' 61 | t_RSHIFT = '>>' 62 | t_RRSHIFT = '>>>' 63 | 64 | t_TIMES_ASSIGN = r'\*=' 65 | t_DIVIDE_ASSIGN = '/=' 66 | t_REMAINDER_ASSIGN = '%=' 67 | t_PLUS_ASSIGN = r'\+=' 68 | t_MINUS_ASSIGN = '-=' 69 | t_LSHIFT_ASSIGN = '<<=' 70 | t_RSHIFT_ASSIGN = '>>=' 71 | t_RRSHIFT_ASSIGN = '>>>=' 72 | t_AND_ASSIGN = '&=' 73 | t_OR_ASSIGN = r'\|=' 74 | t_XOR_ASSIGN = '\^=' 75 | 76 | t_PLUSPLUS = r'\+\+' 77 | t_MINUSMINUS = r'\-\-' 78 | 79 | t_ELLIPSIS = r'\.\.\.' 80 | 81 | t_ignore = ' \t\f' 82 | 83 | def t_NAME(self, t): 84 | '[A-Za-z_$][A-Za-z0-9_$]*' 85 | if t.value in MyLexer.keywords: 86 | t.type = t.value.upper() 87 | return t 88 | 89 | def t_newline(self, t): 90 | r'\n+' 91 | t.lexer.lineno += len(t.value) 92 | 93 | def t_newline2(self, t): 94 | r'(\r\n)+' 95 | t.lexer.lineno += len(t.value) / 2 96 | 97 | def t_error(self, t): 98 | print("Illegal character '{}' ({}) in line {}".format(t.value[0], hex(ord(t.value[0])), t.lexer.lineno)) 99 | t.lexer.skip(1) 100 | 101 | class ExpressionParser(object): 102 | 103 | def p_expression(self, p): 104 | '''expression : assignment_expression''' 105 | p[0] = p[1] 106 | 107 | def p_expression_not_name(self, p): 108 | '''expression_not_name : assignment_expression_not_name''' 109 | p[0] = p[1] 110 | 111 | def p_assignment_expression(self, p): 112 | '''assignment_expression : assignment 113 | | conditional_expression''' 114 | p[0] = p[1] 115 | 116 | def p_assignment_expression_not_name(self, p): 117 | '''assignment_expression_not_name : assignment 118 | | conditional_expression_not_name''' 119 | p[0] = p[1] 120 | 121 | def p_assignment(self, p): 122 | '''assignment : postfix_expression assignment_operator assignment_expression''' 123 | p[0] = Assignment(p[2], p[1], p[3]) 124 | 125 | def p_assignment_operator(self, p): 126 | '''assignment_operator : '=' 127 | | TIMES_ASSIGN 128 | | DIVIDE_ASSIGN 129 | | REMAINDER_ASSIGN 130 | | PLUS_ASSIGN 131 | | MINUS_ASSIGN 132 | | LSHIFT_ASSIGN 133 | | RSHIFT_ASSIGN 134 | | RRSHIFT_ASSIGN 135 | | AND_ASSIGN 136 | | OR_ASSIGN 137 | | XOR_ASSIGN''' 138 | p[0] = p[1] 139 | 140 | def p_conditional_expression(self, p): 141 | '''conditional_expression : conditional_or_expression 142 | | conditional_or_expression '?' expression ':' conditional_expression''' 143 | if len(p) == 2: 144 | p[0] = p[1] 145 | else: 146 | p[0] = Conditional(p[1], p[3], p[5]) 147 | 148 | def p_conditional_expression_not_name(self, p): 149 | '''conditional_expression_not_name : conditional_or_expression_not_name 150 | | conditional_or_expression_not_name '?' expression ':' conditional_expression 151 | | name '?' expression ':' conditional_expression''' 152 | if len(p) == 2: 153 | p[0] = p[1] 154 | else: 155 | p[0] = Conditional(p[1], p[3], p[5]) 156 | 157 | def binop(self, p, ctor): 158 | if len(p) == 2: 159 | p[0] = p[1] 160 | else: 161 | p[0] = ctor(p[2], p[1], p[3]) 162 | 163 | def p_conditional_or_expression(self, p): 164 | '''conditional_or_expression : conditional_and_expression 165 | | conditional_or_expression OR conditional_and_expression''' 166 | self.binop(p, ConditionalOr) 167 | 168 | def p_conditional_or_expression_not_name(self, p): 169 | '''conditional_or_expression_not_name : conditional_and_expression_not_name 170 | | conditional_or_expression_not_name OR conditional_and_expression 171 | | name OR conditional_and_expression''' 172 | self.binop(p, ConditionalOr) 173 | 174 | def p_conditional_and_expression(self, p): 175 | '''conditional_and_expression : inclusive_or_expression 176 | | conditional_and_expression AND inclusive_or_expression''' 177 | self.binop(p, ConditionalAnd) 178 | 179 | def p_conditional_and_expression_not_name(self, p): 180 | '''conditional_and_expression_not_name : inclusive_or_expression_not_name 181 | | conditional_and_expression_not_name AND inclusive_or_expression 182 | | name AND inclusive_or_expression''' 183 | self.binop(p, ConditionalAnd) 184 | 185 | def p_inclusive_or_expression(self, p): 186 | '''inclusive_or_expression : exclusive_or_expression 187 | | inclusive_or_expression '|' exclusive_or_expression''' 188 | self.binop(p, Or) 189 | 190 | def p_inclusive_or_expression_not_name(self, p): 191 | '''inclusive_or_expression_not_name : exclusive_or_expression_not_name 192 | | inclusive_or_expression_not_name '|' exclusive_or_expression 193 | | name '|' exclusive_or_expression''' 194 | self.binop(p, Or) 195 | 196 | def p_exclusive_or_expression(self, p): 197 | '''exclusive_or_expression : and_expression 198 | | exclusive_or_expression '^' and_expression''' 199 | self.binop(p, Xor) 200 | 201 | def p_exclusive_or_expression_not_name(self, p): 202 | '''exclusive_or_expression_not_name : and_expression_not_name 203 | | exclusive_or_expression_not_name '^' and_expression 204 | | name '^' and_expression''' 205 | self.binop(p, Xor) 206 | 207 | def p_and_expression(self, p): 208 | '''and_expression : equality_expression 209 | | and_expression '&' equality_expression''' 210 | self.binop(p, And) 211 | 212 | def p_and_expression_not_name(self, p): 213 | '''and_expression_not_name : equality_expression_not_name 214 | | and_expression_not_name '&' equality_expression 215 | | name '&' equality_expression''' 216 | self.binop(p, And) 217 | 218 | def p_equality_expression(self, p): 219 | '''equality_expression : instanceof_expression 220 | | equality_expression EQ instanceof_expression 221 | | equality_expression NEQ instanceof_expression''' 222 | self.binop(p, Equality) 223 | 224 | def p_equality_expression_not_name(self, p): 225 | '''equality_expression_not_name : instanceof_expression_not_name 226 | | equality_expression_not_name EQ instanceof_expression 227 | | name EQ instanceof_expression 228 | | equality_expression_not_name NEQ instanceof_expression 229 | | name NEQ instanceof_expression''' 230 | self.binop(p, Equality) 231 | 232 | def p_instanceof_expression(self, p): 233 | '''instanceof_expression : relational_expression 234 | | instanceof_expression INSTANCEOF reference_type''' 235 | self.binop(p, InstanceOf) 236 | 237 | def p_instanceof_expression_not_name(self, p): 238 | '''instanceof_expression_not_name : relational_expression_not_name 239 | | name INSTANCEOF reference_type 240 | | instanceof_expression_not_name INSTANCEOF reference_type''' 241 | self.binop(p, InstanceOf) 242 | 243 | def p_relational_expression(self, p): 244 | '''relational_expression : shift_expression 245 | | relational_expression '>' shift_expression 246 | | relational_expression '<' shift_expression 247 | | relational_expression GTEQ shift_expression 248 | | relational_expression LTEQ shift_expression''' 249 | self.binop(p, Relational) 250 | 251 | def p_relational_expression_not_name(self, p): 252 | '''relational_expression_not_name : shift_expression_not_name 253 | | shift_expression_not_name '<' shift_expression 254 | | name '<' shift_expression 255 | | shift_expression_not_name '>' shift_expression 256 | | name '>' shift_expression 257 | | shift_expression_not_name GTEQ shift_expression 258 | | name GTEQ shift_expression 259 | | shift_expression_not_name LTEQ shift_expression 260 | | name LTEQ shift_expression''' 261 | self.binop(p, Relational) 262 | 263 | def p_shift_expression(self, p): 264 | '''shift_expression : additive_expression 265 | | shift_expression LSHIFT additive_expression 266 | | shift_expression RSHIFT additive_expression 267 | | shift_expression RRSHIFT additive_expression''' 268 | self.binop(p, Shift) 269 | 270 | def p_shift_expression_not_name(self, p): 271 | '''shift_expression_not_name : additive_expression_not_name 272 | | shift_expression_not_name LSHIFT additive_expression 273 | | name LSHIFT additive_expression 274 | | shift_expression_not_name RSHIFT additive_expression 275 | | name RSHIFT additive_expression 276 | | shift_expression_not_name RRSHIFT additive_expression 277 | | name RRSHIFT additive_expression''' 278 | self.binop(p, Shift) 279 | 280 | def p_additive_expression(self, p): 281 | '''additive_expression : multiplicative_expression 282 | | additive_expression '+' multiplicative_expression 283 | | additive_expression '-' multiplicative_expression''' 284 | self.binop(p, Additive) 285 | 286 | def p_additive_expression_not_name(self, p): 287 | '''additive_expression_not_name : multiplicative_expression_not_name 288 | | additive_expression_not_name '+' multiplicative_expression 289 | | name '+' multiplicative_expression 290 | | additive_expression_not_name '-' multiplicative_expression 291 | | name '-' multiplicative_expression''' 292 | self.binop(p, Additive) 293 | 294 | def p_multiplicative_expression(self, p): 295 | '''multiplicative_expression : unary_expression 296 | | multiplicative_expression '*' unary_expression 297 | | multiplicative_expression '/' unary_expression 298 | | multiplicative_expression '%' unary_expression''' 299 | self.binop(p, Multiplicative) 300 | 301 | def p_multiplicative_expression_not_name(self, p): 302 | '''multiplicative_expression_not_name : unary_expression_not_name 303 | | multiplicative_expression_not_name '*' unary_expression 304 | | name '*' unary_expression 305 | | multiplicative_expression_not_name '/' unary_expression 306 | | name '/' unary_expression 307 | | multiplicative_expression_not_name '%' unary_expression 308 | | name '%' unary_expression''' 309 | self.binop(p, Multiplicative) 310 | 311 | def p_unary_expression(self, p): 312 | '''unary_expression : pre_increment_expression 313 | | pre_decrement_expression 314 | | '+' unary_expression 315 | | '-' unary_expression 316 | | unary_expression_not_plus_minus''' 317 | if len(p) == 2: 318 | p[0] = p[1] 319 | else: 320 | p[0] = Unary(p[1], p[2]) 321 | 322 | def p_unary_expression_not_name(self, p): 323 | '''unary_expression_not_name : pre_increment_expression 324 | | pre_decrement_expression 325 | | '+' unary_expression 326 | | '-' unary_expression 327 | | unary_expression_not_plus_minus_not_name''' 328 | if len(p) == 2: 329 | p[0] = p[1] 330 | else: 331 | p[0] = Unary(p[1], p[2]) 332 | 333 | def p_pre_increment_expression(self, p): 334 | '''pre_increment_expression : PLUSPLUS unary_expression''' 335 | p[0] = Unary('++x', p[2]) 336 | 337 | def p_pre_decrement_expression(self, p): 338 | '''pre_decrement_expression : MINUSMINUS unary_expression''' 339 | p[0] = Unary('--x', p[2]) 340 | 341 | def p_unary_expression_not_plus_minus(self, p): 342 | '''unary_expression_not_plus_minus : postfix_expression 343 | | '~' unary_expression 344 | | '!' unary_expression 345 | | cast_expression''' 346 | if len(p) == 2: 347 | p[0] = p[1] 348 | else: 349 | p[0] = Unary(p[1], p[2]) 350 | 351 | def p_unary_expression_not_plus_minus_not_name(self, p): 352 | '''unary_expression_not_plus_minus_not_name : postfix_expression_not_name 353 | | '~' unary_expression 354 | | '!' unary_expression 355 | | cast_expression''' 356 | if len(p) == 2: 357 | p[0] = p[1] 358 | else: 359 | p[0] = Unary(p[1], p[2]) 360 | 361 | def p_postfix_expression(self, p): 362 | '''postfix_expression : primary 363 | | name 364 | | post_increment_expression 365 | | post_decrement_expression''' 366 | p[0] = p[1] 367 | 368 | def p_postfix_expression_not_name(self, p): 369 | '''postfix_expression_not_name : primary 370 | | post_increment_expression 371 | | post_decrement_expression''' 372 | p[0] = p[1] 373 | 374 | def p_post_increment_expression(self, p): 375 | '''post_increment_expression : postfix_expression PLUSPLUS''' 376 | p[0] = Unary('x++', p[1]) 377 | 378 | def p_post_decrement_expression(self, p): 379 | '''post_decrement_expression : postfix_expression MINUSMINUS''' 380 | p[0] = Unary('x--', p[1]) 381 | 382 | def p_primary(self, p): 383 | '''primary : primary_no_new_array 384 | | array_creation_with_array_initializer 385 | | array_creation_without_array_initializer''' 386 | p[0] = p[1] 387 | 388 | def p_primary_no_new_array(self, p): 389 | '''primary_no_new_array : literal 390 | | THIS 391 | | class_instance_creation_expression 392 | | field_access 393 | | method_invocation 394 | | array_access''' 395 | p[0] = p[1] 396 | 397 | def p_primary_no_new_array2(self, p): 398 | '''primary_no_new_array : '(' name ')' 399 | | '(' expression_not_name ')' ''' 400 | p[0] = p[2] 401 | 402 | def p_primary_no_new_array3(self, p): 403 | '''primary_no_new_array : name '.' THIS 404 | | name '.' SUPER''' 405 | p[1].append_name(p[3]) 406 | p[0] = p[1] 407 | 408 | def p_primary_no_new_array4(self, p): 409 | '''primary_no_new_array : name '.' CLASS 410 | | name dims '.' CLASS 411 | | primitive_type dims '.' CLASS 412 | | primitive_type '.' CLASS''' 413 | if len(p) == 4: 414 | p[0] = ClassLiteral(Type(p[1])) 415 | else: 416 | p[0] = ClassLiteral(Type(p[1], dimensions=p[2])) 417 | 418 | def p_dims_opt(self, p): 419 | '''dims_opt : dims''' 420 | p[0] = p[1] 421 | 422 | def p_dims_opt2(self, p): 423 | '''dims_opt : empty''' 424 | p[0] = 0 425 | 426 | def p_dims(self, p): 427 | '''dims : dims_loop''' 428 | p[0] = p[1] 429 | 430 | def p_dims_loop(self, p): 431 | '''dims_loop : one_dim_loop 432 | | dims_loop one_dim_loop''' 433 | if len(p) == 2: 434 | p[0] = 1 435 | else: 436 | p[0] = 1 + p[1] 437 | 438 | def p_one_dim_loop(self, p): 439 | '''one_dim_loop : '[' ']' ''' 440 | # ignore 441 | 442 | def p_cast_expression(self, p): 443 | '''cast_expression : '(' primitive_type dims_opt ')' unary_expression''' 444 | p[0] = Cast(Type(p[2], dimensions=p[3]), p[5]) 445 | 446 | def p_cast_expression2(self, p): 447 | '''cast_expression : '(' name type_arguments dims_opt ')' unary_expression_not_plus_minus''' 448 | p[0] = Cast(Type(p[2], type_arguments=p[3], dimensions=p[4]), p[6]) 449 | 450 | def p_cast_expression3(self, p): 451 | '''cast_expression : '(' name type_arguments '.' class_or_interface_type dims_opt ')' unary_expression_not_plus_minus''' 452 | p[5].dimensions = p[6] 453 | p[5].enclosed_in = Type(p[2], type_arguments=p[3]) 454 | p[0] = Cast(p[5], p[8]) 455 | 456 | def p_cast_expression4(self, p): 457 | '''cast_expression : '(' name ')' unary_expression_not_plus_minus''' 458 | # technically it's not necessarily a type but could be a type parameter 459 | p[0] = Cast(Type(p[2]), p[4]) 460 | 461 | def p_cast_expression5(self, p): 462 | '''cast_expression : '(' name dims ')' unary_expression_not_plus_minus''' 463 | # technically it's not necessarily a type but could be a type parameter 464 | p[0] = Cast(Type(p[2], dimensions=p[3]), p[5]) 465 | 466 | class StatementParser(object): 467 | 468 | def p_block(self, p): 469 | '''block : '{' block_statements_opt '}' ''' 470 | p[0] = Block(p[2]) 471 | 472 | def p_block_statements_opt(self, p): 473 | '''block_statements_opt : block_statements''' 474 | p[0] = p[1] 475 | 476 | def p_block_statements_opt2(self, p): 477 | '''block_statements_opt : empty''' 478 | p[0] = [] 479 | 480 | def p_block_statements(self, p): 481 | '''block_statements : block_statement 482 | | block_statements block_statement''' 483 | if len(p) == 2: 484 | p[0] = [p[1]] 485 | else: 486 | p[0] = p[1] + [p[2]] 487 | 488 | def p_block_statement(self, p): 489 | '''block_statement : local_variable_declaration_statement 490 | | statement 491 | | class_declaration 492 | | interface_declaration 493 | | annotation_type_declaration 494 | | enum_declaration''' 495 | p[0] = p[1] 496 | 497 | def p_local_variable_declaration_statement(self, p): 498 | '''local_variable_declaration_statement : local_variable_declaration ';' ''' 499 | p[0] = p[1] 500 | 501 | def p_local_variable_declaration(self, p): 502 | '''local_variable_declaration : type variable_declarators''' 503 | p[0] = VariableDeclaration(p[1], p[2]) 504 | 505 | def p_local_variable_declaration2(self, p): 506 | '''local_variable_declaration : modifiers type variable_declarators''' 507 | p[0] = VariableDeclaration(p[2], p[3], modifiers=p[1]) 508 | 509 | def p_variable_declarators(self, p): 510 | '''variable_declarators : variable_declarator 511 | | variable_declarators ',' variable_declarator''' 512 | if len(p) == 2: 513 | p[0] = [p[1]] 514 | else: 515 | p[0] = p[1] + [p[3]] 516 | 517 | def p_variable_declarator(self, p): 518 | '''variable_declarator : variable_declarator_id 519 | | variable_declarator_id '=' variable_initializer''' 520 | if len(p) == 2: 521 | p[0] = VariableDeclarator(p[1]) 522 | else: 523 | p[0] = VariableDeclarator(p[1], initializer=p[3]) 524 | 525 | def p_variable_declarator_id(self, p): 526 | '''variable_declarator_id : NAME dims_opt''' 527 | p[0] = Variable(p[1], dimensions=p[2]) 528 | 529 | def p_variable_initializer(self, p): 530 | '''variable_initializer : expression 531 | | array_initializer''' 532 | p[0] = p[1] 533 | 534 | def p_statement(self, p): 535 | '''statement : statement_without_trailing_substatement 536 | | labeled_statement 537 | | if_then_statement 538 | | if_then_else_statement 539 | | while_statement 540 | | for_statement 541 | | enhanced_for_statement''' 542 | p[0] = p[1] 543 | 544 | def p_statement_without_trailing_substatement(self, p): 545 | '''statement_without_trailing_substatement : block 546 | | expression_statement 547 | | assert_statement 548 | | empty_statement 549 | | switch_statement 550 | | do_statement 551 | | break_statement 552 | | continue_statement 553 | | return_statement 554 | | synchronized_statement 555 | | throw_statement 556 | | try_statement 557 | | try_statement_with_resources''' 558 | p[0] = p[1] 559 | 560 | def p_expression_statement(self, p): 561 | '''expression_statement : statement_expression ';' 562 | | explicit_constructor_invocation''' 563 | if len(p) == 2: 564 | p[0] = p[1] 565 | else: 566 | p[0] = ExpressionStatement(p[1]) 567 | 568 | def p_statement_expression(self, p): 569 | '''statement_expression : assignment 570 | | pre_increment_expression 571 | | pre_decrement_expression 572 | | post_increment_expression 573 | | post_decrement_expression 574 | | method_invocation 575 | | class_instance_creation_expression''' 576 | p[0] = p[1] 577 | 578 | def p_comma_opt(self, p): 579 | '''comma_opt : ',' 580 | | empty''' 581 | # ignore 582 | 583 | def p_array_initializer(self, p): 584 | '''array_initializer : '{' comma_opt '}' ''' 585 | p[0] = ArrayInitializer() 586 | 587 | def p_array_initializer2(self, p): 588 | '''array_initializer : '{' variable_initializers '}' 589 | | '{' variable_initializers ',' '}' ''' 590 | p[0] = ArrayInitializer(p[2]) 591 | 592 | def p_variable_initializers(self, p): 593 | '''variable_initializers : variable_initializer 594 | | variable_initializers ',' variable_initializer''' 595 | if len(p) == 2: 596 | p[0] = [p[1]] 597 | else: 598 | p[0] = p[1] + [p[3]] 599 | 600 | def p_method_invocation(self, p): 601 | '''method_invocation : NAME '(' argument_list_opt ')' ''' 602 | p[0] = MethodInvocation(p[1], arguments=p[3]) 603 | 604 | def p_method_invocation2(self, p): 605 | '''method_invocation : name '.' type_arguments NAME '(' argument_list_opt ')' 606 | | primary '.' type_arguments NAME '(' argument_list_opt ')' 607 | | SUPER '.' type_arguments NAME '(' argument_list_opt ')' ''' 608 | p[0] = MethodInvocation(p[4], target=p[1], type_arguments=p[3], arguments=p[6]) 609 | 610 | def p_method_invocation3(self, p): 611 | '''method_invocation : name '.' NAME '(' argument_list_opt ')' 612 | | primary '.' NAME '(' argument_list_opt ')' 613 | | SUPER '.' NAME '(' argument_list_opt ')' ''' 614 | p[0] = MethodInvocation(p[3], target=p[1], arguments=p[5]) 615 | 616 | def p_labeled_statement(self, p): 617 | '''labeled_statement : label ':' statement''' 618 | p[3].label = p[1] 619 | p[0] = p[3] 620 | 621 | def p_labeled_statement_no_short_if(self, p): 622 | '''labeled_statement_no_short_if : label ':' statement_no_short_if''' 623 | p[3].label = p[1] 624 | p[0] = p[3] 625 | 626 | def p_label(self, p): 627 | '''label : NAME''' 628 | p[0] = p[1] 629 | 630 | def p_if_then_statement(self, p): 631 | '''if_then_statement : IF '(' expression ')' statement''' 632 | p[0] = IfThenElse(p[3], p[5]) 633 | 634 | def p_if_then_else_statement(self, p): 635 | '''if_then_else_statement : IF '(' expression ')' statement_no_short_if ELSE statement''' 636 | p[0] = IfThenElse(p[3], p[5], p[7]) 637 | 638 | def p_if_then_else_statement_no_short_if(self, p): 639 | '''if_then_else_statement_no_short_if : IF '(' expression ')' statement_no_short_if ELSE statement_no_short_if''' 640 | p[0] = IfThenElse(p[3], p[5], p[7]) 641 | 642 | def p_while_statement(self, p): 643 | '''while_statement : WHILE '(' expression ')' statement''' 644 | p[0] = While(p[3], p[5]) 645 | 646 | def p_while_statement_no_short_if(self, p): 647 | '''while_statement_no_short_if : WHILE '(' expression ')' statement_no_short_if''' 648 | p[0] = While(p[3], p[5]) 649 | 650 | def p_for_statement(self, p): 651 | '''for_statement : FOR '(' for_init_opt ';' expression_opt ';' for_update_opt ')' statement''' 652 | p[0] = For(p[3], p[5], p[7], p[9]) 653 | 654 | def p_for_statement_no_short_if(self, p): 655 | '''for_statement_no_short_if : FOR '(' for_init_opt ';' expression_opt ';' for_update_opt ')' statement_no_short_if''' 656 | p[0] = For(p[3], p[5], p[7], p[9]) 657 | 658 | def p_for_init_opt(self, p): 659 | '''for_init_opt : for_init 660 | | empty''' 661 | p[0] = p[1] 662 | 663 | def p_for_init(self, p): 664 | '''for_init : statement_expression_list 665 | | local_variable_declaration''' 666 | p[0] = p[1] 667 | 668 | def p_statement_expression_list(self, p): 669 | '''statement_expression_list : statement_expression 670 | | statement_expression_list ',' statement_expression''' 671 | if len(p) == 2: 672 | p[0] = [p[1]] 673 | else: 674 | p[0] = p[1] + [p[3]] 675 | 676 | def p_expression_opt(self, p): 677 | '''expression_opt : expression 678 | | empty''' 679 | p[0] = p[1] 680 | 681 | def p_for_update_opt(self, p): 682 | '''for_update_opt : for_update 683 | | empty''' 684 | p[0] = p[1] 685 | 686 | def p_for_update(self, p): 687 | '''for_update : statement_expression_list''' 688 | p[0] = p[1] 689 | 690 | def p_enhanced_for_statement(self, p): 691 | '''enhanced_for_statement : enhanced_for_statement_header statement''' 692 | p[0] = ForEach(p[1]['type'], p[1]['variable'], p[1]['iterable'], p[2], modifiers=p[1]['modifiers']) 693 | 694 | def p_enhanced_for_statement_no_short_if(self, p): 695 | '''enhanced_for_statement_no_short_if : enhanced_for_statement_header statement_no_short_if''' 696 | p[0] = ForEach(p[1]['type'], p[1]['variable'], p[1]['iterable'], p[2], modifiers=p[1]['modifiers']) 697 | 698 | def p_enhanced_for_statement_header(self, p): 699 | '''enhanced_for_statement_header : enhanced_for_statement_header_init ':' expression ')' ''' 700 | p[1]['iterable'] = p[3] 701 | p[0] = p[1] 702 | 703 | def p_enhanced_for_statement_header_init(self, p): 704 | '''enhanced_for_statement_header_init : FOR '(' type NAME dims_opt''' 705 | p[0] = {'modifiers': [], 'type': p[3], 'variable': Variable(p[4], dimensions=p[5])} 706 | 707 | def p_enhanced_for_statement_header_init2(self, p): 708 | '''enhanced_for_statement_header_init : FOR '(' modifiers type NAME dims_opt''' 709 | p[0] = {'modifiers': p[3], 'type': p[4], 'variable': Variable(p[5], dimensions=p[6])} 710 | 711 | def p_statement_no_short_if(self, p): 712 | '''statement_no_short_if : statement_without_trailing_substatement 713 | | labeled_statement_no_short_if 714 | | if_then_else_statement_no_short_if 715 | | while_statement_no_short_if 716 | | for_statement_no_short_if 717 | | enhanced_for_statement_no_short_if''' 718 | p[0] = p[1] 719 | 720 | def p_assert_statement(self, p): 721 | '''assert_statement : ASSERT expression ';' 722 | | ASSERT expression ':' expression ';' ''' 723 | if len(p) == 4: 724 | p[0] = Assert(p[2]) 725 | else: 726 | p[0] = Assert(p[2], message=p[4]) 727 | 728 | def p_empty_statement(self, p): 729 | '''empty_statement : ';' ''' 730 | p[0] = Empty() 731 | 732 | def p_switch_statement(self, p): 733 | '''switch_statement : SWITCH '(' expression ')' switch_block''' 734 | p[0] = Switch(p[3], p[5]) 735 | 736 | def p_switch_block(self, p): 737 | '''switch_block : '{' '}' ''' 738 | p[0] = [] 739 | 740 | def p_switch_block2(self, p): 741 | '''switch_block : '{' switch_block_statements '}' ''' 742 | p[0] = p[2] 743 | 744 | def p_switch_block3(self, p): 745 | '''switch_block : '{' switch_labels '}' ''' 746 | p[0] = [SwitchCase(p[2])] 747 | 748 | def p_switch_block4(self, p): 749 | '''switch_block : '{' switch_block_statements switch_labels '}' ''' 750 | p[0] = p[2] + [SwitchCase(p[3])] 751 | 752 | def p_switch_block_statements(self, p): 753 | '''switch_block_statements : switch_block_statement 754 | | switch_block_statements switch_block_statement''' 755 | if len(p) == 2: 756 | p[0] = [p[1]] 757 | else: 758 | p[0] = p[1] + [p[2]] 759 | 760 | def p_switch_block_statement(self, p): 761 | '''switch_block_statement : switch_labels block_statements''' 762 | p[0] = SwitchCase(p[1], body=p[2]) 763 | 764 | def p_switch_labels(self, p): 765 | '''switch_labels : switch_label 766 | | switch_labels switch_label''' 767 | if len(p) == 2: 768 | p[0] = [p[1]] 769 | else: 770 | p[0] = p[1] + [p[2]] 771 | 772 | def p_switch_label(self, p): 773 | '''switch_label : CASE constant_expression ':' 774 | | DEFAULT ':' ''' 775 | if len(p) == 3: 776 | p[0] = 'default' 777 | else: 778 | p[0] = p[2] 779 | 780 | def p_constant_expression(self, p): 781 | '''constant_expression : expression''' 782 | p[0] = p[1] 783 | 784 | def p_do_statement(self, p): 785 | '''do_statement : DO statement WHILE '(' expression ')' ';' ''' 786 | p[0] = DoWhile(p[5], body=p[2]) 787 | 788 | def p_break_statement(self, p): 789 | '''break_statement : BREAK ';' 790 | | BREAK NAME ';' ''' 791 | if len(p) == 3: 792 | p[0] = Break() 793 | else: 794 | p[0] = Break(p[2]) 795 | 796 | def p_continue_statement(self, p): 797 | '''continue_statement : CONTINUE ';' 798 | | CONTINUE NAME ';' ''' 799 | if len(p) == 3: 800 | p[0] = Continue() 801 | else: 802 | p[0] = Continue(p[2]) 803 | 804 | def p_return_statement(self, p): 805 | '''return_statement : RETURN expression_opt ';' ''' 806 | p[0] = Return(p[2]) 807 | 808 | def p_synchronized_statement(self, p): 809 | '''synchronized_statement : SYNCHRONIZED '(' expression ')' block''' 810 | p[0] = Synchronized(p[3], p[5]) 811 | 812 | def p_throw_statement(self, p): 813 | '''throw_statement : THROW expression ';' ''' 814 | p[0] = Throw(p[2]) 815 | 816 | def p_try_statement(self, p): 817 | '''try_statement : TRY try_block catches 818 | | TRY try_block catches_opt finally''' 819 | if len(p) == 4: 820 | p[0] = Try(p[2], catches=p[3]) 821 | else: 822 | p[0] = Try(p[2], catches=p[3], _finally=p[4]) 823 | 824 | def p_try_block(self, p): 825 | '''try_block : block''' 826 | p[0] = p[1] 827 | 828 | def p_catches(self, p): 829 | '''catches : catch_clause 830 | | catches catch_clause''' 831 | if len(p) == 2: 832 | p[0] = [p[1]] 833 | else: 834 | p[0] = p[1] + [p[2]] 835 | 836 | def p_catches_opt(self, p): 837 | '''catches_opt : catches''' 838 | p[0] = p[1] 839 | 840 | def p_catches_opt2(self, p): 841 | '''catches_opt : empty''' 842 | p[0] = [] 843 | 844 | def p_catch_clause(self, p): 845 | '''catch_clause : CATCH '(' catch_formal_parameter ')' block''' 846 | p[0] = Catch(p[3]['variable'], types=p[3]['types'], modifiers=p[3]['modifiers'], block=p[5]) 847 | 848 | def p_catch_formal_parameter(self, p): 849 | '''catch_formal_parameter : modifiers_opt catch_type variable_declarator_id''' 850 | p[0] = {'modifiers': p[1], 'types': p[2], 'variable': p[3]} 851 | 852 | def p_catch_type(self, p): 853 | '''catch_type : union_type''' 854 | p[0] = p[1] 855 | 856 | def p_union_type(self, p): 857 | '''union_type : type 858 | | union_type '|' type''' 859 | if len(p) == 2: 860 | p[0] = [p[1]] 861 | else: 862 | p[0] = p[1] + [p[3]] 863 | 864 | def p_try_statement_with_resources(self, p): 865 | '''try_statement_with_resources : TRY resource_specification try_block catches_opt 866 | | TRY resource_specification try_block catches_opt finally''' 867 | if len(p) == 5: 868 | p[0] = Try(p[3], resources=p[2], catches=p[4]) 869 | else: 870 | p[0] = Try(p[3], resources=p[2], catches=p[4], _finally=p[5]) 871 | 872 | def p_resource_specification(self, p): 873 | '''resource_specification : '(' resources semi_opt ')' ''' 874 | p[0] = p[2] 875 | 876 | def p_semi_opt(self, p): 877 | '''semi_opt : ';' 878 | | empty''' 879 | # ignore 880 | 881 | def p_resources(self, p): 882 | '''resources : resource 883 | | resources trailing_semicolon resource''' 884 | if len(p) == 2: 885 | p[0] = [p[1]] 886 | else: 887 | p[0] = p[1] + [p[3]] 888 | 889 | def p_trailing_semicolon(self, p): 890 | '''trailing_semicolon : ';' ''' 891 | # ignore 892 | 893 | def p_resource(self, p): 894 | '''resource : type variable_declarator_id '=' variable_initializer''' 895 | p[0] = Resource(p[2], type=p[1], initializer=p[4]) 896 | 897 | def p_resource2(self, p): 898 | '''resource : modifiers type variable_declarator_id '=' variable_initializer''' 899 | p[0] = Resource(p[3], type=p[2], modifiers=p[1], initializer=p[5]) 900 | 901 | def p_finally(self, p): 902 | '''finally : FINALLY block''' 903 | p[0] = p[2] 904 | 905 | def p_explicit_constructor_invocation(self, p): 906 | '''explicit_constructor_invocation : THIS '(' argument_list_opt ')' ';' 907 | | SUPER '(' argument_list_opt ')' ';' ''' 908 | p[0] = ConstructorInvocation(p[1], arguments=p[3]) 909 | 910 | def p_explicit_constructor_invocation2(self, p): 911 | '''explicit_constructor_invocation : type_arguments SUPER '(' argument_list_opt ')' ';' 912 | | type_arguments THIS '(' argument_list_opt ')' ';' ''' 913 | p[0] = ConstructorInvocation(p[2], type_arguments=p[1], arguments=p[4]) 914 | 915 | def p_explicit_constructor_invocation3(self, p): 916 | '''explicit_constructor_invocation : primary '.' SUPER '(' argument_list_opt ')' ';' 917 | | name '.' SUPER '(' argument_list_opt ')' ';' 918 | | primary '.' THIS '(' argument_list_opt ')' ';' 919 | | name '.' THIS '(' argument_list_opt ')' ';' ''' 920 | p[0] = ConstructorInvocation(p[3], target=p[1], arguments=p[5]) 921 | 922 | def p_explicit_constructor_invocation4(self, p): 923 | '''explicit_constructor_invocation : primary '.' type_arguments SUPER '(' argument_list_opt ')' ';' 924 | | name '.' type_arguments SUPER '(' argument_list_opt ')' ';' 925 | | primary '.' type_arguments THIS '(' argument_list_opt ')' ';' 926 | | name '.' type_arguments THIS '(' argument_list_opt ')' ';' ''' 927 | p[0] = ConstructorInvocation(p[4], target=p[1], type_arguments=p[3], arguments=p[6]) 928 | 929 | def p_class_instance_creation_expression(self, p): 930 | '''class_instance_creation_expression : NEW type_arguments class_type '(' argument_list_opt ')' class_body_opt''' 931 | p[0] = InstanceCreation(p[3], type_arguments=p[3], arguments=p[5], body=p[7]) 932 | 933 | def p_class_instance_creation_expression2(self, p): 934 | '''class_instance_creation_expression : NEW class_type '(' argument_list_opt ')' class_body_opt''' 935 | p[0] = InstanceCreation(p[2], arguments=p[4], body=p[6]) 936 | 937 | def p_class_instance_creation_expression3(self, p): 938 | '''class_instance_creation_expression : primary '.' NEW type_arguments class_type '(' argument_list_opt ')' class_body_opt''' 939 | p[0] = InstanceCreation(p[5], enclosed_in=p[1], type_arguments=p[4], arguments=p[7], body=p[9]) 940 | 941 | def p_class_instance_creation_expression4(self, p): 942 | '''class_instance_creation_expression : primary '.' NEW class_type '(' argument_list_opt ')' class_body_opt''' 943 | p[0] = InstanceCreation(p[4], enclosed_in=p[1], arguments=p[6], body=p[8]) 944 | 945 | def p_class_instance_creation_expression5(self, p): 946 | '''class_instance_creation_expression : class_instance_creation_expression_name NEW class_type '(' argument_list_opt ')' class_body_opt''' 947 | p[0] = InstanceCreation(p[3], enclosed_in=p[1], arguments=p[5], body=p[7]) 948 | 949 | def p_class_instance_creation_expression6(self, p): 950 | '''class_instance_creation_expression : class_instance_creation_expression_name NEW type_arguments class_type '(' argument_list_opt ')' class_body_opt''' 951 | p[0] = InstanceCreation(p[4], enclosed_in=p[1], type_arguments=p[3], arguments=p[6], body=p[8]) 952 | 953 | def p_class_instance_creation_expression_name(self, p): 954 | '''class_instance_creation_expression_name : name '.' ''' 955 | p[0] = p[1] 956 | 957 | def p_class_body_opt(self, p): 958 | '''class_body_opt : class_body 959 | | empty''' 960 | p[0] = p[1] 961 | 962 | def p_field_access(self, p): 963 | '''field_access : primary '.' NAME 964 | | SUPER '.' NAME''' 965 | p[0] = FieldAccess(p[3], p[1]) 966 | 967 | def p_array_access(self, p): 968 | '''array_access : name '[' expression ']' 969 | | primary_no_new_array '[' expression ']' 970 | | array_creation_with_array_initializer '[' expression ']' ''' 971 | p[0] = ArrayAccess(p[3], p[1]) 972 | 973 | def p_array_creation_with_array_initializer(self, p): 974 | '''array_creation_with_array_initializer : NEW primitive_type dim_with_or_without_exprs array_initializer 975 | | NEW class_or_interface_type dim_with_or_without_exprs array_initializer''' 976 | p[0] = ArrayCreation(p[2], dimensions=p[3], initializer=p[4]) 977 | 978 | def p_dim_with_or_without_exprs(self, p): 979 | '''dim_with_or_without_exprs : dim_with_or_without_expr 980 | | dim_with_or_without_exprs dim_with_or_without_expr''' 981 | if len(p) == 2: 982 | p[0] = [p[1]] 983 | else: 984 | p[0] = p[1] + [p[2]] 985 | 986 | def p_dim_with_or_without_expr(self, p): 987 | '''dim_with_or_without_expr : '[' expression ']' 988 | | '[' ']' ''' 989 | if len(p) == 3: 990 | p[0] = None 991 | else: 992 | p[0] = p[2] 993 | 994 | def p_array_creation_without_array_initializer(self, p): 995 | '''array_creation_without_array_initializer : NEW primitive_type dim_with_or_without_exprs 996 | | NEW class_or_interface_type dim_with_or_without_exprs''' 997 | p[0] = ArrayCreation(p[2], dimensions=p[3]) 998 | 999 | class NameParser(object): 1000 | 1001 | def p_name(self, p): 1002 | '''name : simple_name 1003 | | qualified_name''' 1004 | p[0] = p[1] 1005 | 1006 | def p_simple_name(self, p): 1007 | '''simple_name : NAME''' 1008 | p[0] = Name(p[1]) 1009 | 1010 | def p_qualified_name(self, p): 1011 | '''qualified_name : name '.' simple_name''' 1012 | p[1].append_name(p[3]) 1013 | p[0] = p[1] 1014 | 1015 | class LiteralParser(object): 1016 | 1017 | def p_literal(self, p): 1018 | '''literal : NUM 1019 | | CHAR_LITERAL 1020 | | STRING_LITERAL 1021 | | TRUE 1022 | | FALSE 1023 | | NULL''' 1024 | p[0] = Literal(p[1]) 1025 | 1026 | class TypeParser(object): 1027 | 1028 | def p_modifiers_opt(self, p): 1029 | '''modifiers_opt : modifiers''' 1030 | p[0] = p[1] 1031 | 1032 | def p_modifiers_opt2(self, p): 1033 | '''modifiers_opt : empty''' 1034 | p[0] = [] 1035 | 1036 | def p_modifiers(self, p): 1037 | '''modifiers : modifier 1038 | | modifiers modifier''' 1039 | if len(p) == 2: 1040 | p[0] = [p[1]] 1041 | else: 1042 | p[0] = p[1] + [p[2]] 1043 | 1044 | def p_modifier(self, p): 1045 | '''modifier : PUBLIC 1046 | | PROTECTED 1047 | | PRIVATE 1048 | | STATIC 1049 | | ABSTRACT 1050 | | FINAL 1051 | | NATIVE 1052 | | SYNCHRONIZED 1053 | | TRANSIENT 1054 | | VOLATILE 1055 | | STRICTFP 1056 | | annotation''' 1057 | p[0] = p[1] 1058 | 1059 | def p_type(self, p): 1060 | '''type : primitive_type 1061 | | reference_type''' 1062 | p[0] = p[1] 1063 | 1064 | def p_primitive_type(self, p): 1065 | '''primitive_type : BOOLEAN 1066 | | VOID 1067 | | BYTE 1068 | | SHORT 1069 | | INT 1070 | | LONG 1071 | | CHAR 1072 | | FLOAT 1073 | | DOUBLE''' 1074 | p[0] = p[1] 1075 | 1076 | def p_reference_type(self, p): 1077 | '''reference_type : class_or_interface_type 1078 | | array_type''' 1079 | p[0] = p[1] 1080 | 1081 | def p_class_or_interface_type(self, p): 1082 | '''class_or_interface_type : class_or_interface 1083 | | generic_type''' 1084 | p[0] = p[1] 1085 | 1086 | def p_class_type(self, p): 1087 | '''class_type : class_or_interface_type''' 1088 | p[0] = p[1] 1089 | 1090 | def p_class_or_interface(self, p): 1091 | '''class_or_interface : name 1092 | | generic_type '.' name''' 1093 | if len(p) == 2: 1094 | p[0] = Type(p[1]) 1095 | else: 1096 | p[0] = Type(p[3], enclosed_in=p[1]) 1097 | 1098 | def p_generic_type(self, p): 1099 | '''generic_type : class_or_interface type_arguments''' 1100 | p[1].type_arguments = p[2] 1101 | p[0] = p[1] 1102 | 1103 | def p_generic_type2(self, p): 1104 | '''generic_type : class_or_interface '<' '>' ''' 1105 | p[0] = Type(p[1], type_arguments='diamond') 1106 | 1107 | # def p_array_type(self, p): 1108 | # '''array_type : primitive_type dims 1109 | # | name dims 1110 | # | array_type_with_type_arguments_name dims 1111 | # | generic_type dims''' 1112 | # p[0] = p[1] + '[' + p[2] + ']' 1113 | # 1114 | # def p_array_type_with_type_arguments_name(self, p): 1115 | # '''array_type_with_type_arguments_name : generic_type '.' name''' 1116 | # p[0] = p[1] + '.' + p[3] 1117 | 1118 | def p_array_type(self, p): 1119 | '''array_type : primitive_type dims 1120 | | name dims''' 1121 | p[0] = Type(p[1], dimensions=p[2]) 1122 | 1123 | def p_array_type2(self, p): 1124 | '''array_type : generic_type dims''' 1125 | p[1].dimensions = p[2] 1126 | p[0] = p[1] 1127 | 1128 | def p_array_type3(self, p): 1129 | '''array_type : generic_type '.' name dims''' 1130 | p[0] = Type(p[3], enclosed_in=p[1], dimensions=p[4]) 1131 | 1132 | def p_type_arguments(self, p): 1133 | '''type_arguments : '<' type_argument_list1''' 1134 | p[0] = p[2] 1135 | 1136 | def p_type_argument_list1(self, p): 1137 | '''type_argument_list1 : type_argument1 1138 | | type_argument_list ',' type_argument1''' 1139 | if len(p) == 2: 1140 | p[0] = [p[1]] 1141 | else: 1142 | p[0] = p[1] + [p[3]] 1143 | 1144 | def p_type_argument_list(self, p): 1145 | '''type_argument_list : type_argument 1146 | | type_argument_list ',' type_argument''' 1147 | if len(p) == 2: 1148 | p[0] = [p[1]] 1149 | else: 1150 | p[0] = p[1] + [p[3]] 1151 | 1152 | def p_type_argument(self, p): 1153 | '''type_argument : reference_type 1154 | | wildcard''' 1155 | p[0] = p[1] 1156 | 1157 | def p_type_argument1(self, p): 1158 | '''type_argument1 : reference_type1 1159 | | wildcard1''' 1160 | p[0] = p[1] 1161 | 1162 | def p_reference_type1(self, p): 1163 | '''reference_type1 : reference_type '>' 1164 | | class_or_interface '<' type_argument_list2''' 1165 | if len(p) == 3: 1166 | p[0] = p[1] 1167 | else: 1168 | p[1].type_arguments = p[3] 1169 | p[0] = p[1] 1170 | 1171 | def p_type_argument_list2(self, p): 1172 | '''type_argument_list2 : type_argument2 1173 | | type_argument_list ',' type_argument2''' 1174 | if len(p) == 2: 1175 | p[0] = [p[1]] 1176 | else: 1177 | p[0] = p[1] + [p[3]] 1178 | 1179 | def p_type_argument2(self, p): 1180 | '''type_argument2 : reference_type2 1181 | | wildcard2''' 1182 | p[0] = p[1] 1183 | 1184 | def p_reference_type2(self, p): 1185 | '''reference_type2 : reference_type RSHIFT 1186 | | class_or_interface '<' type_argument_list3''' 1187 | if len(p) == 3: 1188 | p[0] = p[1] 1189 | else: 1190 | p[1].type_arguments = p[3] 1191 | p[0] = p[1] 1192 | 1193 | def p_type_argument_list3(self, p): 1194 | '''type_argument_list3 : type_argument3 1195 | | type_argument_list ',' type_argument3''' 1196 | if len(p) == 2: 1197 | p[0] = [p[1]] 1198 | else: 1199 | p[0] = p[1] + [p[3]] 1200 | 1201 | def p_type_argument3(self, p): 1202 | '''type_argument3 : reference_type3 1203 | | wildcard3''' 1204 | p[0] = p[1] 1205 | 1206 | def p_reference_type3(self, p): 1207 | '''reference_type3 : reference_type RRSHIFT''' 1208 | p[0] = p[1] 1209 | 1210 | def p_wildcard(self, p): 1211 | '''wildcard : '?' 1212 | | '?' wildcard_bounds''' 1213 | if len(p) == 2: 1214 | p[0] = Wildcard() 1215 | else: 1216 | p[0] = Wildcard(bounds=p[2]) 1217 | 1218 | def p_wildcard_bounds(self, p): 1219 | '''wildcard_bounds : EXTENDS reference_type 1220 | | SUPER reference_type''' 1221 | if p[1] == 'extends': 1222 | p[0] = WildcardBound(p[2], extends=True) 1223 | else: 1224 | p[0] = WildcardBound(p[2], _super=True) 1225 | 1226 | def p_wildcard1(self, p): 1227 | '''wildcard1 : '?' '>' 1228 | | '?' wildcard_bounds1''' 1229 | if p[2] == '>': 1230 | p[0] = Wildcard() 1231 | else: 1232 | p[0] = Wildcard(bounds=p[2]) 1233 | 1234 | def p_wildcard_bounds1(self, p): 1235 | '''wildcard_bounds1 : EXTENDS reference_type1 1236 | | SUPER reference_type1''' 1237 | if p[1] == 'extends': 1238 | p[0] = WildcardBound(p[2], extends=True) 1239 | else: 1240 | p[0] = WildcardBound(p[2], _super=True) 1241 | 1242 | def p_wildcard2(self, p): 1243 | '''wildcard2 : '?' RSHIFT 1244 | | '?' wildcard_bounds2''' 1245 | if p[2] == '>>': 1246 | p[0] = Wildcard() 1247 | else: 1248 | p[0] = Wildcard(bounds=p[2]) 1249 | 1250 | def p_wildcard_bounds2(self, p): 1251 | '''wildcard_bounds2 : EXTENDS reference_type2 1252 | | SUPER reference_type2''' 1253 | if p[1] == 'extends': 1254 | p[0] = WildcardBound(p[2], extends=True) 1255 | else: 1256 | p[0] = WildcardBound(p[2], _super=True) 1257 | 1258 | def p_wildcard3(self, p): 1259 | '''wildcard3 : '?' RRSHIFT 1260 | | '?' wildcard_bounds3''' 1261 | if p[2] == '>>>': 1262 | p[0] = Wildcard() 1263 | else: 1264 | p[0] = Wildcard(bounds=p[2]) 1265 | 1266 | def p_wildcard_bounds3(self, p): 1267 | '''wildcard_bounds3 : EXTENDS reference_type3 1268 | | SUPER reference_type3''' 1269 | if p[1] == 'extends': 1270 | p[0] = WildcardBound(p[2], extends=True) 1271 | else: 1272 | p[0] = WildcardBound(p[2], _super=True) 1273 | 1274 | def p_type_parameter_header(self, p): 1275 | '''type_parameter_header : NAME''' 1276 | p[0] = p[1] 1277 | 1278 | def p_type_parameters(self, p): 1279 | '''type_parameters : '<' type_parameter_list1''' 1280 | p[0] = p[2] 1281 | 1282 | def p_type_parameter_list(self, p): 1283 | '''type_parameter_list : type_parameter 1284 | | type_parameter_list ',' type_parameter''' 1285 | if len(p) == 2: 1286 | p[0] = [p[1]] 1287 | else: 1288 | p[0] = p[1] + [p[3]] 1289 | 1290 | def p_type_parameter(self, p): 1291 | '''type_parameter : type_parameter_header 1292 | | type_parameter_header EXTENDS reference_type 1293 | | type_parameter_header EXTENDS reference_type additional_bound_list''' 1294 | if len(p) == 2: 1295 | p[0] = TypeParameter(p[1]) 1296 | elif len(p) == 4: 1297 | p[0] = TypeParameter(p[1], extends=[p[3]]) 1298 | else: 1299 | p[0] = TypeParameter(p[1], extends=[p[3]] + p[4]) 1300 | 1301 | def p_additional_bound_list(self, p): 1302 | '''additional_bound_list : additional_bound 1303 | | additional_bound_list additional_bound''' 1304 | if len(p) == 2: 1305 | p[0] = [p[1]] 1306 | else: 1307 | p[0] = p[1] + [p[2]] 1308 | 1309 | def p_additional_bound(self, p): 1310 | '''additional_bound : '&' reference_type''' 1311 | p[0] = p[2] 1312 | 1313 | def p_type_parameter_list1(self, p): 1314 | '''type_parameter_list1 : type_parameter1 1315 | | type_parameter_list ',' type_parameter1''' 1316 | if len(p) == 2: 1317 | p[0] = [p[1]] 1318 | else: 1319 | p[0] = p[1] + [p[3]] 1320 | 1321 | def p_type_parameter1(self, p): 1322 | '''type_parameter1 : type_parameter_header '>' 1323 | | type_parameter_header EXTENDS reference_type1 1324 | | type_parameter_header EXTENDS reference_type additional_bound_list1''' 1325 | if len(p) == 3: 1326 | p[0] = TypeParameter(p[1]) 1327 | elif len(p) == 4: 1328 | p[0] = TypeParameter(p[1], extends=[p[3]]) 1329 | else: 1330 | p[0] = TypeParameter(p[1], extends=[p[3]] + p[4]) 1331 | 1332 | def p_additional_bound_list1(self, p): 1333 | '''additional_bound_list1 : additional_bound1 1334 | | additional_bound_list additional_bound1''' 1335 | if len(p) == 2: 1336 | p[0] = [p[1]] 1337 | else: 1338 | p[0] = p[1] + [p[2]] 1339 | 1340 | def p_additional_bound1(self, p): 1341 | '''additional_bound1 : '&' reference_type1''' 1342 | p[0] = p[2] 1343 | 1344 | class ClassParser(object): 1345 | 1346 | def p_type_declaration(self, p): 1347 | '''type_declaration : class_declaration 1348 | | interface_declaration 1349 | | enum_declaration 1350 | | annotation_type_declaration''' 1351 | p[0] = p[1] 1352 | 1353 | def p_type_declaration2(self, p): 1354 | '''type_declaration : ';' ''' 1355 | p[0] = EmptyDeclaration() 1356 | 1357 | def p_class_declaration(self, p): 1358 | '''class_declaration : class_header class_body''' 1359 | p[0] = ClassDeclaration(p[1]['name'], p[2], modifiers=p[1]['modifiers'], 1360 | extends=p[1]['extends'], implements=p[1]['implements'], 1361 | type_parameters=p[1]['type_parameters']) 1362 | 1363 | def p_class_header(self, p): 1364 | '''class_header : class_header_name class_header_extends_opt class_header_implements_opt''' 1365 | p[1]['extends'] = p[2] 1366 | p[1]['implements'] = p[3] 1367 | p[0] = p[1] 1368 | 1369 | def p_class_header_name(self, p): 1370 | '''class_header_name : class_header_name1 type_parameters 1371 | | class_header_name1''' 1372 | if len(p) == 2: 1373 | p[1]['type_parameters'] = [] 1374 | else: 1375 | p[1]['type_parameters'] = p[2] 1376 | p[0] = p[1] 1377 | 1378 | def p_class_header_name1(self, p): 1379 | '''class_header_name1 : modifiers_opt CLASS NAME''' 1380 | p[0] = {'modifiers': p[1], 'name': p[3]} 1381 | 1382 | def p_class_header_extends_opt(self, p): 1383 | '''class_header_extends_opt : class_header_extends 1384 | | empty''' 1385 | p[0] = p[1] 1386 | 1387 | def p_class_header_extends(self, p): 1388 | '''class_header_extends : EXTENDS class_type''' 1389 | p[0] = p[2] 1390 | 1391 | def p_class_header_implements_opt(self, p): 1392 | '''class_header_implements_opt : class_header_implements 1393 | | empty''' 1394 | p[0] = p[1] 1395 | 1396 | def p_class_header_implements(self, p): 1397 | '''class_header_implements : IMPLEMENTS interface_type_list''' 1398 | p[0] = p[2] 1399 | 1400 | def p_interface_type_list(self, p): 1401 | '''interface_type_list : interface_type 1402 | | interface_type_list ',' interface_type''' 1403 | if len(p) == 2: 1404 | p[0] = [p[1]] 1405 | else: 1406 | p[0] = p[1] + [p[3]] 1407 | 1408 | def p_interface_type(self, p): 1409 | '''interface_type : class_or_interface_type''' 1410 | p[0] = p[1] 1411 | 1412 | def p_class_body(self, p): 1413 | '''class_body : '{' class_body_declarations_opt '}' ''' 1414 | p[0] = p[2] 1415 | 1416 | def p_class_body_declarations_opt(self, p): 1417 | '''class_body_declarations_opt : class_body_declarations''' 1418 | p[0] = p[1] 1419 | 1420 | def p_class_body_declarations_opt2(self, p): 1421 | '''class_body_declarations_opt : empty''' 1422 | p[0] = [] 1423 | 1424 | def p_class_body_declarations(self, p): 1425 | '''class_body_declarations : class_body_declaration 1426 | | class_body_declarations class_body_declaration''' 1427 | if len(p) == 2: 1428 | p[0] = [p[1]] 1429 | else: 1430 | p[0] = p[1] + [p[2]] 1431 | 1432 | def p_class_body_declaration(self, p): 1433 | '''class_body_declaration : class_member_declaration 1434 | | static_initializer 1435 | | constructor_declaration''' 1436 | p[0] = p[1] 1437 | 1438 | def p_class_body_declaration2(self, p): 1439 | '''class_body_declaration : block''' 1440 | p[0] = ClassInitializer(p[1]) 1441 | 1442 | def p_class_member_declaration(self, p): 1443 | '''class_member_declaration : field_declaration 1444 | | class_declaration 1445 | | method_declaration 1446 | | interface_declaration 1447 | | enum_declaration 1448 | | annotation_type_declaration''' 1449 | p[0] = p[1] 1450 | 1451 | def p_class_member_declaration2(self, p): 1452 | '''class_member_declaration : ';' ''' 1453 | p[0] = EmptyDeclaration() 1454 | 1455 | def p_field_declaration(self, p): 1456 | '''field_declaration : modifiers_opt type variable_declarators ';' ''' 1457 | p[0] = FieldDeclaration(p[2], p[3], modifiers=p[1]) 1458 | 1459 | def p_static_initializer(self, p): 1460 | '''static_initializer : STATIC block''' 1461 | p[0] = ClassInitializer(p[2], static=True) 1462 | 1463 | def p_constructor_declaration(self, p): 1464 | '''constructor_declaration : constructor_header method_body''' 1465 | p[0] = ConstructorDeclaration(p[1]['name'], p[2], modifiers=p[1]['modifiers'], 1466 | type_parameters=p[1]['type_parameters'], 1467 | parameters=p[1]['parameters'], throws=p[1]['throws']) 1468 | 1469 | def p_constructor_header(self, p): 1470 | '''constructor_header : constructor_header_name formal_parameter_list_opt ')' method_header_throws_clause_opt''' 1471 | p[1]['parameters'] = p[2] 1472 | p[1]['throws'] = p[4] 1473 | p[0] = p[1] 1474 | 1475 | def p_constructor_header_name(self, p): 1476 | '''constructor_header_name : modifiers_opt type_parameters NAME '(' 1477 | | modifiers_opt NAME '(' ''' 1478 | if len(p) == 4: 1479 | p[0] = {'modifiers': p[1], 'type_parameters': [], 'name': p[2]} 1480 | else: 1481 | p[0] = {'modifiers': p[1], 'type_parameters': p[2], 'name': p[3]} 1482 | 1483 | def p_formal_parameter_list_opt(self, p): 1484 | '''formal_parameter_list_opt : formal_parameter_list''' 1485 | p[0] = p[1] 1486 | 1487 | def p_formal_parameter_list_opt2(self, p): 1488 | '''formal_parameter_list_opt : empty''' 1489 | p[0] = [] 1490 | 1491 | def p_formal_parameter_list(self, p): 1492 | '''formal_parameter_list : formal_parameter 1493 | | formal_parameter_list ',' formal_parameter''' 1494 | if len(p) == 2: 1495 | p[0] = [p[1]] 1496 | else: 1497 | p[0] = p[1] + [p[3]] 1498 | 1499 | def p_formal_parameter(self, p): 1500 | '''formal_parameter : modifiers_opt type variable_declarator_id 1501 | | modifiers_opt type ELLIPSIS variable_declarator_id''' 1502 | if len(p) == 4: 1503 | p[0] = FormalParameter(p[3], p[2], modifiers=p[1]) 1504 | else: 1505 | p[0] = FormalParameter(p[4], p[2], modifiers=p[1], vararg=True) 1506 | 1507 | def p_method_header_throws_clause_opt(self, p): 1508 | '''method_header_throws_clause_opt : method_header_throws_clause 1509 | | empty''' 1510 | p[0] = p[1] 1511 | 1512 | def p_method_header_throws_clause(self, p): 1513 | '''method_header_throws_clause : THROWS class_type_list''' 1514 | p[0] = Throws(p[2]) 1515 | 1516 | def p_class_type_list(self, p): 1517 | '''class_type_list : class_type_elt 1518 | | class_type_list ',' class_type_elt''' 1519 | if len(p) == 2: 1520 | p[0] = [p[1]] 1521 | else: 1522 | p[0] = p[1] + [p[3]] 1523 | 1524 | def p_class_type_elt(self, p): 1525 | '''class_type_elt : class_type''' 1526 | p[0] = p[1] 1527 | 1528 | def p_method_body(self, p): 1529 | '''method_body : '{' block_statements_opt '}' ''' 1530 | p[0] = p[2] 1531 | 1532 | def p_method_declaration(self, p): 1533 | '''method_declaration : abstract_method_declaration 1534 | | method_header method_body''' 1535 | if len(p) == 2: 1536 | p[0] = p[1] 1537 | else: 1538 | p[0] = MethodDeclaration(p[1]['name'], parameters=p[1]['parameters'], 1539 | extended_dims=p[1]['extended_dims'], type_parameters=p[1]['type_parameters'], 1540 | return_type=p[1]['type'], modifiers=p[1]['modifiers'], 1541 | throws=p[1]['throws'], body=p[2]) 1542 | 1543 | def p_abstract_method_declaration(self, p): 1544 | '''abstract_method_declaration : method_header ';' ''' 1545 | p[0] = MethodDeclaration(p[1]['name'], abstract=True, parameters=p[1]['parameters'], 1546 | extended_dims=p[1]['extended_dims'], type_parameters=p[1]['type_parameters'], 1547 | return_type=p[1]['type'], modifiers=p[1]['modifiers'], 1548 | throws=p[1]['throws']) 1549 | 1550 | def p_method_header(self, p): 1551 | '''method_header : method_header_name formal_parameter_list_opt ')' method_header_extended_dims method_header_throws_clause_opt''' 1552 | p[1]['parameters'] = p[2] 1553 | p[1]['extended_dims'] = p[4] 1554 | p[1]['throws'] = p[5] 1555 | p[0] = p[1] 1556 | 1557 | def p_method_header_name(self, p): 1558 | '''method_header_name : modifiers_opt type_parameters type NAME '(' 1559 | | modifiers_opt type NAME '(' ''' 1560 | if len(p) == 5: 1561 | p[0] = {'modifiers': p[1], 'type_parameters': [], 'type': p[2], 'name': p[3]} 1562 | else: 1563 | p[0] = {'modifiers': p[1], 'type_parameters': p[2], 'type': p[3], 'name': p[4]} 1564 | 1565 | def p_method_header_extended_dims(self, p): 1566 | '''method_header_extended_dims : dims_opt''' 1567 | p[0] = p[1] 1568 | 1569 | def p_interface_declaration(self, p): 1570 | '''interface_declaration : interface_header interface_body''' 1571 | p[0] = InterfaceDeclaration(p[1]['name'], modifiers=p[1]['modifiers'], 1572 | type_parameters=p[1]['type_parameters'], 1573 | extends=p[1]['extends'], 1574 | body=p[2]) 1575 | 1576 | def p_interface_header(self, p): 1577 | '''interface_header : interface_header_name interface_header_extends_opt''' 1578 | p[1]['extends'] = p[2] 1579 | p[0] = p[1] 1580 | 1581 | def p_interface_header_name(self, p): 1582 | '''interface_header_name : interface_header_name1 type_parameters 1583 | | interface_header_name1''' 1584 | if len(p) == 2: 1585 | p[1]['type_parameters'] = [] 1586 | else: 1587 | p[1]['type_parameters'] = p[2] 1588 | p[0] = p[1] 1589 | 1590 | def p_interface_header_name1(self, p): 1591 | '''interface_header_name1 : modifiers_opt INTERFACE NAME''' 1592 | p[0] = {'modifiers': p[1], 'name': p[3]} 1593 | 1594 | def p_interface_header_extends_opt(self, p): 1595 | '''interface_header_extends_opt : interface_header_extends''' 1596 | p[0] = p[1] 1597 | 1598 | def p_interface_header_extends_opt2(self, p): 1599 | '''interface_header_extends_opt : empty''' 1600 | p[0] = [] 1601 | 1602 | def p_interface_header_extends(self, p): 1603 | '''interface_header_extends : EXTENDS interface_type_list''' 1604 | p[0] = p[2] 1605 | 1606 | def p_interface_body(self, p): 1607 | '''interface_body : '{' interface_member_declarations_opt '}' ''' 1608 | p[0] = p[2] 1609 | 1610 | def p_interface_member_declarations_opt(self, p): 1611 | '''interface_member_declarations_opt : interface_member_declarations''' 1612 | p[0] = p[1] 1613 | 1614 | def p_interface_member_declarations_opt2(self, p): 1615 | '''interface_member_declarations_opt : empty''' 1616 | p[0] = [] 1617 | 1618 | def p_interface_member_declarations(self, p): 1619 | '''interface_member_declarations : interface_member_declaration 1620 | | interface_member_declarations interface_member_declaration''' 1621 | if len(p) == 2: 1622 | p[0] = [p[1]] 1623 | else: 1624 | p[0] = p[1] + [p[2]] 1625 | 1626 | def p_interface_member_declaration(self, p): 1627 | '''interface_member_declaration : constant_declaration 1628 | | abstract_method_declaration 1629 | | class_declaration 1630 | | interface_declaration 1631 | | enum_declaration 1632 | | annotation_type_declaration''' 1633 | p[0] = p[1] 1634 | 1635 | def p_interface_member_declaration2(self, p): 1636 | '''interface_member_declaration : ';' ''' 1637 | p[0] = EmptyDeclaration() 1638 | 1639 | def p_constant_declaration(self, p): 1640 | '''constant_declaration : field_declaration''' 1641 | p[0] = p[1] 1642 | 1643 | def p_enum_declaration(self, p): 1644 | '''enum_declaration : enum_header enum_body''' 1645 | p[0] = EnumDeclaration(p[1]['name'], implements=p[1]['implements'], 1646 | modifiers=p[1]['modifiers'], 1647 | type_parameters=p[1]['type_parameters'], body=p[2]) 1648 | 1649 | def p_enum_header(self, p): 1650 | '''enum_header : enum_header_name class_header_implements_opt''' 1651 | p[1]['implements'] = p[2] 1652 | p[0] = p[1] 1653 | 1654 | def p_enum_header_name(self, p): 1655 | '''enum_header_name : modifiers_opt ENUM NAME 1656 | | modifiers_opt ENUM NAME type_parameters''' 1657 | if len(p) == 4: 1658 | p[0] = {'modifiers': p[1], 'name': p[3], 'type_parameters': []} 1659 | else: 1660 | p[0] = {'modifiers': p[1], 'name': p[3], 'type_parameters': p[4]} 1661 | 1662 | def p_enum_body(self, p): 1663 | '''enum_body : '{' enum_body_declarations_opt '}' ''' 1664 | p[0] = p[2] 1665 | 1666 | def p_enum_body2(self, p): 1667 | '''enum_body : '{' ',' enum_body_declarations_opt '}' ''' 1668 | p[0] = p[3] 1669 | 1670 | def p_enum_body3(self, p): 1671 | '''enum_body : '{' enum_constants ',' enum_body_declarations_opt '}' ''' 1672 | p[0] = p[2] + p[4] 1673 | 1674 | def p_enum_body4(self, p): 1675 | '''enum_body : '{' enum_constants enum_body_declarations_opt '}' ''' 1676 | p[0] = p[2] + p[3] 1677 | 1678 | def p_enum_constants(self, p): 1679 | '''enum_constants : enum_constant 1680 | | enum_constants ',' enum_constant''' 1681 | if len(p) == 2: 1682 | p[0] = [p[1]] 1683 | else: 1684 | p[0] = p[1] + [p[3]] 1685 | 1686 | def p_enum_constant(self, p): 1687 | '''enum_constant : enum_constant_header class_body 1688 | | enum_constant_header''' 1689 | if len(p) == 2: 1690 | p[0] = EnumConstant(p[1]['name'], arguments=p[1]['arguments'], modifiers=p[1]['modifiers']) 1691 | else: 1692 | p[0] = EnumConstant(p[1]['name'], arguments=p[1]['arguments'], modifiers=p[1]['modifiers'], body=p[2]) 1693 | 1694 | def p_enum_constant_header(self, p): 1695 | '''enum_constant_header : enum_constant_header_name arguments_opt''' 1696 | p[1]['arguments'] = p[2] 1697 | p[0] = p[1] 1698 | 1699 | def p_enum_constant_header_name(self, p): 1700 | '''enum_constant_header_name : modifiers_opt NAME''' 1701 | p[0] = {'modifiers': p[1], 'name': p[2]} 1702 | 1703 | def p_arguments_opt(self, p): 1704 | '''arguments_opt : arguments''' 1705 | p[0] = p[1] 1706 | 1707 | def p_arguments_opt2(self, p): 1708 | '''arguments_opt : empty''' 1709 | p[0] = [] 1710 | 1711 | def p_arguments(self, p): 1712 | '''arguments : '(' argument_list_opt ')' ''' 1713 | p[0] = p[2] 1714 | 1715 | def p_argument_list_opt(self, p): 1716 | '''argument_list_opt : argument_list''' 1717 | p[0] = p[1] 1718 | 1719 | def p_argument_list_opt2(self, p): 1720 | '''argument_list_opt : empty''' 1721 | p[0] = [] 1722 | 1723 | def p_argument_list(self, p): 1724 | '''argument_list : expression 1725 | | argument_list ',' expression''' 1726 | if len(p) == 2: 1727 | p[0] = [p[1]] 1728 | else: 1729 | p[0] = p[1] + [p[3]] 1730 | 1731 | def p_enum_body_declarations_opt(self, p): 1732 | '''enum_body_declarations_opt : enum_declarations''' 1733 | p[0] = p[1] 1734 | 1735 | def p_enum_body_declarations_opt2(self, p): 1736 | '''enum_body_declarations_opt : empty''' 1737 | p[0] = [] 1738 | 1739 | def p_enum_body_declarations(self, p): 1740 | '''enum_declarations : ';' class_body_declarations_opt''' 1741 | p[0] = p[2] 1742 | 1743 | def p_annotation_type_declaration(self, p): 1744 | '''annotation_type_declaration : annotation_type_declaration_header annotation_type_body''' 1745 | p[0] = AnnotationDeclaration(p[1]['name'], modifiers=p[1]['modifiers'], 1746 | type_parameters=p[1]['type_parameters'], 1747 | extends=p[1]['extends'], implements=p[1]['implements'], 1748 | body=p[2]) 1749 | 1750 | def p_annotation_type_declaration_header(self, p): 1751 | '''annotation_type_declaration_header : annotation_type_declaration_header_name class_header_extends_opt class_header_implements_opt''' 1752 | p[1]['extends'] = p[2] 1753 | p[1]['implements'] = p[3] 1754 | p[0] = p[1] 1755 | 1756 | def p_annotation_type_declaration_header_name(self, p): 1757 | '''annotation_type_declaration_header_name : modifiers '@' INTERFACE NAME''' 1758 | p[0] = {'modifiers': p[1], 'name': p[4], 'type_parameters': []} 1759 | 1760 | def p_annotation_type_declaration_header_name2(self, p): 1761 | '''annotation_type_declaration_header_name : modifiers '@' INTERFACE NAME type_parameters''' 1762 | p[0] = {'modifiers': p[1], 'name': p[4], 'type_parameters': p[5]} 1763 | 1764 | def p_annotation_type_declaration_header_name3(self, p): 1765 | '''annotation_type_declaration_header_name : '@' INTERFACE NAME type_parameters''' 1766 | p[0] = {'modifiers': [], 'name': p[3], 'type_parameters': p[4]} 1767 | 1768 | def p_annotation_type_declaration_header_name4(self, p): 1769 | '''annotation_type_declaration_header_name : '@' INTERFACE NAME''' 1770 | p[0] = {'modifiers': [], 'name': p[3], 'type_parameters': []} 1771 | 1772 | def p_annotation_type_body(self, p): 1773 | '''annotation_type_body : '{' annotation_type_member_declarations_opt '}' ''' 1774 | p[0] = p[2] 1775 | 1776 | def p_annotation_type_member_declarations_opt(self, p): 1777 | '''annotation_type_member_declarations_opt : annotation_type_member_declarations''' 1778 | p[0] = p[1] 1779 | 1780 | def p_annotation_type_member_declarations_opt2(self, p): 1781 | '''annotation_type_member_declarations_opt : empty''' 1782 | p[0] = [] 1783 | 1784 | def p_annotation_type_member_declarations(self, p): 1785 | '''annotation_type_member_declarations : annotation_type_member_declaration 1786 | | annotation_type_member_declarations annotation_type_member_declaration''' 1787 | if len(p) == 2: 1788 | p[0] = [p[1]] 1789 | else: 1790 | p[0] = p[1] + [p[2]] 1791 | 1792 | def p_annotation_type_member_declaration(self, p): 1793 | '''annotation_type_member_declaration : annotation_method_header ';' 1794 | | constant_declaration 1795 | | constructor_declaration 1796 | | type_declaration''' 1797 | p[0] = p[1] 1798 | 1799 | def p_annotation_method_header(self, p): 1800 | '''annotation_method_header : annotation_method_header_name formal_parameter_list_opt ')' method_header_extended_dims annotation_method_header_default_value_opt''' 1801 | p[0] = AnnotationMethodDeclaration(p[1]['name'], p[1]['type'], parameters=p[2], 1802 | default=p[5], extended_dims=p[4], 1803 | type_parameters=p[1]['type_parameters'], 1804 | modifiers=p[1]['modifiers']) 1805 | 1806 | def p_annotation_method_header_name(self, p): 1807 | '''annotation_method_header_name : modifiers_opt type_parameters type NAME '(' 1808 | | modifiers_opt type NAME '(' ''' 1809 | if len(p) == 5: 1810 | p[0] = {'modifiers': p[1], 'type_parameters': [], 'type': p[2], 'name': p[3]} 1811 | else: 1812 | p[0] = {'modifiers': p[1], 'type_parameters': p[2], 'type': p[3], 'name': p[4]} 1813 | 1814 | def p_annotation_method_header_default_value_opt(self, p): 1815 | '''annotation_method_header_default_value_opt : default_value 1816 | | empty''' 1817 | p[0] = p[1] 1818 | 1819 | def p_default_value(self, p): 1820 | '''default_value : DEFAULT member_value''' 1821 | p[0] = p[2] 1822 | 1823 | def p_member_value(self, p): 1824 | '''member_value : conditional_expression_not_name 1825 | | name 1826 | | annotation 1827 | | member_value_array_initializer''' 1828 | p[0] = p[1] 1829 | 1830 | def p_member_value_array_initializer(self, p): 1831 | '''member_value_array_initializer : '{' member_values ',' '}' 1832 | | '{' member_values '}' ''' 1833 | p[0] = ArrayInitializer(p[2]) 1834 | 1835 | def p_member_value_array_initializer2(self, p): 1836 | '''member_value_array_initializer : '{' ',' '}' 1837 | | '{' '}' ''' 1838 | # ignore 1839 | 1840 | def p_member_values(self, p): 1841 | '''member_values : member_value 1842 | | member_values ',' member_value''' 1843 | if len(p) == 2: 1844 | p[0] = [p[1]] 1845 | else: 1846 | p[0] = p[1] + [p[3]] 1847 | 1848 | def p_annotation(self, p): 1849 | '''annotation : normal_annotation 1850 | | marker_annotation 1851 | | single_member_annotation''' 1852 | p[0] = p[1] 1853 | 1854 | def p_normal_annotation(self, p): 1855 | '''normal_annotation : annotation_name '(' member_value_pairs_opt ')' ''' 1856 | p[0] = Annotation(p[1], members=p[3]) 1857 | 1858 | def p_annotation_name(self, p): 1859 | '''annotation_name : '@' name''' 1860 | p[0] = p[2] 1861 | 1862 | def p_member_value_pairs_opt(self, p): 1863 | '''member_value_pairs_opt : member_value_pairs''' 1864 | p[0] = p[1] 1865 | 1866 | def p_member_value_pairs_opt2(self, p): 1867 | '''member_value_pairs_opt : empty''' 1868 | p[0] = [] 1869 | 1870 | def p_member_value_pairs(self, p): 1871 | '''member_value_pairs : member_value_pair 1872 | | member_value_pairs ',' member_value_pair''' 1873 | if len(p) == 2: 1874 | p[0] = [p[1]] 1875 | else: 1876 | p[0] = p[1] + [p[3]] 1877 | 1878 | def p_member_value_pair(self, p): 1879 | '''member_value_pair : simple_name '=' member_value''' 1880 | p[0] = AnnotationMember(p[1], p[3]) 1881 | 1882 | def p_marker_annotation(self, p): 1883 | '''marker_annotation : annotation_name''' 1884 | p[0] = Annotation(p[1]) 1885 | 1886 | def p_single_member_annotation(self, p): 1887 | '''single_member_annotation : annotation_name '(' single_member_annotation_member_value ')' ''' 1888 | p[0] = Annotation(p[1], single_member=p[3]) 1889 | 1890 | def p_single_member_annotation_member_value(self, p): 1891 | '''single_member_annotation_member_value : member_value''' 1892 | p[0] = p[1] 1893 | 1894 | class CompilationUnitParser(object): 1895 | 1896 | def p_compilation_unit(self, p): 1897 | '''compilation_unit : package_declaration''' 1898 | p[0] = CompilationUnit(package_declaration=p[1]) 1899 | 1900 | def p_compilation_unit2(self, p): 1901 | '''compilation_unit : package_declaration import_declarations''' 1902 | p[0] = CompilationUnit(package_declaration=p[1], import_declarations=p[2]) 1903 | 1904 | def p_compilation_unit3(self, p): 1905 | '''compilation_unit : package_declaration import_declarations type_declarations''' 1906 | p[0] = CompilationUnit(package_declaration=p[1], import_declarations=p[2], type_declarations=p[3]) 1907 | 1908 | def p_compilation_unit4(self, p): 1909 | '''compilation_unit : package_declaration type_declarations''' 1910 | p[0] = CompilationUnit(package_declaration=p[1], type_declarations=p[2]) 1911 | 1912 | def p_compilation_unit5(self, p): 1913 | '''compilation_unit : import_declarations''' 1914 | p[0] = CompilationUnit(import_declarations=p[1]) 1915 | 1916 | def p_compilation_unit6(self, p): 1917 | '''compilation_unit : type_declarations''' 1918 | p[0] = CompilationUnit(type_declarations=p[1]) 1919 | 1920 | def p_compilation_unit7(self, p): 1921 | '''compilation_unit : import_declarations type_declarations''' 1922 | p[0] = CompilationUnit(import_declarations=p[1], type_declarations=p[2]) 1923 | 1924 | def p_compilation_unit8(self, p): 1925 | '''compilation_unit : empty''' 1926 | p[0] = CompilationUnit() 1927 | 1928 | def p_package_declaration(self, p): 1929 | '''package_declaration : package_declaration_name ';' ''' 1930 | if p[1][0]: 1931 | p[0] = PackageDeclaration(p[1][1], modifiers=p[1][0]) 1932 | else: 1933 | p[0] = PackageDeclaration(p[1][1]) 1934 | 1935 | def p_package_declaration_name(self, p): 1936 | '''package_declaration_name : modifiers PACKAGE name 1937 | | PACKAGE name''' 1938 | if len(p) == 3: 1939 | p[0] = (None, p[2]) 1940 | else: 1941 | p[0] = (p[1], p[3]) 1942 | 1943 | def p_import_declarations(self, p): 1944 | '''import_declarations : import_declaration 1945 | | import_declarations import_declaration''' 1946 | if len(p) == 2: 1947 | p[0] = [p[1]] 1948 | else: 1949 | p[0] = p[1] + [p[2]] 1950 | 1951 | def p_import_declaration(self, p): 1952 | '''import_declaration : single_type_import_declaration 1953 | | type_import_on_demand_declaration 1954 | | single_static_import_declaration 1955 | | static_import_on_demand_declaration''' 1956 | p[0] = p[1] 1957 | 1958 | def p_single_type_import_declaration(self, p): 1959 | '''single_type_import_declaration : IMPORT name ';' ''' 1960 | p[0] = ImportDeclaration(p[2]) 1961 | 1962 | def p_type_import_on_demand_declaration(self, p): 1963 | '''type_import_on_demand_declaration : IMPORT name '.' '*' ';' ''' 1964 | p[0] = ImportDeclaration(p[2], on_demand=True) 1965 | 1966 | def p_single_static_import_declaration(self, p): 1967 | '''single_static_import_declaration : IMPORT STATIC name ';' ''' 1968 | p[0] = ImportDeclaration(p[3], static=True) 1969 | 1970 | def p_static_import_on_demand_declaration(self, p): 1971 | '''static_import_on_demand_declaration : IMPORT STATIC name '.' '*' ';' ''' 1972 | p[0] = ImportDeclaration(p[3], static=True, on_demand=True) 1973 | 1974 | def p_type_declarations(self, p): 1975 | '''type_declarations : type_declaration 1976 | | type_declarations type_declaration''' 1977 | if len(p) == 2: 1978 | p[0] = [p[1]] 1979 | else: 1980 | p[0] = p[1] + [p[2]] 1981 | 1982 | class MyParser(ExpressionParser, NameParser, LiteralParser, TypeParser, ClassParser, StatementParser, CompilationUnitParser): 1983 | 1984 | tokens = MyLexer.tokens 1985 | 1986 | def p_goal_compilation_unit(self, p): 1987 | '''goal : PLUSPLUS compilation_unit''' 1988 | p[0] = p[2] 1989 | 1990 | def p_goal_expression(self, p): 1991 | '''goal : MINUSMINUS expression''' 1992 | p[0] = p[2] 1993 | 1994 | def p_goal_statement(self, p): 1995 | '''goal : '*' block_statement''' 1996 | p[0] = p[2] 1997 | 1998 | def p_error(self, p): 1999 | print('error: {}'.format(p)) 2000 | 2001 | def p_empty(self, p): 2002 | '''empty :''' 2003 | 2004 | class Parser(object): 2005 | 2006 | def __init__(self): 2007 | self.lexer = lex.lex(module=MyLexer(), optimize=1) 2008 | self.parser = yacc.yacc(module=MyParser(), start='goal', optimize=1) 2009 | 2010 | def tokenize_string(self, code): 2011 | self.lexer.input(code) 2012 | for token in self.lexer: 2013 | print(token) 2014 | 2015 | def tokenize_file(self, _file): 2016 | if type(_file) == str: 2017 | _file = open(_file) 2018 | content = '' 2019 | for line in _file: 2020 | content += line 2021 | return self.tokenize_string(content) 2022 | 2023 | def parse_expression(self, code, debug=0, lineno=1): 2024 | return self.parse_string(code, debug, lineno, prefix='--') 2025 | 2026 | def parse_statement(self, code, debug=0, lineno=1): 2027 | return self.parse_string(code, debug, lineno, prefix='* ') 2028 | 2029 | def parse_string(self, code, debug=0, lineno=1, prefix='++'): 2030 | self.lexer.lineno = lineno 2031 | return self.parser.parse(prefix + code, lexer=self.lexer, debug=debug) 2032 | 2033 | def parse_file(self, _file, debug=0): 2034 | if type(_file) == str: 2035 | _file = open(_file) 2036 | content = _file.read() 2037 | return self.parse_string(content, debug=debug) 2038 | 2039 | if __name__ == '__main__': 2040 | # for testing 2041 | lexer = lex.lex(module=MyLexer()) 2042 | parser = yacc.yacc(module=MyParser(), write_tables=0, start='type_parameters') 2043 | 2044 | expressions = [ 2045 | '' 2046 | ] 2047 | 2048 | for expr in expressions: 2049 | print('lexing expression {}'.format(expr)) 2050 | lexer.input(expr) 2051 | for token in lexer: 2052 | print(token) 2053 | 2054 | print('parsing expression {}'.format(expr)) 2055 | t = parser.parse(expr, lexer=lexer, debug=1) 2056 | print('result: {}'.format(t)) 2057 | print('--------------------------------') 2058 | 2059 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import setup 2 | 3 | setup( 4 | name='plyj', 5 | version='0.2-dev', 6 | author='Werner Hahn', 7 | author_email='werner_hahn@gmx.com', 8 | packages=['plyj'], 9 | url='http://github.com/musiKk/plyj', 10 | license='COPYING', 11 | description='A Java parser written in Python using PLY. ', 12 | long_description=open('README.md').read(), 13 | classifiers = [ 14 | 'Development Status :: 4 - Beta', 15 | 'Intended Audience :: Developers', 16 | 'Intended Audience :: Education', 17 | 'Intended Audience :: Science/Research', 18 | 'Operating System :: OS Independent', 19 | 'Programming Language :: Python', 20 | 'Topic :: Education', 21 | 'Topic :: Software Development', 22 | 'Topic :: Software Development :: Libraries', 23 | 'Topic :: Software Development :: Libraries :: Python Modules', 24 | 'Topic :: Text Processing' 25 | ], 26 | install_requires=[ 27 | "ply >= 3.4", 28 | ], 29 | test_suite='test' 30 | ) 31 | -------------------------------------------------------------------------------- /test/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/musiKk/plyj/c27d159b2fffe241a2d091e1be3d79790b216732/test/__init__.py -------------------------------------------------------------------------------- /test/compilation_unit.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import plyj.parser as plyj 4 | import plyj.model as model 5 | 6 | class CompilationUnitTest(unittest.TestCase): 7 | 8 | def setUp(self): 9 | self.parser = plyj.Parser() 10 | 11 | def test_class(self): 12 | m = self.parser.parse_string(''' 13 | class Foo {} 14 | ''') 15 | cls = self._assert_declaration(m, 'Foo') 16 | self.assertEqual(len(cls.modifiers), 0) 17 | 18 | def test_class_modifiers(self): 19 | m = self.parser.parse_string(''' 20 | public static final class Foo {} 21 | ''') 22 | cls = self._assert_declaration(m, 'Foo') 23 | self.assertEqual(cls.modifiers, ['public', 'static', 'final']) 24 | 25 | def test_default_package(self): 26 | m = self.parser.parse_string(''' 27 | class Foo {} 28 | ''') 29 | self.assertIsNone(m.package_declaration) 30 | 31 | def test_package(self): 32 | m = self.parser.parse_string(''' 33 | package foo.bar; 34 | ''') 35 | self.assertEqual(m.package_declaration, model.PackageDeclaration(model.Name('foo.bar'))) 36 | 37 | def test_package_annotation(self): 38 | m = self.parser.parse_string(''' 39 | @Annot 40 | package foo; 41 | ''') 42 | self.assertEqual(m.package_declaration, 43 | model.PackageDeclaration(model.Name('foo'), 44 | modifiers=[model.Annotation(model.Name('Annot'))])) 45 | 46 | def test_import(self): 47 | m = self.parser.parse_string(''' 48 | import foo; 49 | import foo.bar; 50 | ''') 51 | self.assertEqual(m.import_declarations, 52 | [model.ImportDeclaration(model.Name('foo')), 53 | model.ImportDeclaration(model.Name('foo.bar'))]) 54 | 55 | def test_static_import(self): 56 | m = self.parser.parse_string(''' 57 | import static foo.bar; 58 | ''') 59 | self.assertEqual(m.import_declarations, 60 | [model.ImportDeclaration(model.Name('foo.bar'), static=True)]) 61 | 62 | def test_wildcard_import(self): 63 | m = self.parser.parse_string(''' 64 | import foo.bar.*; 65 | ''') 66 | self.assertEqual(m.import_declarations, 67 | [model.ImportDeclaration(model.Name('foo.bar'), on_demand=True)]) 68 | 69 | def test_static_wildcard_import(self): 70 | m = self.parser.parse_string(''' 71 | import static foo.bar.*; 72 | ''') 73 | self.assertEqual(m.import_declarations, 74 | [model.ImportDeclaration(model.Name('foo.bar'), static=True, on_demand=True)]) 75 | 76 | def test_annotations(self): 77 | # bug #13 78 | m = self.parser.parse_string(''' 79 | @Annot(key = 1) 80 | class Foo {} 81 | ''') 82 | t = self._assert_declaration(m, 'Foo') 83 | 84 | self.assertEqual(t.modifiers, [model.Annotation( 85 | name=model.Name('Annot'), 86 | members=[model.AnnotationMember(name=model.Name('key'), 87 | value=model.Literal('1'))])]) 88 | 89 | def test_line_comment(self): 90 | m = self.parser.parse_string(r''' 91 | class Foo {} 92 | // 93 | //\ 94 | // line comment at last line'''); 95 | self._assert_declaration(m, 'Foo') 96 | 97 | def test_visit_empty_declaration(self): 98 | m = self.parser.parse_string(r''' 99 | interface IFoo { 100 | ; 101 | } 102 | class Foo { 103 | ; 104 | };''') 105 | v = model.Visitor() 106 | m.accept(v) 107 | 108 | def test_visit_abstract_method(self): 109 | m = self.parser.parse_string(r''' 110 | abstract class Foo { 111 | abstract void foo(); 112 | } 113 | ''') 114 | v = model.Visitor() 115 | m.accept(v) 116 | 117 | def test_visit_right_hand_this(self): 118 | m = self.parser.parse_string(r''' 119 | class Foo { 120 | static Foo instance; 121 | Foo() { 122 | instance = this; 123 | } 124 | } 125 | ''') 126 | v = model.Visitor() 127 | m.accept(v) 128 | 129 | def _assert_declaration(self, compilation_unit, name, index=0, type=model.ClassDeclaration): 130 | self.assertIsInstance(compilation_unit, model.CompilationUnit) 131 | self.assertTrue(len(compilation_unit.type_declarations) >= index + 1) 132 | 133 | decl = compilation_unit.type_declarations[index] 134 | self.assertIsInstance(decl, type) 135 | 136 | self.assertEqual(decl.name, name) 137 | 138 | return decl 139 | -------------------------------------------------------------------------------- /test/expressions.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import plyj.parser as plyj 4 | import plyj.model as model 5 | 6 | one = model.Literal('1') 7 | two = model.Literal('2') 8 | three = model.Literal('3') 9 | a = model.Name('a') 10 | b = model.Name('b') 11 | c = model.Name('c') 12 | d = model.Name('d') 13 | e = model.Name('e') 14 | 15 | def bin(operator, operand1, operand2): 16 | return model.BinaryExpression(operator, operand1, operand2) 17 | 18 | def u(operator, operand): 19 | return model.Unary(operator, operand) 20 | 21 | expression_tests = [ 22 | # simple test for each operator 23 | ('1+2', bin('+', one, two)), 24 | (' 1 + 2 ', bin('+', one, two)), 25 | ('1-2', bin('-', one, two)), 26 | ('1*2', bin('*', one, two)), 27 | ('1/2', bin('/', one, two)), 28 | ('1%2', bin('%', one, two)), 29 | ('1^2', bin('^', one, two)), 30 | ('1&2', bin('&', one, two)), 31 | ('1&&2', bin('&&', one, two)), 32 | ('1|2', bin('|', one, two)), 33 | ('1||2', bin('||', one, two)), 34 | ('1==2', bin('==', one, two)), 35 | ('1!=2', bin('!=', one, two)), 36 | ('1<2', bin('<', one, two)), 37 | ('1<=2', bin('<=', one, two)), 38 | ('1>2', bin('>', one, two)), 39 | ('1>=2', bin('>=', one, two)), 40 | ('1<<2', bin('<<', one, two)), 41 | ('1>>2', bin('>>', one, two)), 42 | ('1>>>2', bin('>>>', one, two)), 43 | # left associativity 44 | ('1+2+3', bin('+', bin('+', one, two), three)), 45 | # precedence 46 | ('1+2*3', bin('+', one, bin('*', two, three))), 47 | # parenthesized expressions 48 | ('(1+2)*3', bin('*', bin('+', one, two), three)), 49 | # conditionals 50 | ('a ? b : c', model.Conditional(a, b, c)), 51 | ('a ? b ? c : d : e', model.Conditional(a, model.Conditional(b, c, d), e)), 52 | ('a ? b : c ? d : e', model.Conditional(a, b, model.Conditional(c, d, e))), 53 | # unary expressions 54 | ('+a', u('+', a)), 55 | ('-a', u('-', a)), 56 | ('!a', u('!', a)), 57 | ('!!a', u('!', u('!', a))), 58 | ('~a', u('~', a)), 59 | ('++a', u('++x', a)), 60 | ('--a', u('--x', a)), 61 | ('a++', u('x++', a)), 62 | ('a--', u('x--', a)), 63 | # assignment expressions 64 | ('a = 1', model.Assignment('=', a, one)), 65 | ('a += 1', model.Assignment('+=', a, one)), 66 | ('a -= 1', model.Assignment('-=', a, one)), 67 | ('a *= 1', model.Assignment('*=', a, one)), 68 | ('a /= 1', model.Assignment('/=', a, one)), 69 | ('a %= 1', model.Assignment('%=', a, one)), 70 | ('a ^= 1', model.Assignment('^=', a, one)), 71 | ('a &= 1', model.Assignment('&=', a, one)), 72 | ('a |= 1', model.Assignment('|=', a, one)), 73 | ('a <<= 1', model.Assignment('<<=', a, one)), 74 | ('a >>= 1', model.Assignment('>>=', a, one)), 75 | ('a >>>= 1', model.Assignment('>>>=', a, one)), 76 | # casts 77 | ('(Foo) a', model.Cast(model.Type(model.Name('Foo')), a)), 78 | ('(int[]) a', model.Cast(model.Type('int', dimensions=1), a)), 79 | ('(Foo[]) a', model.Cast(model.Type(model.Name('Foo'), dimensions=1), a)), 80 | ('(Foo) a', model.Cast(model.Type(model.Name('Foo'), type_arguments=[model.Type(model.Name('T'))]), a)), 81 | ('(Foo.Bar) a', model.Cast(model.Type(model.Name('Bar'), 82 | enclosed_in=model.Type(model.Name('Foo'), type_arguments=[model.Type(model.Name('T'))])), a)), 83 | # method invocation 84 | ('foo.bar()', model.MethodInvocation(name='bar', target=model.Name(value='foo'))), 85 | ('foo.class.getName()', model.MethodInvocation(target=model.ClassLiteral(model.Type(model.Name('foo'))), name='getName')), 86 | 87 | ('foo.Class[].class', model.ClassLiteral(model.Type(model.Name('foo.Class'), dimensions=1))) 88 | ] 89 | 90 | class ExpressionTest(unittest.TestCase): 91 | 92 | def setUp(self): 93 | self.parser = plyj.Parser() 94 | 95 | def test_expressions(self): 96 | for expr, result in expression_tests: 97 | t = self.parser.parse_expression(expr) 98 | self.assertEqual(t, result, 'for {} got: {}, expected: {}'.format(expr, t, result)) 99 | 100 | if __name__ == '__main__': 101 | unittest.main() 102 | -------------------------------------------------------------------------------- /test/statements.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import plyj.parser as plyj 4 | import plyj.model as model 5 | 6 | foo = model.Name('foo') 7 | bar = model.Name('bar') 8 | i = model.Name('i') 9 | j = model.Name('j') 10 | zero = model.Literal('0') 11 | one = model.Literal('1') 12 | two = model.Literal('2') 13 | three = model.Literal('3') 14 | ten = model.Literal('10') 15 | 16 | class StatementTest(unittest.TestCase): 17 | 18 | def setUp(self): 19 | self.parser = plyj.Parser() 20 | 21 | def test_while(self): 22 | self.assert_stmt('while(foo) return;', model.While(foo, body=model.Return())) 23 | self.assert_stmt('while(foo) { return; }', model.While(foo, body=model.Block([model.Return()]))) 24 | 25 | self.assert_stmt('do return; while(foo);', model.DoWhile(foo, body=model.Return())) 26 | self.assert_stmt('do { return; } while(foo);', model.DoWhile(foo, body=model.Block([model.Return()]))) 27 | 28 | def test_for(self): 29 | initializer = model.VariableDeclaration('int', [model.VariableDeclarator(model.Variable('i'), initializer=zero)]) 30 | predicate = model.BinaryExpression('<', i, ten) 31 | update = model.Unary('x++', i) 32 | 33 | self.assert_stmt('for(;;);', model.For(None, None, None, body=model.Empty())) 34 | self.assert_stmt('for(;;) return;', model.For(None, None, None, body=model.Return())) 35 | self.assert_stmt('for(;;) { return; }', model.For(None, None, None, body=model.Block([model.Return()]))) 36 | self.assert_stmt('for(int i=0;;) return;', model.For(initializer, None, None, body=model.Return())) 37 | self.assert_stmt('for(;i<10;) return;', model.For(None, predicate, None, body=model.Return())) 38 | self.assert_stmt('for(;;i++) return;', model.For(None, None, [update], body=model.Return())) 39 | self.assert_stmt('for(int i=0; i<10; i++) return;', model.For(initializer, predicate, [update], body=model.Return())) 40 | 41 | initializer2 = [model.Assignment('=', i, zero), model.Assignment('=', j, ten)] 42 | self.assert_stmt('for(i=0, j=10;;) return;', model.For(initializer2, None, None, body=model.Return())) 43 | 44 | update2 = model.Unary('x++', j) 45 | self.assert_stmt('for(;;i++, j++) return;', model.For(None, None, [update, update2], body=model.Return())) 46 | 47 | self.assert_stmt('for(int i : foo) return;', model.ForEach('int', model.Variable('i'), foo, body=model.Return())) 48 | 49 | def test_assert(self): 50 | self.assert_stmt('assert foo;', model.Assert(foo)) 51 | self.assert_stmt('assert foo : "bar";', model.Assert(foo, message=model.Literal('"bar"'))) 52 | 53 | def test_switch(self): 54 | default = model.SwitchCase(['default'], body=[model.Return()]) 55 | 56 | self.assert_stmt('switch(foo) {}', model.Switch(foo, [])) 57 | self.assert_stmt('switch(foo) { default: return; }', model.Switch(foo, [default])) 58 | 59 | case1 = model.SwitchCase([one], [model.Return(one)]) 60 | self.assert_stmt('switch(foo) { case 1: return 1; }', model.Switch(foo, [case1])) 61 | self.assert_stmt('switch(foo) { case 1: return 1; default: return; }', model.Switch(foo, [case1, default])) 62 | 63 | case12 = model.SwitchCase([one, two], [model.Return(three)]) 64 | self.assert_stmt('switch(foo) { case 1: case 2: return 3; }', model.Switch(foo, [case12])) 65 | self.assert_stmt('switch(foo) { case 1: case 2: return 3; default: return; }', model.Switch(foo, [case12, default])) 66 | 67 | def test_control_flow(self): 68 | self.assert_stmt('break;', model.Break()) 69 | self.assert_stmt('break label;', model.Break('label')) 70 | 71 | self.assert_stmt('continue;', model.Continue()) 72 | self.assert_stmt('continue label;', model.Continue('label')) 73 | 74 | self.assert_stmt('return;', model.Return()) 75 | self.assert_stmt('return 1;', model.Return(one)) 76 | 77 | self.assert_stmt('throw foo;', model.Throw(foo)) 78 | 79 | def test_synchronized(self): 80 | self.assert_stmt('synchronized (foo) { return; }', model.Synchronized(foo, body=model.Block([model.Return()]))) 81 | 82 | def test_try(self): 83 | r1 = model.Return(one) 84 | r2 = model.Return(two) 85 | r3 = model.Return(three) 86 | c1 = model.Catch(model.Variable('e'), types=[model.Type(model.Name('Exception'))], block=model.Block([r2])) 87 | self.assert_stmt('try { return 1; } catch (Exception e) { return 2; }', model.Try(model.Block([r1]), catches=[c1])) 88 | self.assert_stmt('try { return 1; } catch (Exception e) { return 2; } finally { return 3; }', 89 | model.Try(model.Block([r1]), catches=[c1], _finally=model.Block([r3]))) 90 | self.assert_stmt('try { return 1; } finally { return 2; }', model.Try(model.Block([r1]), _finally=model.Block([r2]))) 91 | 92 | c2 = model.Catch(model.Variable('e'), types=[model.Type(model.Name('Exception1')), model.Type(model.Name('Exception2'))], block=model.Block([r3])) 93 | self.assert_stmt('try { return 1; } catch (Exception1 | Exception2 e) { return 3; }', 94 | model.Try(model.Block([r1]), catches=[c2])) 95 | self.assert_stmt('try { return 1; } catch (Exception e) { return 2; } catch (Exception1 | Exception2 e) { return 3; }', 96 | model.Try(model.Block([r1]), catches=[c1, c2])) 97 | self.assert_stmt('try { return 1; } catch (Exception e) { return 2; } catch (Exception1 | Exception2 e) { return 3; } finally { return 3; }', 98 | model.Try(model.Block([r1]), catches=[c1, c2], _finally=model.Block([r3]))) 99 | 100 | res1 = model.Resource(model.Variable('r'), type=model.Type(model.Name('Resource')), initializer=model.Name('foo')) 101 | res2 = model.Resource(model.Variable('r2'), type=model.Type(model.Name('Resource2')), initializer=model.Name('bar')) 102 | self.assert_stmt('try(Resource r = foo) { return 1; }', model.Try(model.Block([r1]), resources=[res1])) 103 | self.assert_stmt('try(Resource r = foo;) { return 1; }', model.Try(model.Block([r1]), resources=[res1])) 104 | self.assert_stmt('try(Resource r = foo; Resource2 r2 = bar) { return 1; }', 105 | model.Try(model.Block([r1]), resources=[res1, res2])) 106 | self.assert_stmt('try(Resource r = foo; Resource2 r2 = bar;) { return 1; }', 107 | model.Try(model.Block([r1]), resources=[res1, res2])) 108 | self.assert_stmt('try(Resource r = foo) { return 1; } catch (Exception e) { return 2; }', 109 | model.Try(model.Block([r1]), resources=[res1], catches=[c1])) 110 | self.assert_stmt('try(Resource r = foo) { return 1; } catch (Exception1 | Exception2 e) { return 3;}', 111 | model.Try(model.Block([r1]), resources=[res1], catches=[c2])) 112 | self.assert_stmt('try(Resource r = foo) { return 1; } catch (Exception e) { return 2; } catch (Exception1 | Exception2 e) { return 3; }', 113 | model.Try(model.Block([r1]), resources=[res1], catches=[c1, c2])) 114 | self.assert_stmt('try(Resource r = foo) { return 1; } finally { return 3; }', 115 | model.Try(model.Block([r1]), resources=[res1], _finally=model.Block([r3]))) 116 | self.assert_stmt('try(Resource r = foo) { return 1; } catch (Exception e) { return 2; } finally { return 3; }', 117 | model.Try(model.Block([r1]), resources=[res1], catches=[c1], _finally=model.Block([r3]))) 118 | self.assert_stmt('try(Resource r = foo) { return 1; } catch (Exception e) { return 2; } catch (Exception1 | Exception2 e) { return 3; } finally { return 3; }', 119 | model.Try(model.Block([r1]), resources=[res1], catches=[c1, c2], _finally=model.Block([r3]))) 120 | 121 | def test_constructor_invocation(self): 122 | footype = model.Type(model.Name('Foo')) 123 | bartype = model.Type(model.Name('Bar')) 124 | for call in ['super', 'this']: 125 | self.assert_stmt('{}();'.format(call), model.ConstructorInvocation(call)) 126 | self.assert_stmt('{}(1);'.format(call), model.ConstructorInvocation(call, arguments=[one])) 127 | self.assert_stmt('{}(1, foo, "bar");'.format(call), 128 | model.ConstructorInvocation(call, arguments=[one, foo, model.Literal('"bar"')])) 129 | self.assert_stmt(' {}();'.format(call), 130 | model.ConstructorInvocation(call, type_arguments=[footype])) 131 | self.assert_stmt('Foo.{}();'.format(call), 132 | model.ConstructorInvocation(call, target=model.Name('Foo'))) 133 | self.assert_stmt('Foo. {}();'.format(call), 134 | model.ConstructorInvocation(call, type_arguments=[bartype], target=model.Name('Foo'))) 135 | 136 | def test_if(self): 137 | self.assert_stmt('if(foo) return;', model.IfThenElse(foo, if_true=model.Return())) 138 | self.assert_stmt('if(foo) { return; }', model.IfThenElse(foo, if_true=model.Block([model.Return()]))) 139 | 140 | r1 = model.Return(result=one) 141 | r2 = model.Return(result=two) 142 | self.assert_stmt('if(foo) return 1; else return 2;', model.IfThenElse(foo, if_true=r1, if_false=r2)) 143 | self.assert_stmt('if(foo) {return 1;} else return 2;', 144 | model.IfThenElse(foo, if_true=model.Block([r1]), if_false=r2)) 145 | self.assert_stmt('if(foo) return 1; else {return 2;}', 146 | model.IfThenElse(foo, if_true=r1, if_false=model.Block([r2]))) 147 | self.assert_stmt('if(foo) {return 1;} else {return 2;}', 148 | model.IfThenElse(foo, if_true=model.Block([r1]), if_false=model.Block([r2]))) 149 | 150 | # test proper nesting, every parser writer's favorite 151 | self.assert_stmt('if(foo) if(bar) return 1;', model.IfThenElse(foo, if_true=model.IfThenElse(bar, if_true=r1))) 152 | self.assert_stmt('if(foo) if(bar) return 1; else return 2;', 153 | model.IfThenElse(foo, if_true=model.IfThenElse(bar, if_true=r1, if_false=r2))) 154 | self.assert_stmt('if(foo) return 1; else if(bar) return 2;', 155 | model.IfThenElse(foo, if_true=r1, if_false=model.IfThenElse(bar, if_true=r2))) 156 | 157 | def test_variable_declaration(self): 158 | var_i = model.Variable('i') 159 | var_i_decltor = model.VariableDeclarator(var_i) 160 | var_j = model.Variable('j') 161 | var_j_decltor = model.VariableDeclarator(var_j) 162 | 163 | self.assert_stmt('int i;', model.VariableDeclaration('int', [var_i_decltor])) 164 | self.assert_stmt('int i, j;', model.VariableDeclaration('int', [var_i_decltor, var_j_decltor])) 165 | 166 | var_i_decltor.initializer = one 167 | self.assert_stmt('int i = 1;', model.VariableDeclaration('int', [var_i_decltor])) 168 | self.assert_stmt('int i = 1, j;', model.VariableDeclaration('int', [var_i_decltor, var_j_decltor])) 169 | 170 | var_j_decltor.initializer = i 171 | self.assert_stmt('int i = 1, j = i;', model.VariableDeclaration('int', [var_i_decltor, var_j_decltor])) 172 | 173 | int_ar = model.Type('int', dimensions=1) 174 | var_i_decltor.initializer = None 175 | self.assert_stmt('int[] i;', model.VariableDeclaration(int_ar, [var_i_decltor])) 176 | 177 | foo_ar = model.Type(name=model.Name('Foo'), type_arguments=[model.Type(name=model.Name(value='T'))], dimensions=1) 178 | self.assert_stmt('Foo[] i;', model.VariableDeclaration(foo_ar, [var_i_decltor])) 179 | 180 | def test_array(self): 181 | var_i = model.Variable('i') 182 | var_i_decltor = model.VariableDeclarator(var_i) 183 | var_j = model.Variable('j') 184 | var_j_decltor = model.VariableDeclarator(var_j) 185 | 186 | int_ar = model.Type('int', dimensions=1) 187 | 188 | arr_init = model.ArrayInitializer([one, three]) 189 | var_i_decltor.initializer = arr_init 190 | self.assert_stmt('int[] i = {1, 3};', model.VariableDeclaration(int_ar, [var_i_decltor])) 191 | 192 | arr_creation = model.ArrayCreation('int', dimensions=[None], initializer=arr_init) 193 | var_i_decltor.initializer = arr_creation 194 | self.assert_stmt('int[] i = new int[] {1, 3};', model.VariableDeclaration(int_ar, [var_i_decltor])) 195 | 196 | arr_creation.dimensions = [two] 197 | self.assert_stmt('int[] i = new int[2] {1, 3};', model.VariableDeclaration(int_ar, [var_i_decltor])) 198 | 199 | def test_empty(self): 200 | self.assert_stmt(';', model.Empty()) 201 | 202 | def assert_stmt(self, stmt, result): 203 | s = self.parser.parse_statement(stmt) 204 | # print 'comparing expected - actual:\n{}\n{}'.format(result, s) 205 | self.assertEqual(s, result, 'for {} got {}, expected {}'.format(stmt, s, result)) 206 | -------------------------------------------------------------------------------- /test/type_declaration.py: -------------------------------------------------------------------------------- 1 | import unittest 2 | 3 | import plyj.parser as plyj 4 | import plyj.model as model 5 | from plyj.model import * 6 | 7 | class TypeDeclarationTest(unittest.TestCase): 8 | 9 | def setUp(self): 10 | self.parser = plyj.Parser() 11 | 12 | def test_class_method(self): 13 | m = self.parser.parse_string(''' 14 | class Foo { 15 | void foo() {} 16 | } 17 | ''') 18 | cls = self._assert_declaration(m, 'Foo') 19 | self.assertEquals(cls.body, [MethodDeclaration('foo', body=[])]) 20 | 21 | def test_interface_method(self): 22 | m = self.parser.parse_string(''' 23 | interface Foo { 24 | void foo(); 25 | } 26 | ''') 27 | cls = self._assert_declaration(m, 'Foo', type=model.InterfaceDeclaration) 28 | self.assertEquals(cls.body, [MethodDeclaration('foo', abstract=True)]) 29 | 30 | def test_class_abstract_method(self): 31 | m = self.parser.parse_string(''' 32 | abstract class Foo { 33 | abstract void foo(); 34 | } 35 | ''') 36 | cls = self._assert_declaration(m, 'Foo') 37 | self.assertEquals(cls.body, [MethodDeclaration('foo', modifiers=['abstract'], abstract=True)]) 38 | 39 | def _assert_declaration(self, compilation_unit, name, index=0, type=model.ClassDeclaration): 40 | self.assertIsInstance(compilation_unit, model.CompilationUnit) 41 | self.assertTrue(len(compilation_unit.type_declarations) >= index + 1) 42 | 43 | decl = compilation_unit.type_declarations[index] 44 | self.assertIsInstance(decl, type) 45 | 46 | self.assertEqual(decl.name, name) 47 | 48 | return decl 49 | --------------------------------------------------------------------------------