All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.eclipse.epsilon.egl.EgxModule Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2012-2022 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
 *     Sina Madani - refactoring
 *     Antonio Garcia-Dominguez - Add support for customising the formatter
 ******************************************************************************/
package org.eclipse.epsilon.egl;

import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

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.debug.EgxDebugger;
import org.eclipse.epsilon.egl.dom.GenerationRule;
import org.eclipse.epsilon.egl.exceptions.EglRuntimeException;
import org.eclipse.epsilon.egl.execute.context.EgxContext;
import org.eclipse.epsilon.egl.execute.context.IEgxContext;
import org.eclipse.epsilon.egl.formatter.Formatter;
import org.eclipse.epsilon.egl.parse.EgxLexer;
import org.eclipse.epsilon.egl.parse.EgxParser;
import org.eclipse.epsilon.eol.debug.EolDebugger;
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.ExecutorFactory;
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 generationRules;
	protected NamedRuleList declaredGenerationRules = new NamedRuleList<>();
	
	public EgxModule() {
		this((IEgxContext) null);
	}
	
	/**
	 * Calls {@link #EgxModule(Path)}.
	 * 
	 * @param outputRoot
	 * @throws EglRuntimeException
	 * @since 1.6
	 * @see #EgxModule(Path)
	 */
	public EgxModule(String outputRoot) throws EglRuntimeException {
		this(Paths.get(outputRoot));
	}
	
	/**
	 * Instantiates the module and the context configured for outputting generated files
	 * to the specified directory.
	 * 
	 * @param outputRoot The base location to send output files to.
	 * @throws EglRuntimeException If the path could not be resolved.
	 * @since 1.6
	 */
	public EgxModule(Path outputRoot) throws EglRuntimeException {
		this();
		setFileGeneratingTemplateFactory(outputRoot);
	}
	
	/**
	 * Instantiates the module with the specified execution context.
	 * @param context The execution context
	 */
	public EgxModule(IEgxContext context) {
		super(context != null ? context : new EgxContext());
	}
	
	public EgxModule(EglTemplateFactory templateFactory) {
		this(new EgxContext(templateFactory));
	}
	
	/**
	 * Convenience method for initialising a {@link EglFileGeneratingTemplateFactory} with
	 * the specified output path.
	 * 
	 * @param outputRoot
	 * @throws EglRuntimeException
	 * @since 1.6
	 */
	protected void setFileGeneratingTemplateFactory(Path outputRoot) throws EglRuntimeException {
		getContext().setTemplateFactory(new EglFileGeneratingTemplateFactory(outputRoot.toAbsolutePath()));
	}
	
	@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 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.DOMAIN: return new ExecutableBlock<>(Collection.class);
			case EgxParser.TARGET:
			case EgxParser.TEMPLATE:
				return new ExecutableBlock<>(String.class);
			case EgxParser.OVERWRITE:
			case EgxParser.GUARD:
			case EgxParser.MERGE:
			case EgxParser.APPEND:
			case EgxParser.PATCH:
				return new ExecutableBlock<>(Boolean.class);
			case EgxParser.FORMATTER:
				return new ExecutableBlock<>(Formatter.class);
			case EgxParser.PRE:
			case EgxParser.POST: {
				if (parentAst instanceof GenerationRule) {
					return new ExecutableBlock<>(Void.class);
				}
			}
			default: 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 getDeclaredGenerationRules() {
		return declaredGenerationRules;
	}
	
	@Override
	public boolean parse(File file) throws Exception {
		boolean result = super.parse(file);
		if (result) getContext().getTemplateFactory().initialiseRoot(file.getAbsoluteFile().getParentFile().toURI());
		return result;
	}
	
	@Override
	public boolean parse(URI uri) throws Exception {
		boolean result = super.parse(uri);
		if (result) getContext().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) getContext().getTemplateFactory().initialiseRoot(file.getAbsoluteFile().getParentFile().toURI());
		return result;
	}
	
	@Override
	protected Object processRules() throws EolRuntimeException {
		IEgxContext context = getContext();
		ExecutorFactory executorFactory = context.getExecutorFactory();
		for (GenerationRule rule : getGenerationRules()) {
			executorFactory.execute(rule, context);
		}
		return null;
	}
	
	@Override
	public HashMap> getImportConfiguration() {
		HashMap> importConfiguration = super.getImportConfiguration();
		importConfiguration.put("egx", EgxModule.class);
		return importConfiguration;
	}
	
	@Override
	public List 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
	public IEgxContext getContext() {
		return (IEgxContext) super.getContext();
	}

	@Override
	public EolDebugger createDebugger() {
		return new EgxDebugger();
	}
	
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy