Aufgrund einer Wartung wird GitLab am 18.05. zwischen 8:00 und 9:00 Uhr kurzzeitig nicht zur Verfügung stehen. / Due to maintenance, GitLab will be temporarily unavailable on 18.05. between 8:00 and 9:00 am.

Commit e4fc9a1d authored by vonWenckstern's avatar vonWenckstern
Browse files

new grammar parses all models ;)

-> still long-way to go
parent b10f956e
Pipeline #72942 failed with stage
in 43 seconds
......@@ -48,47 +48,27 @@ grammar EmbeddedMontiArc extends de.monticore.lang.monticar.Common2 {
*/
interface Element;
/**
* A component is a unit of computation or a data store.
* The size of a component may scale from a single
* procedure to a whole application. A component may be
* either decomposed to subcomponents or is atomic.
*
* @attribute name type name of this component
* @attribute head is used to set generic types, a
* configuration and a parent component
* @attribute instanceName if this optional name is given,
* a subcomponent is automatically created that
* instantiates this inner component type. This is only
* allowed for inner component definitions.
* @attribute body contains the architectural elements
* inherited by this component
* A components head is used to define generic type
* parameters that may be used as port types in the
* component, to define configuration parameters that may
* be used to configure the component, and to set the
* parent component of this component.
*
* @attribute genericTypeParameters a list of type
* parameters that may be used as port types in the
* component
* @attribute parameters a list of Parameters that
* define a configurable component. If a configurable
* component is referenced, these parameters have to be
* set.
* @attribute superComponent the type of the super
* component
*/
/**
component X<T = Length, N1 n = 2> ( (0 cm : oo m)^{2, 2} length = [9 cm, 8 cm; 12 cm, 3 cm])
implements Interface1<3> { ... }
*/
symbol scope Component implements Element =
"component" (["interface"])? Name
//("component" | ["component_interface"]) Name
genericTypeParameters:TypeParameters2?
( "(" (Parameter || ",")+ ")" )?
("implements" superComponent:ReferenceType)?
GenericTypeParameters?
ConfigurationParameters?
ImplementedComponentInterfaces?
body:ComponentBody;
GenericTypeParameters = "<" (GenericTypeParameter || ",")+ ">";
GenericTypeParameter = TypeVariableDeclaration2 ("=" Value)?;
ConfigurationParameters = "(" parameters:(Parameter || ",")+ ")";
ImplementedComponentInterfaces = "implements" componentInterfaces:(ComponentInstantiation || ",")+;
// Component1<7, 3> (5)
ComponentInstantiation = Name GenericValues? ConfigurationValues?;
GenericValues = "<" (Type || ",")+ ">";
ConfigurationValues = "(" (Expression || ",")+ ")";
/**
* The body contains architectural elements of
......@@ -102,66 +82,35 @@ grammar EmbeddedMontiArc extends de.monticore.lang.monticar.Common2 {
"}" );
/**
* An Interface defines an interface of a component
* containing in- and outgoing ports.
* @attribute ports a list of ports that are contained in
* this interface
ports in Q in1,
Z in2[3],
(0m : 10m) in3,
B^4 in4,
out Struct1 out1;
*/
Interface implements Element =
("port"|"ports")
ports:(Port || ",")+ ";" ;
/**a
* An incoming port is used to receive messages, an
* outgoing port is used to send messages of a specific
* type. Ports can now also be specified as an array.
*
* @attribute incoming true, if this is an incoming port
* @attribute outgoing true, if this is an outgoing port
* @attribute type the message type of this port
* @attribute name an optional name of this port
*/
/**might support auto type adding based on last previous type
* declaration later on
*/
Port =
AdaptableKeyword? (incoming:["in"] | outgoing:["out"])
Type (Name? | Name ( "[" UnitNumberResolution "]" )?) ;
AdaptableKeyword? (incoming:["in"] | outgoing:["out"])?
Type NamePlusDimension;
ArrayDimension =
"[" UnitNumberResolution "]" ;
// x[5] or y[n]
NamePlusDimension =
Name dimension:ArrayDimension?;
/**
* A subcomponent is used to create one or more instances
* of another component. This way the hierarchical
* structure of a component is defined.
* @attribute type the type of the instantiated component
* @attribute arguments list of configuration parameters
* that are to be set, if the instantiated component is
* configurable.
* @attribute instances list of instances that should be
* created
instances Cmp1<7> c11, c12;
instance Cmp1<8> c2;
*/
SubComponent implements Element =
"instance"
type:ReferenceType
("(" arguments:(Expression || ",")+ ")" )?
instances:(SubComponentInstance || ",")* ";" ;
/**
* A subcomponent instance binds the name of an instance
* with an optional list of simple connectors used to
* connect this instance with other subcomponents/ports.
* It does also support component arrays.
* Simple connectors directly connect outgoing ports of the
* corresponding subcomponent declaration with one or more target ports.
*
* @attribute name the name of this instance
* @attribute connectors list of simple connectors
*/
// TODO better/more intuitive name? e.g. "refConnector" (not really good...)
SubComponentInstance =
Name
("[" UnitNumberResolution "]")? ;
("instance" | "instances")
ComponentInstantiation
instances:(NamePlusDimension || ",")+ ";" ;
/**
* port1
......@@ -174,14 +123,14 @@ grammar EmbeddedMontiArc extends de.monticore.lang.monticar.Common2 {
*/
QualifiedNameWithArrayAndStar = QualifiedNameWithArray DotStar?;
DotStar = "." {noSpace()}? "*";
/**
* A connector connects one source port with one or many
* target ports.
*
* @attribute source source port or component instance
* name
* @attribute targets a list of target ports or component
* instance names
connect sub1.in1 -> sub1B.in1;
connect sub2[2:n].in1 -> sub2B[2:n].in1;
connect sub3.in1[:] -> sub3B.in1[:];
connect 7 km/h -> sub4B.in1;
connect sub1.* -> sub1B.*;
connect sub5[:].* -> sub5B[:].*;
*/
Connector implements Element=
"connect" (source:QualifiedNameWithArrayAndStar |
......
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project 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.0 of the License, or (at your option) any later version.
* This library 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 project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.embeddedmontiarc.cocos;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._cocos.EmbeddedMontiArcASTComponentCoCo;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAConnectorSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
import de.se_rwth.commons.logging.Log;
import java.util.Collection;
import java.util.stream.Collectors;
/**
* CV5: In decomposed components all ports should be used in at least one connector.<br>
* DIFFERENCE to CV6: CV5 checks that in and out ports are connected <em>within</em> the
* (non-atomic) component itself while CV6 checks that a subcomponent is connected in its
* <em>outer context</em> (i.e. the outer component).
*
* @author ahaber, Robert Heim
*/
public class PortUsage implements EmbeddedMontiArcASTComponentCoCo {
private Collection<String> getNames(Collection<EMAPortSymbol> ports) {
return ports.stream().map(p -> p.getName())
.collect(Collectors.toList());
}
private Collection<String> getSourceNames(Collection<EMAConnectorSymbol> connectors) {
return connectors.stream().map(c -> c.getSource()).collect(Collectors.toList());
}
private Collection<String> getTargetNames(Collection<EMAConnectorSymbol> connectors) {
return connectors.stream().map(c -> c.getTarget()).collect(Collectors.toList());
}
@Override
public void check(ASTComponent node) {
EMAComponentSymbol entry = (EMAComponentSymbol) node.getSymbolOpt().get();
// %%%%%%%%%%%%%%%% CV5 %%%%%%%%%%%%%%%%
if (entry.isDecomposed()) {
// --------- IN PORTS ----------
// check that in-ports are used within the component
// in->out or in->sub.in (both only occur as normal connectors where the in ports must be the
// source)
Collection<String> remainingPorts = getNames(entry.getIncomingPorts());
Collection<String> connectorSources = getSourceNames(entry.getConnectors());
if (entry.isInnerComponent()) {
// ports not connected by the inner component itself might be connected from the parent
// component or any of the parent's subcomponents' simple connectors
EMAComponentSymbol componentUsingSubComp = (EMAComponentSymbol) entry.getEnclosingScope()
.getSpanningSymbol().get();
connectorSources.addAll(getSourceNames(componentUsingSubComp.getConnectors()));
}
remainingPorts.removeAll(connectorSources);
if (!remainingPorts.isEmpty()) {
remainingPorts.forEach(p -> Log.error(String.format("0xAC006 Port %s is not used!", p)));
}
// --------- OUT PORTS ----------
// check that out-ports are connected (i.e. they are targets of connectors)
// they might be connected using normal connectors (in->out or sub.out->out)
// or using simple connectors (sub.out->out) (note that simple connectors only allow the
// subcomponents outgoing ports as source)
remainingPorts = getNames(entry.getOutgoingPorts());
Collection<String> connectorTargets = getTargetNames(entry.getConnectors());
// add simple connectors of all subcomponents that might connect the ports.
entry.getSubComponents()
.forEach(sc -> connectorTargets.addAll(getTargetNames(sc.getSimpleConnectors())));
remainingPorts.removeAll(connectorTargets);
if (!remainingPorts.isEmpty()&&node.getSubComponents().size()!=0) {
remainingPorts.forEach(p -> Log.error(String.format("0xAC007 Port %s is not used!", p),
node.get_SourcePositionStart()));
}
}
}
}
///**
// *
// * ******************************************************************************
// * MontiCAR Modeling Family, www.se-rwth.de
// * Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
// * All rights reserved.
// *
// * This project 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.0 of the License, or (at your option) any later version.
// * This library 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 project. If not, see <http://www.gnu.org/licenses/>.
// * *******************************************************************************
// */
//package de.monticore.lang.embeddedmontiarc.cocos;
//
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._cocos.EmbeddedMontiArcASTComponentCoCo;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAConnectorSymbol;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
//import de.se_rwth.commons.logging.Log;
//
//import java.util.Collection;
//import java.util.stream.Collectors;
//
///**
// * CV5: In decomposed components all ports should be used in at least one connector.<br>
// * DIFFERENCE to CV6: CV5 checks that in and out ports are connected <em>within</em> the
// * (non-atomic) component itself while CV6 checks that a subcomponent is connected in its
// * <em>outer context</em> (i.e. the outer component).
// *
// * @author ahaber, Robert Heim
// */
//public class PortUsage implements EmbeddedMontiArcASTComponentCoCo {
//
// private Collection<String> getNames(Collection<EMAPortSymbol> ports) {
// return ports.stream().map(p -> p.getName())
// .collect(Collectors.toList());
// }
//
// private Collection<String> getSourceNames(Collection<EMAConnectorSymbol> connectors) {
// return connectors.stream().map(c -> c.getSource()).collect(Collectors.toList());
// }
//
// private Collection<String> getTargetNames(Collection<EMAConnectorSymbol> connectors) {
// return connectors.stream().map(c -> c.getTarget()).collect(Collectors.toList());
// }
//
// @Override
// public void check(ASTComponent node) {
// EMAComponentSymbol entry = (EMAComponentSymbol) node.getSymbolOpt().get();
//
// // %%%%%%%%%%%%%%%% CV5 %%%%%%%%%%%%%%%%
// if (entry.isDecomposed()) {
// // --------- IN PORTS ----------
// // check that in-ports are used within the component
// // in->out or in->sub.in (both only occur as normal connectors where the in ports must be the
// // source)
//
// Collection<String> remainingPorts = getNames(entry.getIncomingPorts());
//
// Collection<String> connectorSources = getSourceNames(entry.getConnectors());
//
// if (entry.isInnerComponent()) {
// // ports not connected by the inner component itself might be connected from the parent
// // component or any of the parent's subcomponents' simple connectors
// EMAComponentSymbol componentUsingSubComp = (EMAComponentSymbol) entry.getEnclosingScope()
// .getSpanningSymbol().get();
// connectorSources.addAll(getSourceNames(componentUsingSubComp.getConnectors()));
// }
//
// remainingPorts.removeAll(connectorSources);
// if (!remainingPorts.isEmpty()) {
// remainingPorts.forEach(p -> Log.error(String.format("0xAC006 Port %s is not used!", p)));
// }
//
// // --------- OUT PORTS ----------
// // check that out-ports are connected (i.e. they are targets of connectors)
// // they might be connected using normal connectors (in->out or sub.out->out)
// // or using simple connectors (sub.out->out) (note that simple connectors only allow the
// // subcomponents outgoing ports as source)
//
// remainingPorts = getNames(entry.getOutgoingPorts());
// Collection<String> connectorTargets = getTargetNames(entry.getConnectors());
// // add simple connectors of all subcomponents that might connect the ports.
// entry.getSubComponents()
// .forEach(sc -> connectorTargets.addAll(getTargetNames(sc.getSimpleConnectors())));
//
// remainingPorts.removeAll(connectorTargets);
// if (!remainingPorts.isEmpty()&&node.getSubComponents().size()!=0) {
// remainingPorts.forEach(p -> Log.error(String.format("0xAC007 Port %s is not used!", p),
// node.get_SourcePositionStart()));
// }
// }
// }
//}
/**
*
* ******************************************************************************
* MontiCAR Modeling Family, www.se-rwth.de
* Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
* All rights reserved.
*
* This project 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.0 of the License, or (at your option) any later version.
* This library 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 project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.embeddedmontiarc.cocos;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._cocos.EmbeddedMontiArcASTComponentCoCo;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstantiationSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAConnectorSymbol;
import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
import de.se_rwth.commons.logging.Log;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
/**
* CV6: All ports of subcomponents should be used in at least one connector.<br>
* DIFFERENCE to CV5: CV5 checks that in and out ports are connected <em>within</em> the
* (non-atomic) component itself while CV6 checks that a subcomponent is connected in its
* <em>outer context</em> (i.e. the outer component).
*
* @author ahaber, Robert Heim
*/
public class SubComponentsConnected implements EmbeddedMontiArcASTComponentCoCo {
private Collection<String> getNames(Collection<EMAPortSymbol> ports) {
return ports.stream().map(p -> p.getName())
.collect(Collectors.toList());
}
private Collection<String> getSourceNames(Collection<EMAConnectorSymbol> connectors) {
return connectors.stream().map(c -> c.getSource()).collect(Collectors.toList());
}
private Collection<String> getTargetNames(Collection<EMAConnectorSymbol> connectors) {
return connectors.stream().map(c -> c.getTarget()).collect(Collectors.toList());
}
@Override
public void check(ASTComponent node) {
EMAComponentSymbol entry = (EMAComponentSymbol) node.getSymbolOpt().get();
// Implemented on the symTab as it takes auto-instantiation into account which is not reflected
// in the AST.
for (EMAComponentInstantiationSymbol sub : entry.getSubComponents()) {
// ------- IN PORTS -------
// in ports must be connected
// outer.in->sub.in
// outer.AnySub.out->sub.in
// connectors with sub.in as target occur in outer.connectors or as
// outer.AnySub.simpleconnectors
Collection<String> remainingSubIn = getNames(sub.getComponentType().getIncomingPorts());
// Connectors in the outer context always refer to the ports in a relative-qualified way (e.g.
// sub.portX) and hence we must prefix the remaining ones with sub's name to compare sets of
// relative-qualified names
remainingSubIn = remainingSubIn.stream().map(s -> sub.getName() + "." + s)
.collect(Collectors.toList());
Collection<String> outerConnectorTargets = getTargetNames(entry.getConnectors());
remainingSubIn.removeAll(outerConnectorTargets);
if (!remainingSubIn.isEmpty()) {
Collection<String> outerSubSimpleConnectorTargets = getTargetNames(
entry.getSubComponents().stream()
.flatMap(sc -> sc.getSimpleConnectors().stream()).collect(Collectors.toList()));
remainingSubIn.removeAll(outerSubSimpleConnectorTargets);
if (!remainingSubIn.isEmpty()) {
for (String p : remainingSubIn) {
if (EMAPortSymbol.isConstantPortName(p)) {
} else if(isConfigPort(sub,p)){
//ConfigPorts dont need to be connected!
} else {
Log.error(
String.format("0xAC008 Port %s of subcomponent %s is not used!", p,
sub.getFullName()),
node.get_SourcePositionStart());
}
}
/*
remainingSubIn.forEach(p -> Log.error(
String.format("0xAC008 Port %s of subcomponent %s is not used!", p,
sub.getFullName()),
node.get_SourcePositionStart()));*/
}
}
// ------- OUT PORTS -------
// sub.out->outer.out
// sub.out->outer.AnySub.in
// connectors with sub.out as source occur as outer.connectors or
// outer.AnySub.simpleConnectors
Collection<String> remainingSubOut = getNames(sub.getComponentType().getOutgoingPorts());
// Connectors in the outer context always refer to the ports in a relative-qualified way (e.g.
// sub.portX) and hence we must prefix the remaining ones with sub's name to compare sets of
// relative-qualified names
remainingSubOut = remainingSubOut.stream().map(s -> sub.getName() + "." + s)
.collect(Collectors.toList());
Collection<String> outerConnectorSources = getSourceNames(entry.getConnectors());
remainingSubOut.removeAll(outerConnectorSources);
if (!remainingSubOut.isEmpty()) {
// qualified sources of simple connectors
List<Object> outerSubSimpleConnectorSources = entry.getSubComponents().stream()
.flatMap(sc -> sc.getSimpleConnectors().stream()
// map connector to qualified source name
.map(c -> sc.getName() + "." + c.getSource()))
.collect(Collectors.toList());
remainingSubOut.removeAll(outerSubSimpleConnectorSources);
if (!remainingSubOut.isEmpty()) {
remainingSubOut.forEach(p -> Log.error(
String.format("0xAC009 Port %s of subcomponent %s is not used!", p,
sub.getFullName()),
node.get_SourcePositionStart()));
}
}
}
}
private boolean isConfigPort(EMAComponentInstantiationSymbol instanceSymbol, String relativePortName) {
String[] tmp = relativePortName.split("\\.");
String shortName = tmp[tmp.length - 1];
EMAComponentSymbol comp = instanceSymbol.getComponentType().getReferencedSymbol();
EMAPortSymbol port = comp.getIncomingPort(shortName).orElse(null);
return port == null ? false : port.isConfig();
}
}
///**
// *
// * ******************************************************************************
// * MontiCAR Modeling Family, www.se-rwth.de
// * Copyright (c) 2017, Software Engineering Group at RWTH Aachen,
// * All rights reserved.
// *
// * This project 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.0 of the License, or (at your option) any later version.
// * This library 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 project. If not, see <http://www.gnu.org/licenses/>.
// * *******************************************************************************
// */
//package de.monticore.lang.embeddedmontiarc.cocos;
//
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._ast.ASTComponent;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._cocos.EmbeddedMontiArcASTComponentCoCo;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.instanceStructure.EMAComponentInstantiationSymbol;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAComponentSymbol;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAConnectorSymbol;
//import de.monticore.lang.embeddedmontiarc.embeddedmontiarc._symboltable.cncModel.EMAPortSymbol;
//import de.se_rwth.commons.logging.Log;
//
//import java.util.Collection;
//import java.util.List;
//import java.util.stream.Collectors;
//
///**
// * CV6: All ports of subcomponents should be used in at least one connector.<br>
// * DIFFERENCE to CV5: CV5 checks that in and out ports are connected <em>within</em> the
// * (non-atomic) component itself while CV6 checks that a subcomponent is connected in its