/*
* ******************************************************************************
* MontiCore Language Workbench
* Copyright (c) 2016, MontiCore, 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.grammar.symboltable;
import com.google.common.collect.ImmutableList;
import de.monticore.symboltable.CommonScopeSpanningSymbol;
import de.monticore.symboltable.SymbolKind;
import de.se_rwth.commons.logging.Log;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Optional;
import static java.util.Optional.empty;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
/**
* @author Pedram Mir Seyed Nazari
*/
public class MCProdSymbol extends CommonScopeSpanningSymbol {
public static final MCProdKind KIND = new MCProdKind();
private boolean isStartProd = false;
private boolean isInterface;
private boolean isAbstract;
private boolean isExternal;
private boolean isEnum;
private boolean isLexerProd;
/**
* the producution that defines the symbol kind of the current prod symbol
* (only if isSymbolDefinition is true)
*/
private MCProdSymbolReference prodDefiningSymbolKind = null;
/**
* A extends B, C = ...
*/
private final List<MCProdSymbolReference> superProds = new ArrayList<>();
/**
* A implements B, C = ...
*/
private final List<MCProdSymbolReference> superInterfaceProds = new ArrayList<>();
/**
* A astextends B, C, external.java.Type
*/
private List<MCProdOrTypeReference> astSuperClasses = new ArrayList<>();
/**
* A implements B, C, external.java.Type
*/
private List<MCProdOrTypeReference> astSuperInterfaces = new ArrayList<>();
public MCProdSymbol(String name) {
super(name, KIND);
}
public boolean isStartProd() {
return isStartProd;
}
public void setStartProd(boolean isStartProd) {
this.isStartProd = isStartProd;
}
public boolean isSymbolDefinition() {
return prodDefiningSymbolKind != null;
}
public Optional<String> getSymbolDefinitionKind() {
if (isSymbolDefinition()) {
if (prodDefiningSymbolKind.getReferencedSymbol() == this) {
return of(getName());
}
return prodDefiningSymbolKind.getReferencedSymbol().getSymbolDefinitionKind();
}
return empty();
}
public Optional<MCProdSymbolReference> getProdDefiningSymbolKind() {
return ofNullable(prodDefiningSymbolKind);
}
public void setProdDefiningSymbolKind(MCProdSymbolReference prodDefiningSymbolKind) {
this.prodDefiningSymbolKind = prodDefiningSymbolKind;
}
public MCProdComponentSymbol addProdComponent(MCProdComponentSymbol prodComp) {
Log.errorIfNull(prodComp);
MCProdComponentSymbol prevProdComp = getProdComponent(prodComp.getName()).orElse(null);
if (prevProdComp != null) {
// a prod component is a list (*), if at list one of the prod components
// is a list
prevProdComp.setList(prevProdComp.isList() || prodComp.isList());
return prevProdComp;
}
else {
getMutableSpannedScope().add(prodComp);
}
return prodComp;
}
public Collection<MCProdComponentSymbol> getProdComponents() {
return getSpannedScope().resolveLocally(MCProdComponentSymbol.KIND);
}
public Optional<MCProdComponentSymbol> getProdComponent(String componentName) {
return getSpannedScope().resolveLocally(componentName, MCProdComponentSymbol.KIND);
}
public void addProdAttribute(MCProdAttributeSymbol attributeSymbol) {
Log.errorIfNull(attributeSymbol);
getMutableSpannedScope().add(attributeSymbol);
}
public Collection<MCProdAttributeSymbol> getProdAttributes() {
return getSpannedScope().resolveLocally(MCProdAttributeSymbol.KIND);
}
public Optional<MCProdAttributeSymbol> getProdAttribute(String attributeName) {
return getSpannedScope().resolveLocally(attributeName, MCProdAttributeSymbol.KIND);
}
public void addSuperProd(MCProdSymbolReference superProdRef) {
this.superProds.add(Log.errorIfNull(superProdRef));
}
public List<MCProdSymbolReference> getSuperProds() {
return ImmutableList.copyOf(superProds);
}
public void addSuperInterfaceProd(MCProdSymbolReference superInterfaceProdRef) {
this.superInterfaceProds.add(Log.errorIfNull(superInterfaceProdRef));
}
public List<MCProdSymbolReference> getSuperInterfaceProds() {
return ImmutableList.copyOf(superInterfaceProds);
}
public void addAstSuperClass(MCProdOrTypeReference ref) {
astSuperClasses.add(Log.errorIfNull(ref));
}
public List<MCProdOrTypeReference> getAstSuperClasses() {
return ImmutableList.copyOf(astSuperClasses);
}
public void addAstSuperInterface(MCProdOrTypeReference ref) {
astSuperInterfaces.add(Log.errorIfNull(ref));
}
public List<MCProdOrTypeReference> getAstSuperInterfaces() {
return ImmutableList.copyOf(astSuperInterfaces);
}
/**
* @return true, if production is a class production (which is the default)
*/
public boolean isClass() {
return !isInterface() && !isAbstract() && !isExternal() && !isEnum() && !isLexerProd();
}
public void setInterface(boolean anInterface) {
isInterface = anInterface;
}
public boolean isInterface() {
return isInterface;
}
public void setAbstract(boolean anAbstract) {
isAbstract = anAbstract;
}
public boolean isAbstract() {
return isAbstract;
}
public void setExternal(boolean external) {
isExternal = external;
}
public boolean isExternal() {
return isExternal;
}
public void setEnum(boolean anEnum) {
isEnum = anEnum;
}
public boolean isEnum() {
return isEnum;
}
public boolean isParserProd() {
return isClass() || isAbstract();
}
public void setLexerProd(boolean lexerProd) {
isLexerProd = lexerProd;
}
public boolean isLexerProd() {
return isLexerProd;
}
public static class MCProdKind implements SymbolKind {
private static final String NAME = MCProdKind.class.getName();
protected MCProdKind() {
}
@Override
public String getName() {
return NAME;
}
@Override
public boolean isKindOf(SymbolKind kind) {
return NAME.equals(kind.getName()) || SymbolKind.super.isKindOf(kind);
}
}
}