/* * Copyright (C) 2010 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in * all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN * THE SOFTWARE. */ package lombok.ast.grammar; import lombok.ast.Node; import org.parboiled.BaseParser; import org.parboiled.Rule; import org.parboiled.annotations.SuppressSubnodes; public class StructuresParser extends BaseParser<Node> { final ParserGroup group; final StructuresActions actions; public StructuresParser(ParserGroup group) { this.actions = new StructuresActions(group.getSource()); this.group = group; } public Rule typeBody() { return Sequence( Ch('{'), group.basics.optWS(), typeBodyDeclarations(), set(), Ch('}'), group.basics.optWS(), set(actions.posify(value()))); } public Rule typeBodyMember() { return FirstOf( anyTypeDeclaration(), fieldDeclaration(), methodDeclaration(), constructorDeclaration(), staticInitializer(), instanceInitializer(), emptyDeclaration()); } Rule typeBodyDeclarations() { return Sequence( ZeroOrMore(typeBodyMember().label("member")).label("members"), set(actions.createNormalTypeBody(values("members/member")))); } Rule emptyDeclaration() { return Sequence(Ch(';'), group.basics.optWS(), set(actions.createEmptyDeclaration())); } public Rule methodArguments() { return Sequence( Ch('('), group.basics.optWS(), Optional(Sequence( group.expressions.anyExpression(), set(), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), group.expressions.anyExpression(), set())))), Ch(')'), group.basics.optWS(), set(actions.createMethodArguments(value("Optional/Sequence"), values("Optional/Sequence/ZeroOrMore/Sequence")))); } public Rule anyTypeDeclaration() { return Sequence( TestNot(FirstOf(Eoi(), Ch('}'))), FirstOf( classOrInterfaceDeclaration(), enumDeclaration(), annotationDeclaration(), emptyDeclaration())); } public Rule classOrInterfaceDeclaration() { return Sequence( typeDeclarationModifiers().label("modifiers"), FirstOf(String("class"), String("interface")).label("kind"), group.basics.testLexBreak(), group.basics.optWS(), group.basics.identifier().label("typeName"), group.types.typeVariables().label("typeParameters"), ZeroOrMore(FirstOf( extendsClause(), implementsClause()).label("addon")).label("addons"), typeBody().label("body"), set(actions.createTypeDeclaration(text("kind"), value("modifiers"), value("typeName"), value("typeParameters"), value("body"), values("addons/addon")))); } Rule extendsClause() { return Sequence( Sequence(String("extends"), group.basics.testLexBreak(), group.basics.optWS()), group.types.type().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), group.types.type()).label("tail")), set(actions.createExtendsClause(value("head"), values("ZeroOrMore/tail")))); } Rule implementsClause() { return Sequence( Sequence(String("implements"), group.basics.testLexBreak(), group.basics.optWS()), group.types.type().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), group.types.type()).label("tail")), set(actions.createImplementsClause(value("head"), values("ZeroOrMore/tail")))); } public Rule enumDeclaration() { return Sequence( typeDeclarationModifiers().label("modifiers"), String("enum"), group.basics.testLexBreak(), group.basics.optWS(), group.basics.identifier().label("typeName"), ZeroOrMore(FirstOf( extendsClause(), implementsClause()).label("addon")).label("addons"), enumBody().label("body"), set(actions.createEnumDeclaration(value("modifiers"), value("typeName"), value("body"), values("addons/addon")))); } public Rule annotationDeclaration() { return Sequence( typeDeclarationModifiers().label("modifiers"), Ch('@'), group.basics.optWS(), String("interface"), group.basics.testLexBreak(), group.basics.optWS(), group.basics.identifier().label("name"), Ch('{').label("typeOpen"), group.basics.optWS(), ZeroOrMore(annotationElementDeclaration().label("member")).label("members"), Ch('}').label("typeClose"), group.basics.optWS(), set(actions.createAnnotationDeclaration(value("modifiers"), value("name"), values("members/member"), node("typeOpen"), node("typeClose")))); } Rule annotationElementDeclaration() { return FirstOf( annotationMethodDeclaration(), fieldDeclaration(), classOrInterfaceDeclaration(), enumDeclaration(), annotationDeclaration(), Sequence(Ch(';'), group.basics.optWS()) ); } Rule enumBody() { return Sequence( Ch('{'), group.basics.optWS(), Optional(Sequence( enumConstant().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), enumConstant()).label("tail")), Optional(Sequence(Ch(','), group.basics.optWS())))).label("constants"), Optional(Sequence( Ch(';'), group.basics.optWS(), typeBodyDeclarations())).label("typeBodyDeclarations"), Ch('}'), group.basics.optWS(), set(actions.createEnumBody(value("constants/Sequence/head"), values("constants/Sequence/ZeroOrMore/tail"), value("typeBodyDeclarations")))); } Rule enumConstant() { return Sequence( ZeroOrMore(annotation().label("annotation")).label("annotations"), group.basics.identifier().label("name"), Optional(methodArguments()).label("arguments"), Optional(typeBody()).label("body"), set(actions.createEnumConstant(values("annotations/annotation"), value("name"), value("arguments"), value("body")))); } public Rule constructorDeclaration() { return Sequence( methodDeclarationModifiers().label("modifiers"), group.types.typeVariables().label("typeParameters"), group.basics.identifier().label("typeName"), methodParameters().label("params"), Optional(Sequence( Sequence(String("throws"), group.basics.testLexBreak(), group.basics.optWS()), group.types.type().label("throwsHead"), ZeroOrMore(Sequence(Ch(','), group.basics.optWS(), group.types.type()).label("throwsTail")) )).label("throwsClause"), FirstOf( Sequence(Ch(';'), group.basics.optWS()), group.statements.blockStatement()).label("body"), set(actions.createConstructorDeclaration(value("modifiers"), value("typeParameters"), value("typeName"), value("params"), value("throwsClause/Sequence/throwsHead"), values("throwsClause/Sequence/ZeroOrMore/throwsTail"), value("body")))); } public Rule annotationMethodDeclaration() { return Sequence( methodDeclarationModifiers().label("modifiers"), group.types.type().label("resultType"), group.basics.identifier().label("methodName"), Ch('('), group.basics.optWS(), Ch(')'), group.basics.optWS(), ZeroOrMore(Sequence(Ch('['), group.basics.optWS(), Ch(']'), group.basics.optWS()).label("dim")).label("dims"), Optional(Sequence( Sequence(String("default"), group.basics.testLexBreak(), group.basics.optWS()), annotationElementValue())).label("defaultValue"), Ch(';'), group.basics.optWS(), set(actions.createAnnotationMethodDeclaration(value("modifiers"), value("resultType"), value("methodName"), nodes("dims/dim"), value("defaultValue")))); } public Rule methodDeclaration() { return Sequence( methodDeclarationModifiers().label("modifiers"), group.types.typeVariables().label("typeParameters"), group.types.type().label("resultType"), group.basics.identifier().label("methodName"), methodParameters().label("params"), ZeroOrMore(Sequence(Ch('['), group.basics.optWS(), Ch(']'), group.basics.optWS()).label("dim")).label("dims"), Optional(Sequence( Sequence(String("throws"), group.basics.testLexBreak(), group.basics.optWS()), group.types.type().label("throwsHead"), ZeroOrMore(Sequence(Ch(','), group.basics.optWS(), group.types.type()).label("throwsTail")) )).label("throwsClause"), FirstOf( Sequence(Ch(';'), group.basics.optWS()), group.statements.blockStatement()).label("body"), set(actions.createMethodDeclaration(value("modifiers"), value("typeParameters"), value("resultType"), value("methodName"), value("params"), nodes("dims/dim"), value("throwsClause/Sequence/throwsHead"), values("throwsClause/Sequence/ZeroOrMore/throwsTail"), value("body")))); } Rule methodParameters() { return Sequence( Ch('('), group.basics.optWS(), Optional(Sequence( methodParameter().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), methodParameter().label("tail"))))), Ch(')'), group.basics.optWS(), set(actions.createMethodParameters(value("Optional/Sequence/head"), values("Optional/Sequence/ZeroOrMore/Sequence/tail")))); } Rule methodParameter() { return Sequence( variableDefinitionModifiers().label("modifiers"), group.types.type().label("type"), Optional(Sequence(String("..."), group.basics.optWS())).label("varargs"), group.basics.identifier().label("name"), ZeroOrMore(Sequence(Ch('[').label("open"), group.basics.optWS(), Ch(']').label("closed"), group.basics.optWS()).label("dim")).label("dims"), set(actions.createMethodParameter(value("modifiers"), value("type"), text("varargs"), value("name"), nodes("dims/dim/open"), nodes("dims/dim/closed")))); } public Rule instanceInitializer() { return Sequence( group.statements.blockStatement().label("initializer"), set(actions.createInstanceInitializer(value("initializer")))); } public Rule staticInitializer() { return Sequence( String("static"), group.basics.testLexBreak(), group.basics.optWS(), group.statements.blockStatement().label("initializer"), set(actions.createStaticInitializer(value("initializer")))); } public Rule fieldDeclaration() { return Sequence( fieldDeclarationModifiers().label("modifiers"), variableDefinition(), set(), set(actions.posify(value())), Ch(';'), group.basics.optWS(), set(actions.createFieldDeclaration(value(), value("modifiers")))); } /** * Add your own modifiers! */ Rule variableDefinition() { return Sequence( group.types.type().label("type"), variableDefinitionPart().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), variableDefinitionPart()).label("tail")), set(actions.createVariableDefinition(value("type"), value("head"), values("ZeroOrMore/tail")))); } Rule variableDefinitionPartNoAssign() { return Sequence( group.basics.identifier().label("varName"), ZeroOrMore(Sequence(Ch('['), group.basics.optWS(), Ch(']'), group.basics.optWS()).label("dim")).label("dims"), set(actions.createVariableDefinitionPart(value("varName"), texts("dims/dim"), null))); } Rule variableDefinitionPart() { return Sequence( group.basics.identifier().label("varName"), ZeroOrMore(Sequence(Ch('['), group.basics.optWS(), Ch(']'), group.basics.optWS()).label("dim")).label("dims"), Optional(Sequence( Ch('='), group.basics.optWS(), FirstOf( group.expressions.arrayInitializer(), group.expressions.anyExpression()))).label("initializer"), set(actions.createVariableDefinitionPart(value("varName"), texts("dims/dim"), value("initializer")))); } public Rule annotation() { return Sequence( Ch('@'), group.basics.optWS(), group.types.plainReferenceType().label("annotationType"), Optional(Sequence( Ch('('), group.basics.optWS(), Optional(FirstOf( annotationElements(), Sequence(annotationElementValue(), set(actions.createAnnotationFromElement(lastValue()))))), Ch(')'), group.basics.optWS())).label("content"), set(actions.createAnnotation(value("annotationType"), value("content")))); } Rule annotationElements() { return Sequence( annotationElement().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), annotationElement()).label("tail")), set(actions.createAnnotationFromElements(value("head"), values("ZeroOrMore/tail")))); } Rule annotationElement() { return Sequence( group.basics.identifier().label("name"), Ch('='), group.basics.optWS(), annotationElementValue().label("value"), set(actions.createAnnotationElement(value("name"), value("value")))); } Rule annotationElementValue() { return FirstOf( annotation(), Sequence( Ch('{'), group.basics.optWS(), Optional(Sequence( annotationElementValue().label("head"), ZeroOrMore(Sequence( Ch(','), group.basics.optWS(), annotationElementValue()).label("tail")), Optional(Sequence(Ch(','), group.basics.optWS())))), Ch('}'), group.basics.optWS(), set(actions.createAnnotationElementValueArrayInitializer(value("Optional/Sequence/head"), values("Optional/Sequence/ZeroOrMore/tail")))), group.expressions.inlineIfExpressionChaining()); } @SuppressSubnodes Rule anyKeyword() { return FirstOf("final", "strictfp", "abstract", "transient", "volatile", "public", "protected", "private", "synchronized", "static", "native"); } public Rule keywordModifier() { return Sequence( anyKeyword().label("keyword"), group.basics.testLexBreak(), set(actions.createKeywordModifier(text("keyword"))), group.basics.optWS()); } public Rule typeDeclarationModifiers() { return Sequence( TestNot(Ch('}')), ZeroOrMore(anyModifier().label("modifier")), set(actions.createModifiers(values("ZeroOrMore/modifier")))); } public Rule methodDeclarationModifiers() { return Sequence( TestNot(Ch('}')), ZeroOrMore(anyModifier().label("modifier")), set(actions.createModifiers(values("ZeroOrMore/modifier")))); } public Rule fieldDeclarationModifiers() { return Sequence( TestNot(Ch('}')), ZeroOrMore(anyModifier().label("modifier")), set(actions.createModifiers(values("ZeroOrMore/modifier")))); } public Rule variableDefinitionModifiers() { return Sequence( TestNot(Ch('}')), ZeroOrMore(anyModifier().label("modifier")), set(actions.createModifiers(values("ZeroOrMore/modifier")))); } public Rule anyModifier() { return FirstOf(annotation(), keywordModifier()); } public Rule packageDeclaration() { return Sequence( Sequence( ZeroOrMore(annotation().label("annotation")).label("annotations"), String("package"), group.basics.testLexBreak(), group.basics.optWS()), group.basics.identifier().label("head"), ZeroOrMore(group.basics.dotIdentifier().label("tail")), Ch(';'), group.basics.optWS(), set(actions.createPackageDeclaration(values("Sequence/annotations/annotation"), value("head"), values("ZeroOrMore/tail")))); } public Rule importDeclaration() { return Sequence( Sequence(String("import"), group.basics.testLexBreak(), group.basics.optWS()), Optional(Sequence(String("static"), group.basics.testLexBreak(), group.basics.optWS())).label("static"), group.basics.identifier().label("head"), ZeroOrMore(group.basics.dotIdentifier().label("tail")), Optional(Sequence( Ch('.'), group.basics.optWS(), Ch('*'), group.basics.optWS())).label("dotStar"), Ch(';'), group.basics.optWS(), set(actions.createImportDeclaration(text("static"), value("head"), values("ZeroOrMore/tail"), text("dotStar")))); } public Rule compilationUnitEoi() { return Sequence(compilationUnit(), Eoi()); } public Rule compilationUnit() { return Sequence( group.basics.optWS(), Optional(packageDeclaration()).label("package"), ZeroOrMore(importDeclaration().label("import")).label("imports"), ZeroOrMore(anyTypeDeclaration().label("type")).label("types"), set(actions.createCompilationUnit(value("package"), values("imports/import"), values("types/type")))); } }