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

org.eclipse.ocl.lpg.AbstractAnalyzer Maven / Gradle / Ivy

/*******************************************************************************
 * Copyright (c) 2005, 2012 IBM Corporation, Zeligsoft Inc., and others.
 * All rights reserved.   This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 * 
 * Contributors: 
 *   IBM - Initial API and implementation
 *   E.D.Willink - refactored to separate from OCLAnalyzer and OCLParser
 *       - Bug 259818
 *******************************************************************************/
package org.eclipse.ocl.lpg;

import java.io.IOException;
import java.io.Reader;
import java.util.List;

import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.ocl.cst.CSTNode;
import org.eclipse.ocl.internal.OCLPlugin;
import org.eclipse.ocl.utilities.ASTNode;
import org.eclipse.ocl.utilities.CallingASTNode;
import org.eclipse.ocl.utilities.TypedASTNode;

/**
 * The AbstractAnalyzer supports semantic analysis of a CST
 * produced by an AbstractParser to create a corresponding AST. It
 * is necessary that syntactic parsing and semantic analysis are performed in
 * two steps because LPG is a bottom up parser and cannot provide enough
 * contextual information to create the AST on the first pass.
 * 
 * Derived classes should extend the abstract support for AST from CST from
 * tokens from text parsing and analysis to support the AST and CST classes
 * appropriate to a particular language.
 */
public abstract class AbstractAnalyzer {

	private final AbstractParser parser; // The parser that provides CST and
											// source text

	private final BasicEnvironment environment; // The symbol lookup, problem
												// handling context

	private FormattingHelper formatter = null; // The message formatting
												// assistant

	private boolean traceflag = false; // Optional AST tracing for debug

	private int charOffset = 0; // Optional offset applied to reported text to
								// hide

	// extra surrounding context

	protected AbstractAnalyzer(AbstractParser parser) {
		this.parser = parser;
		this.environment = parser.getEnvironment();
	}

	/**
	 * Obtains the text from which the specified CST node was
	 * parsed.
	 * 
	 * @param node
	 *            a concrete syntax node
	 * 
	 * @return its text
	 */
	public String computeInputString(CSTNode node) {
		return getAbstractParser().computeInputString(node.getStartOffset(),
			node.getEndOffset());
	}

	public void dumpTokens() {
		parser.getIPrsStream().dumpTokens();
	}

	public String formatClass(Object object) {
		return getFormatter().formatClass(object);
	}

	public String formatEClassName(EObject object) {
		return getFormatter().formatEClassName(object);
	}

	public String formatName(Object object) {
		return getFormatter().formatName(object);
	}

	public String formatQualifiedName(Object object) {
		return getFormatter().formatQualifiedName(object);
	}

	public String formatPath(List pathName) {
		return getFormatter().formatPath(pathName);
	}

	public String formatPath(List pathName, String name) {
		return getFormatter().formatPath(pathName, name);
	}

	public String formatString(String string) {
		return getFormatter().formatString(string);
	}

	public String formatType(Object object) {
		return getFormatter().formatType(object);
	}

	/**
	 * Obtains the parser that I use to transform the OCL text into the Concrete
	 * Syntax Model.
	 * 
	 * @since 1.3
	 */
	public AbstractParser getAbstractParser() {
		return parser;
	}

	public int getCharOffset() {
		return charOffset;
	}

	public BasicEnvironment getEnvironment() {
		return environment;
	}

	/**
	 * Get the message formatting assistant, returning the value set by
	 * setFormatter, if non-null, else that provided by the environment, if
	 * non-null, else AbstractFormattingHelper.INSTANCE.
	 * 
	 * @return A non-null message formatting helper
	 */
	public FormattingHelper getFormatter() {
		if (formatter == null) {
			BasicEnvironment environment = getEnvironment();
			if (environment != null) {
				formatter = environment.getFormatter();
			}
			if (formatter == null) {
				formatter = AbstractFormattingHelper.INSTANCE;
			}
		}
		return formatter;
	}

	public AbstractLexer getLexer() {
		return getAbstractParser().getLexer();
	}

	/**
	 * Obtains my parser.
	 * 
	 * @return my parser
	 * 
	 * @deprecated Since 1.3, use the {@link #getAbstractParser()} method,
	 *             instead.
	 */
	@Deprecated
	public AbstractParser getParser() {
		return parser;
	}

	public boolean getTraceFlag() {
		return traceflag;
	}

	/**
	 * Initializes the start and end positions of the property name in the
	 * specified calling AST node.
	 * 
	 * @param callingASTNode
	 *            a calling AST node
	 * @param cstNode
	 *            a CST node
	 */
	protected void initPropertyPositions(CallingASTNode callingASTNode,
			CSTNode cstNode) {
		callingASTNode.setPropertyStartPosition(cstNode.getStartOffset()
			+ charOffset);
		callingASTNode.setPropertyEndPosition(cstNode.getEndOffset()
			+ charOffset + 1);
		// +1 because end offset is exclusive
	}

	/**
	 * Initializes the start and end positions of the specified AST node from
	 * the given CST node
	 * 
	 * @param astNode
	 *            an AST node
	 * @param cstNode
	 *            a CST node
	 */
	protected void initStartEndPositions(ASTNode astNode, CSTNode cstNode) {
		if ((astNode != null) && (cstNode != null)) {
			// initASTMapping(astNode, cstNode);
			astNode.setStartPosition(cstNode.getStartOffset() + charOffset);
			astNode.setEndPosition(cstNode.getEndOffset() + charOffset + 1);
			// +1 because end offset is exclusive
		}
	}

	/**
	 * Initializes the type start and end positions of the specified typed AST
	 * node from the given CST node
	 * 
	 * @param typedASTNode
	 *            a typed AST node
	 * @param cstNode
	 *            a CST node
	 */
	protected void initTypePositions(TypedASTNode typedASTNode, CSTNode cstNode) {
		if ((typedASTNode != null) && (cstNode != null)) {
			// if (typedASTNode instanceof TypedElement)
			// initASTMapping(((TypedElement)typedASTNode).getType(), cstNode);
			// else if (typedASTNode instanceof CollectionType)
			// initASTMapping(((CollectionType)typedASTNode).getElementType(),
			// cstNode);
			typedASTNode.setTypeStartPosition(cstNode.getStartOffset()
				+ charOffset);
			typedASTNode.setTypeEndPosition(cstNode.getEndOffset() + charOffset
				+ 1);
			// +1 because end offset is exclusive
		}
	}

	/**
	 * Creates a string by joining the given string list elements with ::.
	 * 
	 * @param namelist
	 *            list of names to make string out of
	 * @return the qualified name comprising the list of name elements
	 */
	protected String makeName(EList namelist) {
		StringBuilder msg = new StringBuilder();
		for (int i = 0; i < namelist.size(); i++) {
			if (i > 0) {
				msg.append("::");//$NON-NLS-1$
			}
			msg.append(namelist.get(i));
		}
		return msg.toString();
	}

	/**
	 * Creates a string by joining the given string list elements with spaces.
	 * 
	 * @param namelist
	 *            list of names to make string out of
	 * @return string representation of the list of string elements
	 */
	protected String makeString(EList namelist) {
		StringBuilder s = new StringBuilder();
		for (int i = 0; i < namelist.size(); i++) {
			if (i > 0) {
				s.append(" ");		//$NON-NLS-1$
			}
			s.append(namelist.get(i));
		}
		return s.toString();
	}

	/**
	 * Sets the character index offset of the input.
	 * 
	 * @param offset
	 */
	public void setCharacterOffset(int offset) {
		charOffset = offset;
	}

	public void setFileName(String filename) {
		getLexer().getILexStream().setFileName(filename);
	}

	/**
	 * Define the input text as a given array of characters.
	 * 
	 * @param buffer
	 *            the characters
	 * 
	 * @deprecated clients should invoke {@link #reset(char[], String)}
	 */
	@Deprecated
	public void initialize(char[] buffer) {
		reset(buffer, null);
	}

	/**
	 * Define the input text by reading from a reader.
	 * 
	 * @param reader
	 *            providing the source text
	 * @throws IOException
	 *             if reading fails
	 * 
	 * @deprecated clients should invoke {@link #reset(Reader, String)}
	 */
	@Deprecated
	public void initialize(Reader reader)
			throws IOException {
		reset(reader, null);
	}
	
	/**
	 *  Define the input text as a given array of characters.
     *
	 * @param buffer
	 *            the characters
	 * @param fileName
     *            the associated finleName of the input, or null if none.
	 * @since 3.0
	 */
	public void reset(char[] buffer, String fileName) {
		getLexer().reset(buffer, fileName);
	}

	/**
	 * Define the input text by reading from a reader.
	 * 
	 * @param reader
	 *            providing the source text
	 * @param fileName
     *            the associated finleName of the input, or null if none.
	 * @throws IOException
	 *             if reading fails
	 * @since 3.0
	 */
	public void reset(Reader reader, String fileName) throws IOException {
		AbstractLexer lexer = getLexer();
		lexer.reset(reader, fileName);
		AbstractParser parser = getAbstractParser();
		if (parser.getIPrsStream() == null) {
			parser.reset(lexer.getILexStream());
		}
	}

	public void setTab(int tab) {
		getLexer().getILexStream().setTab(tab);
	}

	public void setTraceFlag(boolean flag) {
		traceflag = flag;
	}

	public void ERROR(String problemMessage) {
		getEnvironment().utilityError(problemMessage, null, null);
	}

	public void ERROR(Object problemObject, String rule, String problemMessage) {
		getEnvironment().analyzerError(problemMessage, rule, problemObject);
	}

	public void ERROR(List problemObjects, String rule, String problemMessage) {
		getEnvironment().analyzerError(problemMessage, rule, problemObjects);
	}

	protected void TRACE(String rule, String message) {
		if (traceflag) {
			OCLPlugin.trace(rule + ": " + message);//$NON-NLS-1$
		}
	}

	protected void TRACE(String rule, String message, EList namelist) {
		TRACE(rule, message + makeString(namelist));
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy