tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceParser.java
changeset 56 aa2539c91954
parent 41 838cdffd57ce
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/tracesrv/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceParser.java	Fri Oct 08 14:56:39 2010 +0300
@@ -0,0 +1,485 @@
+/*
+* Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies). 
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description:
+*
+* Parser for C++ source files
+*
+*/
+package com.nokia.tracecompiler.source;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Parser for C++ source files. Commented and quoted areas are located during
+ * the construction of this object and those areas are excluded from the
+ * searches.
+ * 
+ */
+public class SourceParser {
+
+	/**
+	 * Skip white spaces. Does not apply to string searches
+	 */
+	public final static int SKIP_WHITE_SPACES = 0x01; // CodForChk_Dis_Magic
+
+	/**
+	 * Skip string areas
+	 */
+	public final static int SKIP_STRINGS = 0x02; // CodForChk_Dis_Magic
+
+	/**
+	 * Search / iterate backwards
+	 */
+	public final static int BACKWARD_SEARCH = 0x04; // CodForChk_Dis_Magic
+
+	/**
+	 * Ignore character case in string searches
+	 */
+	public final static int IGNORE_CASE = 0x08; // CodForChk_Dis_Magic
+
+	/**
+	 * Skip commented areas
+	 */
+	public final static int SKIP_COMMENTS = 0x10; // CodForChk_Dis_Magic
+
+	/**
+	 * Skip preprocessor definitions
+	 */
+	public final static int SKIP_PREPROCESSOR = 0x80; // CodForChk_Dis_Magic
+
+	/**
+	 * Match beginning of word flag
+	 */
+	public final static int MATCH_WORD_BEGINNING = 0x20; // CodForChk_Dis_Magic
+
+	/**
+	 * Match end of word flag
+	 */
+	public final static int MATCH_WORD_END = 0x40; // CodForChk_Dis_Magic
+
+	/**
+	 * Match whole word flag
+	 */
+	public final static int MATCH_WHOLE_WORD = MATCH_WORD_BEGINNING
+			| MATCH_WORD_END;
+
+	/**
+	 * Ignore all special areas during search
+	 */
+	public final static int SKIP_ALL = SKIP_WHITE_SPACES | SKIP_STRINGS
+			| SKIP_COMMENTS | SKIP_PREPROCESSOR;
+
+	/**
+	 * Data to be searched.
+	 */
+	private SourceDocumentInterface source;
+
+	/**
+	 * List of source locations
+	 */
+	private ArrayList<SourceLocation> locations;
+
+	/**
+	 * Document factory for creating locations
+	 */
+	private SourceDocumentFactory documentFactory;
+
+	/**
+	 * Excluded area parser
+	 */
+	private ExcludedAreaParser excludedAreaParser;
+
+	/**
+	 * Context area parser
+	 */
+	private ContextAreaParser contextAreaParser;
+
+	/**
+	 * Function return value parser
+	 */
+	private FunctionReturnValueParser returnValueParser;
+
+	/**
+	 * Creates a new parser for given data
+	 * 
+	 * @param factory
+	 *            the document factory
+	 * @param sourceData
+	 *            the source data
+	 */
+	public SourceParser(SourceDocumentFactory factory, String sourceData) {
+		this(factory, factory.createDocument(sourceData));
+	}
+
+	/**
+	 * Creates a source parser from source document
+	 * 
+	 * @param factory
+	 *            the document factory
+	 * @param source
+	 *            the source document
+	 */
+	public SourceParser(SourceDocumentFactory factory,
+			SourceDocumentInterface source) {
+		this.documentFactory = factory;
+		this.source = source;
+		excludedAreaParser = new ExcludedAreaParser(this);
+		contextAreaParser = new ContextAreaParser(this);
+		returnValueParser = new FunctionReturnValueParser(this);
+		try {
+			findExcludedAreas();
+		} catch (SourceParserException e) {
+		}
+	}
+
+	/**
+	 * Gets the source document
+	 * 
+	 * @return the source
+	 */
+	public SourceDocumentInterface getSource() {
+		return source;
+	}
+
+	/**
+	 * Gets part of the source document data
+	 * 
+	 * @param start
+	 *            the start offset
+	 * @param length
+	 *            the data length
+	 * @return the data or null if offsets are not valid
+	 */
+	public String getData(int start, int length) {
+		String retval;
+		try {
+			retval = source.get(start, length);
+		} catch (SourceParserException e) {
+			retval = null;
+		}
+		return retval;
+	}
+
+	/**
+	 * Gets a character at given offset
+	 * 
+	 * @param offset
+	 *            the offset
+	 * @return the character
+	 */
+	public char getData(int offset) {
+		char retval;
+		try {
+			retval = source.getChar(offset);
+		} catch (SourceParserException e) {
+			retval = '\0';
+		}
+		return retval;
+	}
+
+	/**
+	 * Gets the source document length
+	 * 
+	 * @return the source length
+	 */
+	public int getDataLength() {
+		return source.getLength();
+	}
+
+	/**
+	 * Gets the line number of given offset
+	 * 
+	 * @param offset
+	 *            the offset
+	 * @return the line number or -1 if offset is not valid
+	 */
+	public int getLineNumber(int offset) {
+		int retval;
+		try {
+			retval = source.getLineOfOffset(offset) + 1;
+		} catch (SourceParserException e) {
+			retval = -1;
+		}
+		return retval;
+	}
+
+	/**
+	 * Starts a new string search from given offset
+	 * 
+	 * @param searchString
+	 *            the string to be searched
+	 * @param startOffset
+	 *            the offset to start of search
+	 * @param endOffset
+	 *            the end of search or -1 to search the whole document
+	 * @param searchFlags
+	 *            the search flags
+	 * @return the search object
+	 */
+	public SourceStringSearch startStringSearch(String searchString,
+			int startOffset, int endOffset, int searchFlags) {
+		return new SourceStringSearch(this, searchString, startOffset,
+				endOffset, searchFlags);
+	}
+
+	/**
+	 * Tokenizes the parameter list starting from next bracket. White spaces are
+	 * discarded. For example (a, b , c ) returns { "a", "b", "c" }. This method
+	 * is independent of the current string search and thus can be used during
+	 * one.
+	 * 
+	 * @param startIndex
+	 *            the index where to start
+	 * @param list
+	 *            the list where the parameters are added
+	 * @param findSeparator
+	 *            if true, the processing stops after ';' or '{' character. If
+	 *            false, processing stops after ')' at end of parameters
+	 * @return the offset at end of the parameters
+	 * @throws SourceParserException
+	 *             if parameters are not valid
+	 */
+	public int tokenizeParameters(int startIndex, List<String> list,
+			boolean findSeparator) throws SourceParserException {
+		SourceParameterTokenizer tokenizer = new SourceParameterTokenizer(this,
+				startIndex);
+		return tokenizer.tokenize(list, findSeparator);
+	}
+
+	/**
+	 * Parses the parameter list of given source context. Each entry added into
+	 * the list will be an instance of SourceParameter class. This method is
+	 * independent of the current string search and thus can be used during one.
+	 * 
+	 * @param parameterIndex
+	 *            the index where to start
+	 * @param list
+	 *            the list where the parameters are added
+	 * @return the offset at end of the parameters
+	 * @throws SourceParserException
+	 *             if context is not valid
+	 */
+	public int parseFunctionParameters(int parameterIndex, List<SourceParameter> list)
+			throws SourceParserException {
+		SourceParameterTokenizer tokenizer = new SourceParameterTokenizer(this,
+				parameterIndex);
+		return tokenizer.tokenizeTyped(list);
+	}
+
+	/**
+	 * Parses the return values of given source context
+	 * 
+	 * @param context
+	 *            the context to be parsed
+	 * @param list
+	 *            the list of return values
+	 */
+	void parseReturnValues(SourceContext context, List<SourceReturn> list) {
+		returnValueParser.parseReturnValues(context, list);
+	}
+
+	/**
+	 * Checks if the offset if within an excluded area
+	 * 
+	 * @param offset
+	 *            the offset
+	 * @return true if in excluded area
+	 */
+	public boolean isInExcludedArea(int offset) {
+		return findExcludedAreaIndex(offset) >= 0;
+	}
+
+	/**
+	 * Gets an excluded area
+	 * 
+	 * @param offset
+	 *            the data offset
+	 * @return the area or null
+	 */
+	public SourceExcludedArea getExcludedArea(int offset) {
+		return excludedAreaParser.getArea(offset);
+	}
+
+	/**
+	 * Creates a new source iterator
+	 * 
+	 * @param offset
+	 *            the offset where to start
+	 * @param iteratorFlags
+	 *            the flags for the iterator
+	 * @return the new iterator
+	 */
+	public SourceIterator createIterator(int offset, int iteratorFlags) {
+		return new SourceIterator(this, offset, iteratorFlags);
+	}
+
+	/**
+	 * Returns the context at given offset. This parses the source if it has not
+	 * been parsed before.
+	 * 
+	 * @param offset
+	 *            the offset to the source data
+	 * @return the context at the offset or null if no context exists
+	 */
+	public SourceContext getContext(int offset) {
+		SourceContext retval;
+		try {
+			retval = contextAreaParser.parseAndGet(offset);
+		} catch (SourceParserException e) {
+			retval = null;
+		}
+		return retval;
+	}
+
+	/**
+	 * Locates the start-of-line starting from given offset
+	 * 
+	 * @param offset
+	 *            the offset
+	 * @param cancelIfNotWhitespace
+	 *            flag that tells to stop processing and return the original
+	 *            value if a non-whitespace is found before start of line
+	 * @param stayInContext
+	 *            flag that tells to stay within the context offset currently
+	 *            resides. If this would come out of the context, this locates
+	 *            the start of the next line following offset
+	 * @return the start-of-line
+	 * @throws SourceParserException
+	 *             if the offset is not valid
+	 */
+	public int findStartOfLine(int offset, boolean cancelIfNotWhitespace,
+			boolean stayInContext) throws SourceParserException {
+		int retval = offset == 0 ? offset : offset - 1;
+		for (int i = retval; i >= 0; i--) {
+			char c = source.getChar(i);
+			if (source.getChar(i) == '\n') {
+				retval = i + 1;
+				i = -1;
+			} else if (cancelIfNotWhitespace && !Character.isWhitespace(c)) {
+				retval = offset;
+				i = -1;
+			}
+		}
+		if (stayInContext) {
+			SourceContext context = getContext(offset);
+			if (context != null && retval < context.getOffset()) {
+				retval = context.getOffset();
+				int end = context.getOffset() + context.getLength();
+				for (int i = retval; i < end; i++) {
+					if (source.getChar(i) == '\n') {
+						retval = i + 1;
+						i = end;
+					}
+				}
+			}
+		}
+		return retval;
+	}
+
+	/**
+	 * Finds the array index of the excluded area which contains the offset. If
+	 * none of the areas contain the offset, returns negative integer indicating
+	 * the index of the excluded area following the offset
+	 * 
+	 * @param offset
+	 *            the offset to the data
+	 * @return the excluded area index
+	 */
+	int findExcludedAreaIndex(int offset) {
+		return excludedAreaParser.find(offset);
+	}
+
+	/**
+	 * Finds the excluded source file areas. Excluded areas include comments and
+	 * quoted strings. Overwrites possible old areas.
+	 * 
+	 * @throws SourceParserException
+	 *             if parser fails
+	 */
+	public void findExcludedAreas() throws SourceParserException {
+		excludedAreaParser.parseAll();
+	}
+
+	/**
+	 * Gets the list of excluded areas
+	 * 
+	 * @return the list
+	 */
+	public List<SourceExcludedArea> getExcludedAreas() {
+		return excludedAreaParser.getAreas();
+	}
+
+	/**
+	 * Checks if the area is excluded with given flags
+	 * 
+	 * @param type
+	 *            the area type
+	 * @param flags
+	 *            the flags
+	 * @return true if skipped
+	 */
+	static boolean isExcluded(int type, int flags) {
+		boolean string = ((flags & SKIP_STRINGS) != 0)
+				&& (type == SourceExcludedArea.STRING);
+		boolean comment = ((flags & SKIP_COMMENTS) != 0)
+				&& (type == SourceExcludedArea.MULTILINE_COMMENT);
+		boolean linecomment = ((flags & SKIP_COMMENTS) != 0)
+				&& (type == SourceExcludedArea.LINE_COMMENT);
+		boolean preProcessor = ((flags & SKIP_PREPROCESSOR) != 0)
+				&& (type == SourceExcludedArea.PREPROCESSOR_DEFINITION);
+		return string || comment || linecomment || preProcessor;
+	}
+
+	/**
+	 * Adds a location to this parser
+	 * 
+	 * @param location
+	 *            the location
+	 */
+	void addLocation(SourceLocation location) {
+		if (locations == null) {
+			locations = new ArrayList<SourceLocation>();
+		}
+		locations.add(location);
+		if (source != null) {
+			source.addLocation(location.getLocation());
+		}
+	}
+
+	/**
+	 * Removes a location from this parser
+	 * 
+	 * @param location
+	 *            the location to be removed
+	 */
+	void removeLocation(SourceLocation location) {
+		if (locations != null) {
+			locations.remove(location);
+		}
+		if (source != null) {
+			source.removeLocation(location.getLocation());
+		}
+	}
+
+	/**
+	 * Gets the document framework
+	 * 
+	 * @return the document framework
+	 */
+	public SourceDocumentFactory getDocumentFramework() {
+		return documentFactory;
+	}
+
+}