diff -r 07b41fa8d1dd -r ca8a1b6995f6 tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceParser.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/SourceParser.java Tue Aug 31 16:45:49 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 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 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 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 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 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(); + } + 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; + } + +}