blob: 8894d8dd959a7b612365b0e2d8da7413632aca73 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2012 The University of York.
* This program and the accompanying materials
* are made available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* Contributors:
* Dimitrios Kolovos - initial API and implementation
******************************************************************************/
package org.eclipse.epsilon.egl;
import java.io.File;
import java.net.URI;
import java.util.*;
import org.antlr.runtime.ANTLRInputStream;
import org.antlr.runtime.Lexer;
import org.antlr.runtime.TokenStream;
import org.eclipse.epsilon.common.module.IModule;
import org.eclipse.epsilon.common.module.ModuleElement;
import org.eclipse.epsilon.common.parse.AST;
import org.eclipse.epsilon.common.parse.EpsilonParser;
import org.eclipse.epsilon.common.util.AstUtil;
import org.eclipse.epsilon.egl.dom.GenerationRule;
import org.eclipse.epsilon.egl.execute.context.EgxContext;
import org.eclipse.epsilon.egl.execute.context.IEgxContext;
import org.eclipse.epsilon.egl.parse.EgxLexer;
import org.eclipse.epsilon.egl.parse.EgxParser;
import org.eclipse.epsilon.egl.traceability.Content;
import org.eclipse.epsilon.egl.traceability.Template;
import org.eclipse.epsilon.eol.dom.ExecutableBlock;
import org.eclipse.epsilon.eol.dom.Import;
import org.eclipse.epsilon.eol.exceptions.EolRuntimeException;
import org.eclipse.epsilon.eol.execute.context.IEolContext;
import org.eclipse.epsilon.eol.execute.control.IExecutionListener;
import org.eclipse.epsilon.erl.ErlModule;
import org.eclipse.epsilon.erl.dom.NamedRuleList;
/**
*
* @since 1.6 extends ERL rather than EGL.
*/
public class EgxModule extends ErlModule implements IEgxModule {
protected NamedRuleList<GenerationRule> generationRules;
protected NamedRuleList<GenerationRule> declaredGenerationRules = new NamedRuleList<>();
protected Collection<Content<Template>> invokedTemplates = new ArrayList<>();
public static void main(String[] args) throws Exception {
final EgxModule module = new EgxModule();
module.parse("");
module.getContext().getExecutorFactory().addExecutionListener(new IExecutionListener() {
@Override
public void finishedExecutingWithException(ModuleElement ast,
EolRuntimeException exception, IEolContext context) {}
@Override
public void finishedExecuting(ModuleElement ast, Object result,
IEolContext context) {
if (ast == module) System.out.println("Finished executing.");
}
@Override
public void aboutToExecute(ModuleElement ast, IEolContext context) {
if (ast == module) System.out.println("About to execute ...");
}
});
module.execute();
}
public EgxModule() {
this(new EgxContext());
}
public EgxModule(EglTemplateFactory templateFactory) {
this(new EgxContext(templateFactory));
}
public EgxModule(IEgxContext egxContext) {
this.context = egxContext;
}
@Override
public Collection<Content<Template>> getInvokedTemplates() {
return invokedTemplates;
}
@Override
protected Lexer createLexer(ANTLRInputStream inputStream) {
return new EgxLexer(inputStream);
}
@Override
public EpsilonParser createParser(TokenStream tokenStream) {
return new EgxParser(tokenStream);
}
@Override
public String getMainRule() {
return "egxModule";
}
@Override
public void build(AST cst, IModule module) {
super.build(cst, module);
List<AST> generationRuleChildren = AstUtil.getChildren(cst, EgxParser.GENERATE);
declaredGenerationRules.ensureCapacity(generationRuleChildren.size());
// Parse the transform rules
for (AST generationRuleAst : generationRuleChildren) {
declaredGenerationRules.add((GenerationRule) module.createAst(generationRuleAst, this));
}
getParseProblems().addAll(calculateSuperRules(getGenerationRules()));
}
@Override
public ModuleElement adapt(AST cst, ModuleElement parentAst) {
switch (cst.getType()) {
case EgxParser.GENERATE: return createGenerationRule(cst);
case EgxParser.PARAMETERS: return new ExecutableBlock<>(Map.class);
case EgxParser.TARGET:
case EgxParser.TEMPLATE:
return new ExecutableBlock<>(String.class);
case EgxParser.OVERWRITE:
case EgxParser.GUARD:
case EgxParser.MERGE:
return new ExecutableBlock<>(Boolean.class);
case EgxParser.PRE:
case EgxParser.POST: {
if (parentAst instanceof GenerationRule) {
return new ExecutableBlock<>(Void.class);
}
}
}
return super.adapt(cst, parentAst);
}
/**
* Subclasses may override this method to change the implementation of
* {@link GenerationRule} that is instantiated after parsing an EGX
* program.
*/
protected GenerationRule createGenerationRule(AST generationRuleAst) {
return new GenerationRule();
}
@Override
public List<GenerationRule> getDeclaredGenerationRules() {
return declaredGenerationRules;
}
@Override
public boolean parse(File file) throws Exception {
boolean result = super.parse(file);
if (result) getTemplateFactory().initialiseRoot(file.getAbsoluteFile().getParentFile().toURI());
return result;
}
@Override
public boolean parse(URI uri) throws Exception {
boolean result = super.parse(uri);
if (result) getTemplateFactory().initialiseRoot(uri);
return result;
}
@Override
public boolean parse(String code, File file) throws Exception {
boolean result = super.parse(code, file);
if (result && file != null) getTemplateFactory().initialiseRoot(file.getAbsoluteFile().getParentFile().toURI());
return result;
}
/**
* @since 1.6
*/
@Override
protected void prepareContext() {
super.prepareContext();
getTemplateFactory().getContext().copyFrom(context, true);
}
@Override
public Object executeImpl() throws EolRuntimeException {
prepareExecution();
generateRules(getTemplateFactory());
postExecution();
return null;
}
/**
* Executes all GenerationRules.
*
* @throws EolRuntimeException
* @since 1.6
*/
protected void generateRules(EglTemplateFactory templateFactory) throws EolRuntimeException {
for (GenerationRule rule : getGenerationRules()) {
rule.generateAll(context, templateFactory, this);
}
}
@Override
public HashMap<String, Class<?>> getImportConfiguration() {
HashMap<String, Class<?>> importConfiguration = super.getImportConfiguration();
importConfiguration.put("egx", EgxModule.class);
return importConfiguration;
}
@Override
public IEgxContext getContext() {
return (IEgxContext) context;
}
public void setContext(IEgxContext context) {
this.context = context;
}
@Override
public List<GenerationRule> getGenerationRules() {
if (generationRules == null) {
generationRules = new NamedRuleList<>();
for (Import import_ : imports) {
if (import_.isLoaded() && (import_.getModule() instanceof IEgxModule)) {
IEgxModule module = (IEgxModule) import_.getModule();
generationRules.addAll(module.getGenerationRules());
}
}
generationRules.addAll(declaredGenerationRules);
}
return generationRules;
}
@Override
protected int getPostBlockTokenType() {
return EgxParser.POST;
}
@Override
protected int getPreBlockTokenType() {
return EgxParser.PRE;
}
@Override
public void setContext(IEolContext context) {
if (context instanceof IEgxContext) {
this.context = (IEgxContext) context;
}
}
}