Commit 1bf276d6 authored by Evgeny Kusmenko's avatar Evgeny Kusmenko

Merge branch 'develop' into 'master'

Implemented layer variables and RNN layer

See merge request !23
parents 375a75c1 57bfe101
Pipeline #172292 canceled with stages
......@@ -392,7 +392,14 @@ All predefined methods start with a capital letter and all constructed methods h
Opposite of *Concatenate*. Handles a single input stream and splits it into *n* output streams.
The output streams have the same height and width as the input stream and a number channels which is in general `input_channels / n`.
The last output stream will have a higher number of channels than the other if `input_channels` is not divisible by `n`.
* **n** (integer > 0, required): The number of output streams. Cannot be higher than the number of input channels.
* **OneHot(size)**
Creates a OneHot vector of a given size, given a scalar in the previous layer that determines the OneHot-Index (the index at which the *1* in the vector will be placed).
* **size** (integer > 0, optional): The OneHot-vector's size. Can be omitted to automatically use the output size of the architecture.
......@@ -30,7 +30,7 @@
<groupId>de.monticore.lang.monticar</groupId>
<artifactId>cnn-arch</artifactId>
<version>0.3.1-SNAPSHOT</version>
<version>0.3.2-SNAPSHOT</version>
......
......@@ -56,13 +56,15 @@ grammar CNNArch extends de.monticore.CommonExpressions, de.monticore.lang.Math,
Architecture = methodDeclaration:LayerDeclaration*
instructions:(Instruction || ";")+ ";";
interface Instruction;
Instruction = (LayerVariableDeclaration | Stream);
Stream implements Instruction = elements:(ArchitectureElement || "->")+;
LayerVariableDeclaration = "layer" Layer Name;
Stream = elements:(ArchitectureElement || "->")+;
interface ArchitectureElement;
IOElement implements ArchitectureElement = Name ("[" index:ArchSimpleExpression "]")?;
Variable implements ArchitectureElement = Name ("." (member:"output" | member:Name))? ("[" index:ArchSimpleExpression "]")?;
Constant implements ArchitectureElement = ArchSimpleExpression;
......@@ -77,11 +79,11 @@ grammar CNNArch extends de.monticore.CommonExpressions, de.monticore.lang.Math,
/* ====== Variables/Arguments ======*/
interface Variable;
interface ArchParameter;
ArchitectureParameter implements Variable = Name ("=" default:ArchSimpleExpression)? ;
ArchitectureParameter implements ArchParameter = Name ("=" default:ArchSimpleExpression)? ;
LayerParameter implements Variable = Name ("=" default:ArchSimpleExpression)? ;
LayerParameter implements ArchParameter = Name ("=" default:ArchSimpleExpression)? ;
interface ArchArgument;
......@@ -110,7 +112,7 @@ grammar CNNArch extends de.monticore.CommonExpressions, de.monticore.lang.Math,
(serial2:"->" | parallel2:"|")
end:ArchSimpleExpression "]";
/**
Expressions for variable values.
Expressions for parameter and variable values.
*/
ArchSimpleExpression = (arithmeticExpression:ArchArithmeticExpression
| booleanExpression:ArchBooleanExpression
......@@ -159,7 +161,7 @@ grammar CNNArch extends de.monticore.CommonExpressions, de.monticore.lang.Math,
/* =================================*/
/* ============ ASTRULES ===========*/
/* =================================*/
ast Variable = method String getName(){};
ast ArchParameter = method String getName(){};
ast ArchSpecialArgument = method public String getName(){return "";}; //Override is necessary
ast ArchArgument = method String getName(){}
method ASTArchExpression getRhs(){};
......
/**
*
* ******************************************************************************
* 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.monticar.cnnarch;
import de.monticore.io.paths.ModelPath;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.CNNArchLanguage;
import de.monticore.symboltable.GlobalScope;
import de.monticore.symboltable.Scope;
import de.se_rwth.commons.logging.Log;
import java.io.IOException;
import java.nio.file.Path;
import java.util.Map;
public abstract class CNNArchGenerator {
private String generationTargetPath;
private String modelsDirPath;
public static void quitGeneration(){
Log.error("Code generation is aborted");
System.exit(1);
}
public boolean isCMakeRequired() {
return true;
}
public String getGenerationTargetPath(){
if (generationTargetPath.charAt(generationTargetPath.length() - 1) != '/') {
this.generationTargetPath = generationTargetPath + "/";
}
return generationTargetPath;
}
public void setGenerationTargetPath(String generationTargetPath){
this.generationTargetPath = generationTargetPath;
}
protected String getModelsDirPath() {
return this.modelsDirPath;
}
public void generate(Path modelsDirPath, String rootModelName){
this.modelsDirPath = modelsDirPath.toString();
final ModelPath mp = new ModelPath(modelsDirPath);
GlobalScope scope = new GlobalScope(mp, new CNNArchLanguage());
generate(scope, rootModelName);
}
public abstract boolean check(ArchitectureSymbol architecture);
public abstract void generate(Scope scope, String rootModelName);
//check cocos with CNNArchCocos.checkAll(architecture) before calling this method.
public abstract Map<String, String> generateStrings(ArchitectureSymbol architecture);
//check cocos with CNNArchCocos.checkAll(architecture) before calling this method.
public void generateFiles(ArchitectureSymbol architecture) throws IOException{
Map<String, String> fileContentMap = generateStrings(architecture);
generateFromFilecontentsMap(fileContentMap);
}
public abstract void generateFromFilecontentsMap(Map<String, String> fileContentMap) throws IOException;
public void generateCMake(String rootModelName){
Map<String, String> fileContentMap = generateCMakeContent(rootModelName);
try {
generateFromFilecontentsMap(fileContentMap);
} catch (IOException e) {
Log.error("CMake file could not be generated" + e.getMessage());
}
}
public abstract Map<String, String> generateCMakeContent(String rootModelName);
}
......@@ -67,13 +67,17 @@ public class CNNArchCocos {
.addCoCo(new CheckElementInputs())
.addCoCo(new CheckIOAccessAndIOMissing())
.addCoCo(new CheckArchitectureFinished())
.addCoCo(new CheckNetworkStreamMissing());
.addCoCo(new CheckNetworkStreamMissing())
.addCoCo(new CheckVariableMember())
.addCoCo(new CheckLayerVariableDeclarationLayerType())
.addCoCo(new CheckLayerVariableDeclarationIsUsed());
}
//checks cocos based on symbols before the resolve method of the ArchitectureSymbol is called
public static CNNArchSymbolCoCoChecker createCNNArchPreResolveSymbolChecker() {
return new CNNArchSymbolCoCoChecker()
.addCoCo(new CheckIOName())
.addCoCo(new CheckVariableDeclarationName())
.addCoCo(new CheckVariableName())
.addCoCo(new CheckExpressions());
}
......@@ -82,7 +86,7 @@ public class CNNArchCocos {
return new CNNArchCoCoChecker()
.addCoCo(new CheckLayer())
.addCoCo(new CheckRangeOperators())
.addCoCo(new CheckVariableName())
.addCoCo(new CheckParameterName())
.addCoCo(new CheckLayerName())
.addCoCo(new CheckArgument())
.addCoCo(new CheckLayerRecursion());
......
......@@ -42,8 +42,8 @@ public class CNNArchSymbolCoCo {
else if (sym instanceof ArchTypeSymbol){
check((ArchTypeSymbol) sym);
}
else if (sym instanceof VariableSymbol){
check((VariableSymbol) sym);
else if (sym instanceof ParameterSymbol){
check((ParameterSymbol) sym);
}
else if (sym instanceof ArgumentSymbol){
check((ArgumentSymbol) sym);
......@@ -51,8 +51,8 @@ public class CNNArchSymbolCoCo {
else if (sym instanceof CNNArchCompilationUnitSymbol){
check((CNNArchCompilationUnitSymbol) sym);
}
else if (sym instanceof IODeclarationSymbol){
check((IODeclarationSymbol) sym);
else if (sym instanceof VariableDeclarationSymbol){
check((VariableDeclarationSymbol) sym);
}
else if (sym instanceof MathExpressionSymbol){
check((MathExpressionSymbol) sym);
......@@ -84,7 +84,7 @@ public class CNNArchSymbolCoCo {
//Override if needed
}
public void check(VariableSymbol sym){
public void check(ParameterSymbol sym){
//Override if needed
}
......@@ -96,7 +96,7 @@ public class CNNArchSymbolCoCo {
//Override if needed
}
public void check(IODeclarationSymbol sym){
public void check(VariableDeclarationSymbol sym){
//Override if needed
}
......
......@@ -33,7 +33,7 @@ public class CheckArchitectureFinished extends CNNArchSymbolCoCo {
if (!stream.getOutputTypes().isEmpty()){
Log.error("0" + ErrorCodes.UNFINISHED_ARCHITECTURE + " The architecture is not finished. " +
"There are still open streams at the end of the architecture. "
, architecture.getSourcePosition());
, stream.getSourcePosition());
}
}
if (architecture.getInputs().isEmpty()){
......
......@@ -24,7 +24,7 @@ import de.monticore.lang.math._symboltable.expression.MathExpressionSymbol;
import de.monticore.lang.math._symboltable.expression.MathNameExpressionSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchExpressionSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchSimpleExpressionSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.ParameterSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.monticore.lang.monticar.cnnarch.helper.Utils;
import de.se_rwth.commons.logging.Log;
......@@ -47,11 +47,11 @@ public class CheckExpressions extends CNNArchSymbolCoCo {
for (MathExpressionSymbol subMathExp : Utils.createSubExpressionList(mathExpression)){
if (subMathExp instanceof MathNameExpressionSymbol){
String name = ((MathNameExpressionSymbol) subMathExp).getNameToAccess();
Collection<VariableSymbol> variableCollection = expression.getEnclosingScope().resolveMany(name, VariableSymbol.KIND);
Collection<ParameterSymbol> parameterCollection = expression.getEnclosingScope().resolveMany(name, ParameterSymbol.KIND);
if (variableCollection.isEmpty()){
Log.error("0" + ErrorCodes.UNKNOWN_VARIABLE_NAME + " Unknown variable name. " +
"The variable '" + name + "' does not exist. "
if (parameterCollection.isEmpty()){
Log.error("0" + ErrorCodes.UNKNOWN_PARAMETER_NAME + " Unknown parameter name. " +
"The parameter '" + name + "' does not exist. "
, subMathExp.getSourcePosition());
}
}
......
......@@ -22,7 +22,7 @@ package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IODeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.IOSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.Joiners;
import de.se_rwth.commons.logging.Log;
......@@ -53,7 +53,7 @@ public class CheckIOAccessAndIOMissing extends CNNArchSymbolCoCo {
, ioDeclaration.getSourcePosition());
}
else {
for (IOSymbol ioElement : ioDeclaration.getConnectedElements()){
for (VariableSymbol ioElement : ioDeclaration.getConnectedElements()){
if (ioElement.getArrayAccess().isPresent()){
Log.error("0" + ErrorCodes.INVALID_ARRAY_ACCESS + " Invalid IO array access. " +
"This input or output is not an array."
......@@ -67,7 +67,7 @@ public class CheckIOAccessAndIOMissing extends CNNArchSymbolCoCo {
private void checkIOArray(IODeclarationSymbol ioDeclaration){
List<Integer> unusedIndices = IntStream.range(0, ioDeclaration.getArrayLength()).boxed().collect(Collectors.toList());
for (IOSymbol ioElement : ioDeclaration.getConnectedElements()){
for (VariableSymbol ioElement : ioDeclaration.getConnectedElements()){
if (ioElement.getArrayAccess().isPresent()){
Optional<Integer> arrayAccess = ioElement.getArrayAccess().get().getIntValue();
if (arrayAccess.isPresent() && arrayAccess.get() >= 0 && arrayAccess.get() < ioDeclaration.getArrayLength()){
......
......@@ -46,8 +46,8 @@ public class CheckIOType extends CNNArchSymbolCoCo {
"Type has to be rational or whole number.");
}
if (type.getDimensionSymbols().size() == 2 || type.getDimensionSymbols().size() > 3){
Log.error("0" + ErrorCodes.INVALID_IO_TYPE + " Invalid dimension shape. Shape has to be either of size 1 or 3 (e.g. {number_of_channels, height, width})."
if (type.getDimensionSymbols().size() > 3){
Log.error("0" + ErrorCodes.INVALID_IO_TYPE + " Invalid dimension shape. Shape has to be an tuple either of size 1, 2 or 3 (e.g. {number_of_channels, height, width})."
, ioDeclaration.getSourcePosition());
}
else {
......@@ -60,19 +60,6 @@ public class CheckIOType extends CNNArchSymbolCoCo {
}
}
}
if (Log.getFindings().isEmpty()){
if (ioDeclaration.isInput() && type.getChannels() != 3 && type.getChannels() != 1){
if (type.getHeight() > 1 || type.getWidth() > 1){
Log.warn("The number of channels of input '" +
ioDeclaration.getName() + "' is: " + type.getChannels() +
". Heigth: " + type.getHeight() + ". Width: " + type.getWidth() + ". " +
"This is unusual and a sign of an error. " +
"The standard data format of this language is CHW and not HWC. "
, ioDeclaration.getSourcePosition());
}
}
}
}
}
......@@ -25,7 +25,7 @@ import de.monticore.lang.monticar.cnnarch._ast.ASTLayer;
import de.monticore.lang.monticar.cnnarch._symboltable.ArchitectureSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerDeclarationSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.LayerSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.VariableSymbol;
import de.monticore.lang.monticar.cnnarch._symboltable.ParameterSymbol;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.Joiners;
import de.se_rwth.commons.logging.Log;
......@@ -60,7 +60,7 @@ public class CheckLayer implements CNNArchASTLayerCoCo{
}
else {
Set<String> requiredArguments = new HashSet<>();
for (VariableSymbol param : layerDeclaration.getParameters()){
for (ParameterSymbol param : layerDeclaration.getParameters()){
if (!param.getDefaultExpression().isPresent()){
requiredArguments.add(param.getName());
}
......
......@@ -18,50 +18,44 @@
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch;
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.predefined.AllPredefinedVariables;
import de.monticore.symboltable.Scope;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
import org.junit.Before;
import org.junit.Test;
import static de.monticore.lang.monticar.cnnarch.ParserTest.ENABLE_FAIL_QUICK;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.util.Collection;
public class DataPathConfigParserTest extends AbstractSymtabTest {
public class CheckLayerVariableDeclarationIsUsed extends CNNArchSymbolCoCo {
@Before
public void setUp() {
// ensure an empty log
Log.getFindings().clear();
Log.enableFailQuick(ENABLE_FAIL_QUICK);
}
@Test
public void testDataPathConfigParserValidComponent() {
DataPathConfigParser parser = new DataPathConfigParser("src/test/resources/architectures/data_paths.txt");
@Override
public void check(VariableDeclarationSymbol sym) {
if (sym instanceof LayerVariableDeclarationSymbol) {
LayerVariableDeclarationSymbol layerVariableDeclaration = (LayerVariableDeclarationSymbol) sym;
String data_path = parser.getDataPath("ComponentName");
assertTrue("Wrong data path returned", data_path.equals("/path/to/training/data"));
}
boolean isUsed = false;
@Test
public void testDataPathConfigParserInvalidComponent() {
DataPathConfigParser parser = new DataPathConfigParser("src/test/resources/architectures/data_paths.txt");
for (SerialCompositeElementSymbol stream : layerVariableDeclaration.getLayer().getArchitecture().getStreams()) {
Collection<ArchitectureElementSymbol> elements =
stream.getSpannedScope().resolveMany(layerVariableDeclaration.getName(), ArchitectureElementSymbol.KIND);
String data_path = parser.getDataPath("NotExistingComponent");
assertTrue("For not listed components, null should be returned", data_path == null);
assertTrue(Log.getFindings().size() == 1);
}
for (ArchitectureElementSymbol element : elements) {
if (element instanceof VariableSymbol && ((VariableSymbol) element).getMember() == VariableSymbol.Member.NONE) {
isUsed = true;
break;
}
}
@Test
public void testDataPathConfigParserInvalidPath() {
DataPathConfigParser parser = new DataPathConfigParser("invalid/path/data_paths.txt");
if (isUsed) {
break;
}
}
assertTrue(Log.getFindings().size() == 1);
if (!isUsed) {
Log.error("0" + ErrorCodes.UNUSED_LAYER + " Unused layer. " +
"Declared layer variables need to be used as layer at least once.",
sym.getSourcePosition());
}
}
}
}
/**
*
* ******************************************************************************
* 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.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
public class CheckLayerVariableDeclarationLayerType extends CNNArchSymbolCoCo {
@Override
public void check(VariableDeclarationSymbol sym) {
if (sym instanceof LayerVariableDeclarationSymbol) {
LayerVariableDeclarationSymbol layerVariableDeclaration = (LayerVariableDeclarationSymbol) sym;
// Only allow predefined layers to be declared as layer variable
if (!layerVariableDeclaration.getLayer().getDeclaration().isPredefined()) {
Log.error("0" + ErrorCodes.ILLEGAL_LAYER_USE + " Illegal layer use. " +
"Only predefined layers can be used as a type for a layer variable.",
sym.getSourcePosition());
}
}
}
}
......@@ -29,14 +29,14 @@ public class CheckNetworkStreamMissing extends CNNArchSymbolCoCo {
@Override
public void check(ArchitectureSymbol architecture) {
boolean hasNetworkStream = false;
boolean hasTrainableStream = false;
for (CompositeElementSymbol stream : architecture.getStreams()) {
hasNetworkStream |= stream.isNetwork();
hasTrainableStream |= stream.isTrainable();
}
if (!hasNetworkStream) {
Log.error("0" + ErrorCodes.MISSING_NETWORK_STREAM + " The architecture has no network stream. "
if (!hasTrainableStream) {
Log.error("0" + ErrorCodes.MISSING_TRAINABLE_STREAM + " The architecture has no trainable stream. "
, architecture.getSourcePosition());
}
}
......
/**
*
* ******************************************************************************
* 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.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._ast.ASTLayerParameter;
import de.monticore.lang.monticar.cnnarch._ast.ASTArchParameter;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.monticore.lang.monticar.cnnarch.predefined.AllPredefinedVariables;
import de.monticore.symboltable.Symbol;
import de.se_rwth.commons.logging.Log;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
public class CheckParameterName implements CNNArchASTArchParameterCoCo {
Set<String> parameterNames = new HashSet<>();
@Override
public void check(ASTArchParameter node) {
checkForIllegalNames(node);
checkForDuplicates(node);
}
private void checkForIllegalNames(ASTArchParameter node){
String name = node.getName();
if (name.isEmpty() || !Character.isLowerCase(name.codePointAt(0))){
Log.error("0" + ErrorCodes.ILLEGAL_NAME + " Illegal name: " + name +
". All new parameter and method names have to start with a lowercase letter. "
, node.get_SourcePositionStart());
}
else if (name.equals(AllPredefinedVariables.TRUE_NAME) || name.equals(AllPredefinedVariables.FALSE_NAME)){
Log.error("0" + ErrorCodes.ILLEGAL_NAME + " Illegal name: " + name +
". No parameter can be named 'true' or 'false'"
, node.get_SourcePositionStart());
}
else if (name.equals(AllPredefinedVariables.CONDITIONAL_ARG_NAME.toLowerCase())){
Log.error("0" + ErrorCodes.ILLEGAL_NAME + " Illegal name: " + name +
". No parameter can be named 'if'"
, node.get_SourcePositionStart());
}
}
private void checkForDuplicates(ASTArchParameter node){
String name = node.getName();
if (parameterNames.contains(name)){
if (node instanceof ASTLayerParameter){
Collection<Symbol> allParametersWithSameName = node.getEnclosingScopeOpt().get().getLocalSymbols().get(name);
if (allParametersWithSameName.size() > 1){
duplicationError(node);
}
}
else {
duplicationError(node);
}
}
else{
parameterNames.add(name);
}
}
private void duplicationError(ASTArchParameter node){
Log.error("0" + ErrorCodes.DUPLICATED_NAME + " Duplicated parameter name. " +
"The name '" + node.getName() + "' is already used."
, node.get_SourcePositionStart());
}
}
\ No newline at end of file
......@@ -18,49 +18,36 @@
* License along with this project. If not, see <http://www.gnu.org/licenses/>.
* *******************************************************************************
*/
package de.monticore.lang.monticar.cnnarch;
package de.monticore.lang.monticar.cnnarch._cocos;
import de.monticore.lang.monticar.cnnarch._symboltable.*;
import de.monticore.lang.monticar.cnnarch.helper.ErrorCodes;
import de.se_rwth.commons.logging.Log;
import java.io.*;
import java.net.URL;
import java.util.Objects;
import java.util.Properties;
import java.util.HashSet;
import java.util.Set;
public class DataPathConfigParser{
private String configTargetPath;
private String configFileName;
private Properties properties;
public class CheckVariableDeclarationName extends CNNArchSymbolCoCo {
public DataPathConfigParser(String configPath) {
setConfigPath(configPath);
properties = new Properties();
try
{
properties.load(new FileInputStream(configTargetPath));
} catch(IOException e)
{
Log.error("Config file " + configPath + " could not be found");
}
}
public String getConfigPath() {
if (configTargetPath.charAt(configTargetPath.length() - 1) != '/') {
this.configTargetPath = configTargetPath + "/";
Set<String> variableNames = new HashSet<>();
@Override
public void check(VariableDeclarationSymbol sym) {
String name = sym.getName();
if (name.isEmpty() || name.endsWith("_")) {
Log.error("0" + ErrorCodes.ILLEGAL_NAME + " Illegal variable name. " +
"Variable names cannot end with \"_\"",
sym.getSourcePosition());
}