/** * Copyright (C) 2009-2011 STMicroelectronics * * This file is part of "Mind Compiler" is free software: you can redistribute * it and/or modify it under the terms of the GNU Lesser General Public License * as published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * * Contact: mind@ow2.org * * Authors: Matthieu Leclercq * Contributors: */ package org.ow2.mind.adl.parser; import static org.objectweb.fractal.adl.NodeUtil.castNodeError; import java.io.InputStream; import java.util.HashSet; import java.util.Set; import org.objectweb.fractal.adl.ADLErrors; import org.objectweb.fractal.adl.ADLException; import org.objectweb.fractal.adl.CompilerError; import org.objectweb.fractal.adl.Definition; import org.objectweb.fractal.adl.Node; import org.objectweb.fractal.adl.error.BasicErrorLocator; import org.objectweb.fractal.adl.error.ErrorLocator; import org.objectweb.fractal.adl.error.GenericErrors; import org.objectweb.fractal.adl.error.NodeErrorLocator; import org.objectweb.fractal.adl.interfaces.InterfaceContainer; import org.objectweb.fractal.adl.types.TypeInterface; import org.objectweb.fractal.adl.xml.XMLNodeFactory; import org.ow2.mind.PathHelper; import org.ow2.mind.PathHelper.InvalidRelativPathException; import org.ow2.mind.adl.anonymous.ast.AnonymousDefinitionContainer; import org.ow2.mind.adl.ast.ASTHelper; import org.ow2.mind.adl.ast.AbstractDefinition; import org.ow2.mind.adl.ast.Attribute; import org.ow2.mind.adl.ast.AttributeContainer; import org.ow2.mind.adl.ast.Binding; import org.ow2.mind.adl.ast.BindingContainer; import org.ow2.mind.adl.ast.Component; import org.ow2.mind.adl.ast.ComponentContainer; import org.ow2.mind.adl.ast.Data; import org.ow2.mind.adl.ast.DataField; import org.ow2.mind.adl.ast.DefinitionReference; import org.ow2.mind.adl.ast.DefinitionReferenceContainer; import org.ow2.mind.adl.ast.ImplementationContainer; import org.ow2.mind.adl.ast.MindDefinition; import org.ow2.mind.adl.ast.MindInterface; import org.ow2.mind.adl.ast.Source; import org.ow2.mind.adl.generic.ast.FormalTypeParameter; import org.ow2.mind.adl.generic.ast.FormalTypeParameterContainer; import org.ow2.mind.adl.generic.ast.FormalTypeParameterReference; import org.ow2.mind.adl.generic.ast.TypeArgument; import org.ow2.mind.adl.generic.ast.TypeArgumentContainer; import org.ow2.mind.adl.imports.ast.Import; import org.ow2.mind.adl.imports.ast.ImportContainer; import org.ow2.mind.adl.jtb.ParseException; import org.ow2.mind.adl.jtb.Parser; import org.ow2.mind.adl.jtb.ParserConstants; import org.ow2.mind.adl.jtb.TokenMgrError; import org.ow2.mind.adl.jtb.syntaxtree.ADLFile; import org.ow2.mind.adl.jtb.syntaxtree.AnnotationAnnotationValue; import org.ow2.mind.adl.jtb.syntaxtree.AnnotationParameters; import org.ow2.mind.adl.jtb.syntaxtree.AnnotationValue; import org.ow2.mind.adl.jtb.syntaxtree.AnnotationValuePair; import org.ow2.mind.adl.jtb.syntaxtree.ArchitectureDefinition; import org.ow2.mind.adl.jtb.syntaxtree.ArgumentAssignement; import org.ow2.mind.adl.jtb.syntaxtree.ArrayAnnotationValue; import org.ow2.mind.adl.jtb.syntaxtree.AttributeDefinition; import org.ow2.mind.adl.jtb.syntaxtree.AttributeType; import org.ow2.mind.adl.jtb.syntaxtree.BindingDefinition; import org.ow2.mind.adl.jtb.syntaxtree.BooleanValue; import org.ow2.mind.adl.jtb.syntaxtree.CompositeAnonymousDefinition; import org.ow2.mind.adl.jtb.syntaxtree.CompositeAnonymousExtension; import org.ow2.mind.adl.jtb.syntaxtree.CompositeDefinition; import org.ow2.mind.adl.jtb.syntaxtree.CompositeDefinitionReference; import org.ow2.mind.adl.jtb.syntaxtree.CompoundAttributeValue; import org.ow2.mind.adl.jtb.syntaxtree.CompoundAttributeValueField; import org.ow2.mind.adl.jtb.syntaxtree.CompoundFieldName; import org.ow2.mind.adl.jtb.syntaxtree.DataDefinition; import org.ow2.mind.adl.jtb.syntaxtree.DataFile; import org.ow2.mind.adl.jtb.syntaxtree.ExtendedCompositeDefinitions; import org.ow2.mind.adl.jtb.syntaxtree.ExtendedPrimitiveDefinitions; import org.ow2.mind.adl.jtb.syntaxtree.ExtendedTypeDefinitions; import org.ow2.mind.adl.jtb.syntaxtree.FlowInterfaceDefinition; import org.ow2.mind.adl.jtb.syntaxtree.FlowType; import org.ow2.mind.adl.jtb.syntaxtree.FormalParameterDeclaration; import org.ow2.mind.adl.jtb.syntaxtree.FormalTypeParameterDeclaration; import org.ow2.mind.adl.jtb.syntaxtree.FullyQualifiedName; import org.ow2.mind.adl.jtb.syntaxtree.FunctionalInterfaceDefinition; import org.ow2.mind.adl.jtb.syntaxtree.IDTType; import org.ow2.mind.adl.jtb.syntaxtree.ImplementationDefinition; import org.ow2.mind.adl.jtb.syntaxtree.ImportDefinition; import org.ow2.mind.adl.jtb.syntaxtree.IntegerValue; import org.ow2.mind.adl.jtb.syntaxtree.InterfaceDefinition; import org.ow2.mind.adl.jtb.syntaxtree.NodeChoice; import org.ow2.mind.adl.jtb.syntaxtree.NodeOptional; import org.ow2.mind.adl.jtb.syntaxtree.NodeSequence; import org.ow2.mind.adl.jtb.syntaxtree.NodeToken; import org.ow2.mind.adl.jtb.syntaxtree.NullValue; import org.ow2.mind.adl.jtb.syntaxtree.Path; import org.ow2.mind.adl.jtb.syntaxtree.PathValue; import org.ow2.mind.adl.jtb.syntaxtree.PrimitiveAnonymousDefinition; import org.ow2.mind.adl.jtb.syntaxtree.PrimitiveAnonymousExtension; import org.ow2.mind.adl.jtb.syntaxtree.PrimitiveDefinition; import org.ow2.mind.adl.jtb.syntaxtree.PrimitiveDefinitionReference; import org.ow2.mind.adl.jtb.syntaxtree.ReferenceValue; import org.ow2.mind.adl.jtb.syntaxtree.SimpleSubComponentReference; import org.ow2.mind.adl.jtb.syntaxtree.StringValue; import org.ow2.mind.adl.jtb.syntaxtree.SubComponentDefinition; import org.ow2.mind.adl.jtb.syntaxtree.TypeArgumentAssignement; import org.ow2.mind.adl.jtb.syntaxtree.TypeDefinition; import org.ow2.mind.adl.jtb.syntaxtree.TypeDefinitionReference; import org.ow2.mind.adl.jtb.visitor.GJDepthFirst; import org.ow2.mind.adl.parameter.ast.Argument; import org.ow2.mind.adl.parameter.ast.ArgumentContainer; import org.ow2.mind.adl.parameter.ast.FormalParameter; import org.ow2.mind.adl.parameter.ast.FormalParameterContainer; import org.ow2.mind.annotation.ast.AnnotationArgument; import org.ow2.mind.annotation.ast.AnnotationContainer; import org.ow2.mind.annotation.ast.AnnotationNode; import org.ow2.mind.error.ErrorManager; import org.ow2.mind.value.ast.Array; import org.ow2.mind.value.ast.BooleanLiteral; import org.ow2.mind.value.ast.CompoundValue; import org.ow2.mind.value.ast.CompoundValueField; import org.ow2.mind.value.ast.MultipleValueContainer; import org.ow2.mind.value.ast.NullLiteral; import org.ow2.mind.value.ast.NumberLiteral; import org.ow2.mind.value.ast.PathLiteral; import org.ow2.mind.value.ast.Reference; import org.ow2.mind.value.ast.SingleValueContainer; import org.ow2.mind.value.ast.StringLiteral; import org.ow2.mind.value.ast.Value; import org.xml.sax.SAXException; import com.google.inject.Inject; import com.google.inject.name.Named; /** * Translate the JTB AST of an ADL file into a "fractal-adl like" AST. */ public class JTBProcessor extends GJDepthFirst<Node, Node> implements ADLJTBParser, ParserConstants { public static final String ADL_DTD = "adl-dtd"; @Inject protected XMLNodeFactory nodeFactory; @Inject protected ErrorManager errorManager; @Inject protected BeginTokenVisitor beginTokenVisitor; @Inject protected EndTokenVisitor endTokenVisitor; @Inject @Named(ADL_DTD) protected String adlDtd; protected Set<String> typeParameters; protected String definitionName; protected String filename; public Definition parseADL(final InputStream is, final String definitionName, final String filename) throws ADLException { final Parser parser = new Parser(is); ADLFile content; try { content = parser.ADLFile(); } catch (final ParseException e) { final ErrorLocator locator = new BasicErrorLocator(filename, e.currentToken.next.beginLine, e.currentToken.next.endLine, e.currentToken.next.beginColumn, e.currentToken.next.endColumn); errorManager.logFatal(ADLErrors.PARSE_ERROR, locator, e.getMessage()); return null; } catch (final TokenMgrError e) { // TokenMgrError do not have location info. final ErrorLocator locator = new BasicErrorLocator(filename, -1, -1); errorManager.logFatal(ADLErrors.PARSE_ERROR, locator, e.getMessage()); // never executed (logFatal throw an ADLException). return null; } this.definitionName = definitionName; this.filename = filename; typeParameters = new HashSet<String>(); return (Definition) visit(content, null); } protected Node newNode(final String name) { return newNode(name, null); } protected Node newNode(final String name, final NodeToken source) { return newNode(name, source, source); } protected Node newNode(final String name, final NodeToken beginToken, final NodeToken endToken) { Node node; try { node = nodeFactory.newXMLNode(adlDtd, name); } catch (final SAXException e) { throw new CompilerError(GenericErrors.INTERNAL_ERROR, e, "Unable to create node"); } setSource(node, beginToken, endToken); return node; } protected Node newNode(final String name, final org.ow2.mind.adl.jtb.syntaxtree.Node syntaxNode) { return newNode(name, syntaxNode.accept(beginTokenVisitor), syntaxNode.accept(endTokenVisitor)); } protected void setSource(final Node node, final NodeToken source) { setSource(node, source, source); } protected void setSource(final Node node, final NodeToken beginToken, final NodeToken endToken) { if (beginToken == null) node.astSetSource(filename); else node.astSetSource(NodeErrorLocator.fullLocation(filename, beginToken.beginLine, endToken.endLine, beginToken.beginColumn, endToken.endColumn)); } protected void setSource(final Node node, final org.ow2.mind.adl.jtb.syntaxtree.Node syntaxNode) { setSource(node, syntaxNode.accept(beginTokenVisitor), syntaxNode.accept(endTokenVisitor)); } protected void copySource(final Node node, final Node from) { if (from == null) node.astSetSource(filename); else node.astSetSource(from.astGetSource()); } // --------------------------------------------------------------------------- // File level grammar // --------------------------------------------------------------------------- @Override public Node visit(final ADLFile n, final Node argu) { assert argu == null; final Definition def = (Definition) n.f1.accept(this, argu); assert def != null; // process imports n.f0.accept(this, def); return def; } @Override public Node visit(final ImportDefinition n, final Node argu) { assert argu != null; final ImportContainer container = castNodeError(argu, ImportContainer.class); String packageName; final Import imp = (Import) newNode("import", n); packageName = n.f2.tokenImage; for (final org.ow2.mind.adl.jtb.syntaxtree.Node name : n.f4.nodes) { packageName += "." + ((NodeToken) ((NodeSequence) name).elementAt(0)).tokenImage; } imp.setPackageName(packageName); final NodeToken t = (NodeToken) n.f5.choice; if (t.kind == START) { imp.setSimpleName(Import.ON_DEMAND_IMPORT); } else { imp.setSimpleName(t.tokenImage); } container.addImport(imp); // process annotations n.f0.accept(this, imp); return imp; } @Override public Node visit(final ArchitectureDefinition n, final Node argu) { return n.f0.accept(this, argu); } // --------------------------------------------------------------------------- // Definition prototypes grammar // --------------------------------------------------------------------------- @Override public Node visit(final TypeDefinition n, final Node argu) { assert argu == null; final MindDefinition def = (MindDefinition) newNode("type", n); // process annotations n.f0.accept(this, def); // set name def.setName(fullyQualifiedName(n.f2)); // process "extends ..." n.f3.accept(this, def); // process body n.f4.accept(this, def); return def; } @Override public Node visit(final ExtendedTypeDefinitions n, final Node argu) { assert argu != null; final MindDefinition def = castNodeError(argu, MindDefinition.class); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n); def.setExtends(extend); // process definition reference list. n.f1.accept(this, extend); n.f2.accept(this, extend); return extend; } @Override public Node visit(final TypeDefinitionReference n, final Node argu) { final DefinitionReference defRef = (DefinitionReference) newNode( "definition", n); defRef.setName(fullyQualifiedName(n.f0)); if (argu != null) { castNodeError(argu, DefinitionReferenceContainer.class) .addDefinitionReference(defRef); } return defRef; } // --------------------------------------------------------------------------- @Override public Node visit(final PrimitiveDefinition n, final Node argu) { assert argu == null; final MindDefinition def = (MindDefinition) newNode("primitive", n); // process annotations n.f0.accept(this, def); // process abstract if (n.f1.present()) castNodeError(def, AbstractDefinition.class).setIsAbstract( AbstractDefinition.TRUE); // set name def.setName(fullyQualifiedName(n.f3)); // process formal parameters n.f4.accept(this, def); // process "extends ..." n.f5.accept(this, def); // process body n.f6.accept(this, def); return def; } @Override public Node visit(final FormalParameterDeclaration n, final Node argu) { assert argu != null; final FormalParameterContainer container = castNodeError(argu, FormalParameterContainer.class); final FormalParameter param = (FormalParameter) newNode("parameter", n); param.setName(n.f0.tokenImage); container.addFormalParameter(param); return null; } @Override public Node visit(final ExtendedPrimitiveDefinitions n, final Node argu) { assert argu != null; final MindDefinition def = castNodeError(argu, MindDefinition.class); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n); def.setExtends(extend); // process definition reference list. n.f1.accept(this, extend); n.f2.accept(this, extend); return extend; } @Override public Node visit(final PrimitiveDefinitionReference n, final Node argu) { final DefinitionReference defRef = (DefinitionReference) newNode( "definition", n); defRef.setName(fullyQualifiedName(n.f0)); // process arguments n.f1.accept(this, defRef); if (argu != null) castNodeError(argu, DefinitionReferenceContainer.class) .addDefinitionReference(defRef); return defRef; } @Override public Node visit(final ArgumentAssignement n, final Node argu) { final Argument arg = (Argument) n.f2.accept(this, argu); arg.setName(n.f0.tokenImage); setSource(arg, n.f0); return arg; } @Override public Node visit(final org.ow2.mind.adl.jtb.syntaxtree.Argument n, final Node argu) { assert argu != null; final Argument arg = (Argument) newNode("argument", n); // process argument value n.f0.accept(this, arg); assert arg.getValue() != null; copySource(arg, arg.getValue()); castNodeError(argu, ArgumentContainer.class).addArgument(arg); return arg; } // --------------------------------------------------------------------------- @Override public Node visit(final CompositeDefinition n, final Node argu) { assert argu == null; final MindDefinition def = (MindDefinition) newNode("composite", n); // process annotations n.f0.accept(this, def); // set name def.setName(fullyQualifiedName(n.f2)); // process formal type parameters n.f3.accept(this, def); // process formal parameters n.f4.accept(this, def); // process "extends ..." n.f5.accept(this, def); // process body n.f6.accept(this, def); return def; } @Override public Node visit(final FormalTypeParameterDeclaration n, final Node argu) { assert argu != null; final FormalTypeParameter typeParam = (FormalTypeParameter) newNode( "typeParameter", n); typeParam.setName(n.f0.tokenImage); typeParam.setDefinitionReference((DefinitionReference) n.f2.accept(this, null)); // add typeParam in set of type parameter. typeParameters.add(n.f0.tokenImage); castNodeError(argu, FormalTypeParameterContainer.class) .addFormalTypeParameter(typeParam); return typeParam; } @Override public Node visit(final CompositeDefinitionReference n, final Node argu) { final DefinitionReference defRef = (DefinitionReference) newNode( "definition", n); defRef.setName(fullyQualifiedName(n.f0)); // process type arguments n.f1.accept(this, defRef); // process arguments n.f2.accept(this, defRef); if (argu != null) castNodeError(argu, DefinitionReferenceContainer.class) .addDefinitionReference(defRef); return defRef; } @Override public Node visit(final TypeArgumentAssignement n, final Node argu) { final TypeArgument arg = (TypeArgument) n.f2.accept(this, argu); arg.setTypeParameterName(n.f0.tokenImage); setSource(arg, n.f0); return arg; } @Override public Node visit(final org.ow2.mind.adl.jtb.syntaxtree.TypeArgument n, final Node argu) { assert argu != null; final TypeArgument typeArg = (TypeArgument) newNode("typeArgument", n); if (n.f0.choice instanceof CompositeDefinitionReference) { final CompositeDefinitionReference cdr = (CompositeDefinitionReference) n.f0.choice; // if CompositeDefinitionReference contains only a simple <IDENTIFIER> // that matches a declared formal type parameter if (!cdr.f0.f1.present() && !cdr.f1.present() && !cdr.f2.present() && typeParameters.contains(cdr.f0.f0.tokenImage)) { // CompositeDefinitionReference is in fact a reference to a // FormalTypeParameter. setSource(typeArg, cdr.f0.f0); typeArg.setTypeParameterReference(cdr.f0.f0.tokenImage); } else { // CompositeDefinitionReference is actually a definition reference final DefinitionReference defRef = (DefinitionReference) n.f0.choice .accept(this, null); typeArg.setDefinitionReference(defRef); copySource(typeArg, defRef); } } else { assert n.f0.choice instanceof NodeToken && ((NodeToken) n.f0.choice).kind == ANY; // nothing to do. } castNodeError(argu, TypeArgumentContainer.class).addTypeArgument(typeArg); return typeArg; } @Override public Node visit(final ExtendedCompositeDefinitions n, final Node argu) { assert argu != null; final MindDefinition def = castNodeError(argu, MindDefinition.class); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n); def.setExtends(extend); // process definition reference list. n.f1.accept(this, extend); n.f2.accept(this, extend); return extend; } // --------------------------------------------------------------------------- // Content grammar // --------------------------------------------------------------------------- @Override public Node visit(final InterfaceDefinition n, final Node argu) { assert argu != null; // process FunctionalInterfaceDefinition | FlowInterfaceDefinition final MindInterface itf = (MindInterface) n.f1.accept(this, argu); // process annotations n.f0.accept(this, itf); castNodeError(argu, InterfaceContainer.class).addInterface(itf); return itf; } @Override public Node visit(final FunctionalInterfaceDefinition n, final Node argu) { final MindInterface itf = (MindInterface) newNode("interface", n); if (((NodeToken) n.f0.choice).kind == PROVIDES) { itf.setRole(TypeInterface.SERVER_ROLE); } else { assert ((NodeToken) n.f0.choice).kind == REQUIRES; itf.setRole(TypeInterface.CLIENT_ROLE); } // process contingency if (n.f1.present()) itf.setContingency(TypeInterface.OPTIONAL_CONTINGENCY); // process IDL signature itf.setSignature(fullyQualifiedName(n.f2)); // process name itf.setName(n.f4.tokenImage); // process [count] if (n.f5.present()) { itf.setCardinality(TypeInterface.COLLECTION_CARDINALITY); if (((NodeOptional) ((NodeSequence) n.f5.node).elementAt(1)).present()) { final NodeToken count = (NodeToken) ((NodeOptional) ((NodeSequence) n.f5.node) .elementAt(1)).node; itf.setNumberOfElement(count.tokenImage); } } return itf; } @Override public Node visit(final FlowInterfaceDefinition n, final Node argu) { final MindInterface itf = (MindInterface) newNode("interface", n); if (((NodeToken) n.f0.choice).kind == INPUT) { itf.setRole(ASTHelper.INPUT_ROLE); } else { assert ((NodeToken) n.f0.choice).kind == OUTPUT; itf.setRole(ASTHelper.OUTPUT_ROLE); } // process contingency if (n.f1.present()) itf.setContingency(TypeInterface.OPTIONAL_CONTINGENCY); // process type n.f2.accept(this, itf); // process name itf.setName(n.f4.tokenImage); // process [count] if (n.f5.present()) { itf.setCardinality(TypeInterface.COLLECTION_CARDINALITY); if (((NodeOptional) ((NodeSequence) n.f5.node).elementAt(1)).present()) { final NodeToken count = (NodeToken) ((NodeOptional) ((NodeSequence) n.f5.node) .elementAt(1)).node; itf.setNumberOfElement(count.tokenImage); } } return itf; } @Override public Node visit(final FlowType n, final Node argu) { assert argu != null; if (n.f0.choice instanceof AttributeType) { final AttributeType type = (AttributeType) n.f0.choice; if (argu instanceof MindInterface) { final MindInterface itf = castNodeError(argu, MindInterface.class); itf.setSignature(((NodeToken) type.f0.choice).tokenImage); } else if (argu instanceof Attribute) { final Attribute attr = (Attribute) argu; attr.setType(((NodeToken) type.f0.choice).tokenImage); } else { // This should be a data field final DataField dataField = castNodeError(argu, DataField.class); dataField.setType(((NodeToken) type.f0.choice).tokenImage); } } else { assert n.f0.choice instanceof IDTType; n.f0.choice.accept(this, argu); } return argu; } @Override public Node visit(final IDTType n, final Node argu) { assert argu != null; final String idt = path(n.f0); String type = n.f3.tokenImage; if (n.f2.present()) { type = ((NodeToken) ((NodeChoice) n.f2.node).choice).tokenImage + " " + type; } if (argu instanceof MindInterface) { final MindInterface itf = (MindInterface) argu; itf.setSignature(idt + ":" + type); } else if (argu instanceof Attribute) { final Attribute attr = (Attribute) argu; attr.setIdt(idt); attr.setType(type); } else { // This should be a data field final DataField dataField = castNodeError(argu, DataField.class); dataField.setIdt(idt); dataField.setType(type); } return argu; } // --------------------------------------------------------------------------- @Override public Node visit(final AttributeDefinition n, final Node argu) { assert argu != null; final Attribute attr = (Attribute) newNode("attribute", n); // process annotations n.f0.accept(this, attr); // process attribute type n.f2.accept(this, attr); // process name attr.setName(n.f3.tokenImage); // process value n.f4.accept(this, attr); castNodeError(argu, AttributeContainer.class).addAttribute(attr); return attr; } @Override public Node visit(final AttributeType n, final Node argu) { assert argu != null; castNodeError(argu, Attribute.class).setType( ((NodeToken) n.f0.choice).tokenImage); return argu; } @Override public Node visit(final CompoundAttributeValue n, final Node argu) { assert argu != null; final CompoundValue value = (CompoundValue) newNode("compoundValue", n); // process fields n.f1.accept(this, value); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final CompoundAttributeValueField n, final Node argu) { assert argu != null; final CompoundValueField field = (CompoundValueField) newNode( "compoundValueField", n); // process name (if any) n.f0.accept(this, field); // process value n.f1.accept(this, field); castNodeError(argu, CompoundValue.class).addCompoundValueField(field); return field; } @Override public Node visit(final CompoundFieldName n, final Node argu) { assert argu != null; castNodeError(argu, CompoundValueField.class).setName(n.f1.tokenImage); return argu; } // --------------------------------------------------------------------------- @Override public Node visit(final DataDefinition n, final Node argu) { assert argu != null; // process DataField() | DataFile() if (n.f2.choice instanceof org.ow2.mind.adl.jtb.syntaxtree.DataField) { final DataField dataField = (DataField) newNode("dataField", n); // process annotations n.f0.accept(this, dataField); // process DataField n.f2.accept(this, dataField); castNodeError(argu, ImplementationContainer.class) .addDataField(dataField); return dataField; } else { final Data data = (Data) newNode("data", n); // process annotations n.f0.accept(this, data); // process DataFile n.f2.accept(this, data); final ImplementationContainer implContainer = castNodeError(argu, ImplementationContainer.class); if (implContainer.getData() != null) { try { errorManager.logError(org.ow2.mind.adl.ADLErrors.MULTIPLE_DATA, data); } catch (final ADLException e) { // ignore. } } implContainer.setData(data); return data; } } @Override public Node visit(final DataFile n, final Node argu) { assert argu != null; final Data data = castNodeError(argu, Data.class); // process Path() | <CCode> if (n.f0.choice instanceof NodeToken) { assert ((NodeToken) n.f0.choice).kind == INLINED_CODE; final String inlinedCCode = ((NodeToken) n.f0.choice).tokenImage; data.setCCode(inlinedCCode.substring(2, inlinedCCode.length() - 2)); } else { assert n.f0.choice instanceof Path; data.setPath(path((Path) n.f0.choice)); } return data; } @Override public Node visit(final org.ow2.mind.adl.jtb.syntaxtree.DataField n, final Node argu) { assert argu != null; final DataField dataField = castNodeError(argu, DataField.class); // process FlowType n.f0.accept(this, dataField); // set name dataField.setName(n.f1.tokenImage); return dataField; } // --------------------------------------------------------------------------- @Override public Node visit(final ImplementationDefinition n, final Node argu) { assert argu != null; final Source src = (Source) newNode("source", n); // process annotations n.f0.accept(this, src); // process Path() | <CCode> if (n.f2.choice instanceof NodeToken) { assert ((NodeToken) n.f2.choice).kind == INLINED_CODE; final String inlinedCCode = ((NodeToken) n.f2.choice).tokenImage; src.setCCode(inlinedCCode.substring(2, inlinedCCode.length() - 2)); } else { assert n.f2.choice instanceof Path; src.setPath(path((Path) n.f2.choice)); } castNodeError(argu, ImplementationContainer.class).addSource(src); return src; } // --------------------------------------------------------------------------- @Override public Node visit(final BindingDefinition n, final Node argu) { assert argu != null; final Binding bind = (Binding) newNode("binding", n); // process annotations n.f0.accept(this, bind); // process from component name bind.setFromComponent(((NodeToken) n.f2.f0.choice).tokenImage); // process from interface name bind.setFromInterface(n.f4.tokenImage); // process from interface index (if any) if (n.f5.present()) bind.setFromInterfaceNumber(((NodeToken) ((NodeSequence) n.f5.node) .elementAt(1)).tokenImage); // process to component name bind.setToComponent(((NodeToken) n.f7.f0.choice).tokenImage); // process to interface name bind.setToInterface(n.f9.tokenImage); // process to interface index (if any) if (n.f10.present()) bind.setToInterfaceNumber(((NodeToken) ((NodeSequence) n.f10.node) .elementAt(1)).tokenImage); castNodeError(argu, BindingContainer.class).addBinding(bind); return bind; } // --------------------------------------------------------------------------- @Override public Node visit(final SubComponentDefinition n, final Node argu) { assert argu != null; final Component comp = (Component) newNode("component", n); // process annotations n.f0.accept(this, comp); // process SubComponentReference n.f2.accept(this, comp); castNodeError(argu, ComponentContainer.class).addComponent(comp); return comp; } @Override public Node visit(final SimpleSubComponentReference n, final Node argu) { assert argu != null; final Component comp = (Component) argu; boolean hasDefRef = false; // process definition reference if (n.f0.present()) { hasDefRef = true; final CompositeDefinitionReference cdr = (CompositeDefinitionReference) n.f0.node; // if CompositeDefinitionReference contains only a simple <IDENTIFIER> // that matches a declared formal type parameter if (!cdr.f0.f1.present() && !cdr.f1.present() && !cdr.f2.present() && typeParameters.contains(cdr.f0.f0.tokenImage)) { // CompositeDefinitionReference is in fact a reference to a // FormalTypeParameter. castNodeError(comp, FormalTypeParameterReference.class) .setTypeParameterReference(cdr.f0.f0.tokenImage); } else { // CompositeDefinitionReference is actually a definition reference final DefinitionReference defRef = (DefinitionReference) n.f0.accept( this, null); comp.setDefinitionReference(defRef); } } // process name String nameList = n.f2.tokenImage; for (final org.ow2.mind.adl.jtb.syntaxtree.Node subN : n.f3.nodes) { assert subN instanceof NodeSequence; nameList += "," + ((NodeToken) ((NodeSequence) subN).elementAt(1)).tokenImage; } comp.setName(nameList); // process anonymous definition if (n.f4.present()) { if (comp instanceof FormalTypeParameterReference && ((FormalTypeParameterReference) comp).getTypeParameterReference() != null) { // both reference to template parameter and anonymous definition try { errorManager.logError(ADLErrors.PARSE_ERROR, comp, "The contains construct cannot reference a template parameter and " + "have an anonymous definition."); } catch (final ADLException e) { // ignore. } } n.f4.accept(this, comp); } else if (!hasDefRef) { // neither defRef nor anonymous definition try { errorManager.logError(ADLErrors.PARSE_ERROR, comp, "The contains construct must reference " + "another definition or have an anonymous definition."); } catch (final ADLException e) { // ignore. } } return comp; } @Override public Node visit(final CompositeAnonymousDefinition n, final Node argu) { assert argu != null; final Component comp = (Component) argu; final MindDefinition def = (MindDefinition) newNode("anonymousComposite", n); castNodeError(comp, AnonymousDefinitionContainer.class) .setAnonymousDefinition(def); final DefinitionReference defRef = comp.getDefinitionReference(); if (defRef != null) { comp.setDefinitionReference(null); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n.f1); def.setExtends(extend); extend.addDefinitionReference(defRef); } // process annotations n.f0.accept(this, def); // process composite definition elements n.f3.accept(this, def); return def; } @Override public Node visit(final PrimitiveAnonymousDefinition n, final Node argu) { assert argu != null; final Component comp = (Component) argu; final MindDefinition def = (MindDefinition) newNode("anonymousPrimitive", n); castNodeError(comp, AnonymousDefinitionContainer.class) .setAnonymousDefinition(def); final DefinitionReference defRef = comp.getDefinitionReference(); if (defRef != null) { comp.setDefinitionReference(null); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n.f1); def.setExtends(extend); extend.addDefinitionReference(defRef); } // process annotations n.f0.accept(this, def); // process composite definition elements n.f3.accept(this, def); return def; } @Override public Node visit(final CompositeAnonymousExtension n, final Node argu) { assert argu != null; final Component comp = (Component) argu; final MindDefinition def = (MindDefinition) newNode("anonymousComposite", n); castNodeError(comp, AnonymousDefinitionContainer.class) .setAnonymousDefinition(def); final DefinitionReference defRef = comp.getDefinitionReference(); if (defRef != null) { comp.setDefinitionReference(null); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n.f1); def.setExtends(extend); extend.addDefinitionReference(defRef); } // process annotations n.f0.accept(this, def); // process composite definition elements n.f2.accept(this, def); return def; } @Override public Node visit(final PrimitiveAnonymousExtension n, final Node argu) { assert argu != null; final Component comp = (Component) argu; final MindDefinition def = (MindDefinition) newNode("anonymousPrimitive", n); castNodeError(comp, AnonymousDefinitionContainer.class) .setAnonymousDefinition(def); final DefinitionReference defRef = comp.getDefinitionReference(); if (defRef != null) { comp.setDefinitionReference(null); final DefinitionReferenceContainer extend = (DefinitionReferenceContainer) newNode( "extends", n.f1); def.setExtends(extend); extend.addDefinitionReference(defRef); } // process annotations n.f0.accept(this, def); // process composite definition elements n.f2.accept(this, def); return def; } // --------------------------------------------------------------------------- // Annotation grammar // --------------------------------------------------------------------------- @Override public Node visit(final org.ow2.mind.adl.jtb.syntaxtree.Annotation n, final Node argu) { assert argu != null; final AnnotationNode annotation = (AnnotationNode) newNode("annotation", n); // process type annotation.setType(fullyQualifiedName(n.f1)); // process parameters n.f2.accept(this, annotation); castNodeError(argu, AnnotationContainer.class).addAnnotation(annotation); return annotation; } @Override public Node visit(final AnnotationParameters n, final Node argu) { assert argu != null; final AnnotationNode annotation = (AnnotationNode) argu; if (n.f1.present()) { if (((NodeChoice) n.f1.node).choice instanceof AnnotationValue) { final AnnotationArgument defaultParam = (AnnotationArgument) newNode( "annotationArgument", n); defaultParam.setName(AnnotationArgument.DEFAULT_NAME); annotation.addAnnotationArgument(defaultParam); // process default value n.f1.accept(this, defaultParam); } else { n.f1.accept(this, annotation); } } return annotation; } @Override public Node visit(final AnnotationValuePair n, final Node argu) { assert argu != null; final AnnotationNode annotation = (AnnotationNode) argu; final AnnotationArgument param = (AnnotationArgument) newNode( "annotationArgument", n); annotation.addAnnotationArgument(param); // process name param.setName(n.f0.tokenImage); // process value n.f2.accept(this, param); return annotation; } @Override public Node visit(final AnnotationAnnotationValue n, final Node argu) { assert argu != null; final AnnotationNode value = (AnnotationNode) newNode("annotationValue", n); // process type value.setType(fullyQualifiedName(n.f0.f1)); // process parameters n.f0.f2.accept(this, value); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(castNodeError(value, Value.class)); } else { castNodeError(argu, MultipleValueContainer.class).addValue( castNodeError(value, Value.class)); } return value; } @Override public Node visit(final ArrayAnnotationValue n, final Node argu) { assert argu != null; final Array value = (Array) newNode("array", n); // process sub values n.f1.accept(this, value); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } // --------------------------------------------------------------------------- // Value grammar // --------------------------------------------------------------------------- @Override public Node visit(final StringValue n, final Node argu) { assert argu != null; final StringLiteral value = (StringLiteral) newNode("string", n); value.setValue(n.f0.tokenImage); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final IntegerValue n, final Node argu) { assert argu != null; final NumberLiteral value = (NumberLiteral) newNode("integer", n); if (n.f0.present()) { value.setValue(((NodeToken) ((NodeChoice) n.f0.node).choice).tokenImage + n.f1.tokenImage); } else { value.setValue(n.f1.tokenImage); } if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final BooleanValue n, final Node argu) { assert argu != null; final BooleanLiteral value = (BooleanLiteral) newNode("boolean", n); if (n.f0.tokenImage.equals(BooleanLiteral.TRUE)) { value.setValue(BooleanLiteral.TRUE); } else { value.setValue(BooleanLiteral.FALSE); } if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final ReferenceValue n, final Node argu) { assert argu != null; final Reference value = (Reference) newNode("reference", n); value.setRef(n.f0.tokenImage); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final NullValue n, final Node argu) { assert argu != null; final NullLiteral value = (NullLiteral) newNode("null", n); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } @Override public Node visit(final PathValue n, final Node argu) { assert argu != null; final PathLiteral value = (PathLiteral) newNode("path", n); String path = path(n.f0); if (PathHelper.isRelative(path)) { try { path = PathHelper.fullyQualifiedNameToAbsolute(definitionName, path); } catch (final InvalidRelativPathException e) { try { errorManager.logError(org.ow2.mind.adl.ADLErrors.INVALID_PATH, value, path); } catch (final ADLException e1) { // ignore } } } value.setValue(path); if (argu instanceof SingleValueContainer) { ((SingleValueContainer) argu).setValue(value); } else { castNodeError(argu, MultipleValueContainer.class).addValue(value); } return value; } // --------------------------------------------------------------------------- // Utility // --------------------------------------------------------------------------- private String fullyQualifiedName(final FullyQualifiedName n) { String name = n.f0.tokenImage; for (final org.ow2.mind.adl.jtb.syntaxtree.Node node : n.f1.nodes) { name += "." + ((NodeToken) ((NodeSequence) node).elementAt(1)).tokenImage; } return name; } private String path(final Path n) { String s; if (n.f0.present()) { s = "/"; } else { s = ""; } if (n.f1.present()) { s += "./"; } for (int i = 0; i < n.f2.size(); i++) s += "../"; s += n.f3.tokenImage; for (final org.ow2.mind.adl.jtb.syntaxtree.Node pathElem : n.f4.nodes) { s += "/" + ((NodeToken) ((NodeSequence) pathElem).elementAt(1)).tokenImage; } if (n.f5.present()) { s += "." + ((NodeToken) ((NodeSequence) (n.f5.node)).elementAt(1)).tokenImage; } return s; } }