diff -r ca8a1b6995f6 -r 52e343bb8f80 tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/ContextAreaParser.java --- a/tracefw/tracecompiler/src/com.nokia.tracecompiler/src/com/nokia/tracecompiler/source/ContextAreaParser.java Tue Aug 31 16:45:49 2010 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,521 +0,0 @@ -/* -* Copyright (c) 2008 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 source contexts -* -*/ -package com.nokia.tracecompiler.source; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; - -/** - * Parser for source contexts - * - */ -class ContextAreaParser { - - /** - * Source parser - */ - private SourceParser parser; - - /** - * List of source file contexts - */ - protected ArrayList contextAreas = new ArrayList(); - - /** - * Comparator for array sorting and searching - */ - private PositionArrayComparator arrayComparator = new PositionArrayComparator(); - - /** - * "usingnamespace" text - */ - private static final String USINGNAMESPACE = "usingnamespace"; //$NON-NLS-1$ - - /** - * Start index of "using" substring in "usingnamespace" string - */ - private static final int START_INDEX_OF_USING_SUBSTRING = 0; // CodForChk_Dis_Magic - - /** - * End index of "using" substring in "usingnamespace" string - */ - private static final int END_INDEX_OF_USING_SUBSTRING = 5; // CodForChk_Dis_Magic - - /** - * Start index of "namespace" substring in "usingnamespace" string - */ - private static final int START_INDEX_OF_NAMESPACE_SUBSTRING = 5; // CodForChk_Dis_Magic - - /** - * End index of "namespace" substring in "usingnamespace" string - */ - private static final int END_INDEX_OF_NAMESPACE_SUBSTRING = 14; // CodForChk_Dis_Magic - - /** - * Constructor - * - * @param parser - * the source parser - */ - ContextAreaParser(SourceParser parser) { - this.parser = parser; - } - - /** - * Resets the context areas - */ - void reset() { - contextAreas.clear(); - } - - /** - * Returns the context at given offset - * - * @param offset - * the offset to the source data - * @return the context at the offset or null if no context exists - * @throws SourceParserException - * if parser fails - */ - SourceContext parseAndGet(int offset) throws SourceParserException { - if (contextAreas.isEmpty()) { - parseAll(); - } - int index = find(offset); - SourceContext context = null; - if (index >= 0) { - context = contextAreas.get(index); - } - return context; - } - - /** - * Gets the context areas. If the areas have not been parsed, this parses - * them - * - * @return the areas - * @throws SourceParserException - * if parser fails - */ - Iterator parseAndGetAll() throws SourceParserException { - if (contextAreas.isEmpty()) { - parseAll(); - } - return contextAreas.iterator(); - } - - /** - * Gets the context area list. This does not parse the areas - * - * @return the list of context areas - */ - List getContextList() { - return contextAreas; - } - - /** - * Finds the array index of the context area which contains the offset. If - * none of the areas contain the offset, returns negative integer indicating - * the index of the context area following the offset - * - * @param offset - * the offset to the data - * @return the context area index - */ - int find(int offset) { - return Collections.binarySearch(contextAreas, new SourceLocationBase( - parser, offset), arrayComparator); - } - - /** - * Builds the context array - * - * @throws SourceParserException - * if parser fails - */ - void parseAll() throws SourceParserException { // CodForChk_Dis_ComplexFunc - contextAreas.clear(); - char value; - - int inBrackets = 0; - int inContext = 0; - int inNamespace = 0; - - int usingIndex = START_INDEX_OF_USING_SUBSTRING; - int usingKeywordEnd = 0; - int namespaceIndex = START_INDEX_OF_NAMESPACE_SUBSTRING; - int nameSpaceKeywordEnd = 0; - int previousIndexBeforeNamespace = 0; - boolean checkNextCharacter = false; - - SourceContext context = null; - SourceIterator itr = parser.createIterator(0, SourceParser.SKIP_ALL); - - while (itr.hasNext()) { - value = itr.next(); - - // Next character check is need only if we have found "namespace" - // text - if (checkNextCharacter) { - - // Next character after "namespace" text should be space. - // Because we have skipped spaces, current index should be - // bigger than nameSpaceKeywordEnd + 1. If it is not space then - // we are not inside namespace - if (itr.currentIndex() - nameSpaceKeywordEnd < 2) { // CodForChk_Dis_Magic - inNamespace--; - } - checkNextCharacter = false; - } - - // Check is character part of "using" text - if (value == USINGNAMESPACE.charAt(usingIndex)) { - usingIndex++; - } else { - - // Character not part of "using" text -> reset usingIndex - usingIndex = START_INDEX_OF_USING_SUBSTRING; - } - - // Check that did we found "using" text - if (usingIndex == END_INDEX_OF_USING_SUBSTRING) { - usingKeywordEnd = itr.currentIndex(); - usingIndex = START_INDEX_OF_USING_SUBSTRING; - } - - // Check is character part of "namespace" text - if (value == USINGNAMESPACE.charAt(namespaceIndex)) { - if (previousIndexBeforeNamespace == 0) { - previousIndexBeforeNamespace = itr.previousIndex(); - } - namespaceIndex++; - } else { - - // Character not part of "namespace" text -> reset - // previousIndexBeforeNamespace and namespaceIndex - previousIndexBeforeNamespace = 0; - namespaceIndex = START_INDEX_OF_NAMESPACE_SUBSTRING; - } - - // Check that did we found "namespace" text - if (namespaceIndex == END_INDEX_OF_NAMESPACE_SUBSTRING) { - nameSpaceKeywordEnd = itr.currentIndex(); - - // If there was "using" text just before "namespace" text, then - // namespace is defined like: "using namespace foo;" and we are - // not going inside namespace brackets - if (usingKeywordEnd != previousIndexBeforeNamespace) { - inNamespace++; - checkNextCharacter = true; - } - namespaceIndex = START_INDEX_OF_NAMESPACE_SUBSTRING; - } - - if (value == '{') { - inBrackets++; - - // Check that are we inside namespace or context - if (inBrackets > inNamespace) { - inContext++; - if (inContext == 1) { - int start = itr.currentIndex() + 1; - context = new SourceContext(parser, start); - - // Includes the '{' character into the context - if (!createContext(context, start - 2)) { // CodForChk_Dis_Magic - context = null; - } - } - } - } else if (value == '}') { - // Check that are we exiting from context or namespace - if (inBrackets == inNamespace) { - inNamespace--; - } else { - inContext--; - if (inContext == 0 && context != null) { - context.setLength(itr.currentIndex() + 1 - - context.getOffset()); - contextAreas.add(context); - } - } - - inBrackets--; - } - } - } - - /** - * Sets the data to the source context - * - * @param context - * the source context to be updated - * @param offset - * the index preceeding the '{' character - * @return true if valid, false otherwise - * @throws SourceParserException - * if processing fails - */ - private boolean createContext(SourceContext context, int offset) - throws SourceParserException { - ContextSearchData data = new ContextSearchData(); - data.itr = parser.createIterator(offset, SourceParser.BACKWARD_SEARCH - | SourceParser.SKIP_ALL); - data.context = context; - while (data.itr.hasNext() && !data.finished) { - char c = data.itr.next(); - // Function start or stop character or statement separator breaks - // the search in normal case. In case of nested class separator - // character breaks the search. - if (c == ';' || c == '}' || c == '{' - || (c == ':' && data.itr.peek() == ':') - && data.classStartIndex != -1) { - processContextTerminator(context, data, false); - } else if (!data.parametersFound) { - processParametersNotFoundCharacter(data, c); - } else if (c == ')' || c == '(' || c == ',' - || (c == ':' && data.itr.peek() != ':')) { - // Constructor member initializer list may contain brackets, ',' - // and ':'. When one of the characters from member initializer - // list is encountered, this assumes that the previous - // one was not the actual function parameter list yet. All - // variables are reset in that case - data.parametersFound = false; - data.functionEndIndex = -1; - data.functionStartIndex = -1; - data.classEndIndex = -1; - processParametersNotFoundCharacter(data, c); - } else if (data.functionEndIndex == -1) { - processFunctionNameNotFoundCharacter(data, c); - } else if (data.functionStartIndex == -1) { - processFunctionNameCharacter(context, data, c); - } else if (data.classEndIndex == -1) { - processClassNameNotFoundCharacter(data); - } else if (data.classStartIndex == -1) { - processClassNameCharacter(context, data, c); - } else { - processReturnTypeCharacter(context, data); - } - } - if (!data.finished) { - processContextTerminator(context, data, true); - } - return data.valid; - } - - /** - * Processes a character after class and function names have been found - * - * @param context - * the context - * @param data - * the search data - * @throws SourceParserException - * if processing fails - */ - private void processReturnTypeCharacter(SourceContext context, - ContextSearchData data) throws SourceParserException { - if (data.itr.hasSkipped()) { - // Collects all return type candidates to the context - addReturnType(context, data.itr.previousIndex(), - data.returnEndIndex); - data.returnEndIndex = data.itr.currentIndex(); - } - } - - /** - * Processes a character after function name has been found, but class name - * has not yet been found - * - * @param data - * the search flags - */ - private void processClassNameNotFoundCharacter(ContextSearchData data) { - // After start of function and the separator has been found, the - // next character marks the end of class name - data.classEndIndex = data.itr.currentIndex() + 1; - } - - /** - * Parses a character which belongs to the class name - * - * @param context - * the source context to be parsed - * @param data - * the context search parameters - * @param c - * the character - * @throws SourceParserException - * if processing fails - */ - private void processClassNameCharacter(SourceContext context, - ContextSearchData data, char c) throws SourceParserException { - if (data.itr.hasSkipped() || (c == ':' && data.itr.peek() == ':')) { - // Start of class name is found when iterator skips over - // white space or comment characters or in case of nested class - // separator character has been found - context.setFunctionName(parser.getSource().get( - data.functionStartIndex, - data.functionEndIndex - data.functionStartIndex)); - data.classStartIndex = data.itr.previousIndex(); - data.returnEndIndex = data.itr.currentIndex(); - context.setClassName(parser.getSource().get(data.classStartIndex, - data.classEndIndex - data.classStartIndex)); - - // In case of nested class skips over the second ':' - if (c == ':' && data.itr.peek() == ':') { - data.itr.next(); - } - } - } - - /** - * Processes a character while within function name - * - * @param context - * the source context under processing - * @param data - * the context search flags - * @param c - * the character - * @throws SourceParserException - * if processing fails - */ - private void processFunctionNameCharacter(SourceContext context, - ContextSearchData data, char c) throws SourceParserException { - // After end of function has been found the separator character - // marks the start of function - if (c == ':') { - if (data.itr.hasNext() && data.itr.peek() == ':') { - data.functionStartIndex = data.itr.previousIndex(); - context.setFunctionName(parser.getSource().get( - data.functionStartIndex, - data.functionEndIndex - data.functionStartIndex)); - // Skips over the second ':' - data.itr.next(); - } else { - // Only one ':' character -> Invalid - data.finished = true; - } - } else if (data.itr.hasSkipped()) { - // If the iterator skipped over some characters and the next - // character is not ':' the function is a non-member - data.functionStartIndex = data.itr.previousIndex(); - context.setFunctionName(parser.getSource().get( - data.functionStartIndex, - data.functionEndIndex - data.functionStartIndex)); - // Class name indices are set so parser does not search for them - data.classStartIndex = data.itr.previousIndex(); - data.classEndIndex = data.itr.previousIndex(); - data.returnEndIndex = data.itr.currentIndex(); - } - } - - /** - * Processes a character when function name has not yet been found - * - * @param data - * the search flags - * @param c - * the character to be processed - */ - private void processFunctionNameNotFoundCharacter(ContextSearchData data, - char c) { - // The next character after parameters is the end of function - if (c == ':') { - data.finished = true; - } - data.functionEndIndex = data.itr.currentIndex() + 1; - } - - /** - * Checks if the character is '(' or ')' and updates the parametersFound - * flag accordingly - * - * @param data - * the search data - * @param c - * the current character - */ - private void processParametersNotFoundCharacter(ContextSearchData data, - char c) { - if (c == ')') { - data.inParameters++; - } else if (c == '(') { - data.inParameters--; - if (data.inParameters == 0) { - data.context.setParametersStartIndex(data.itr.currentIndex()); - data.parametersFound = true; - } - } - } - - /** - * Processes a context terminating character - * - * @param context - * the context under processing - * @param data - * the search data - * @param startOfFile - * context was terminated due to start of file - * @throws SourceParserException - * if processing fails - */ - private void processContextTerminator(SourceContext context, - ContextSearchData data, boolean startOfFile) - throws SourceParserException { - int offset = startOfFile ? data.itr.currentIndex() : data.itr - .previousIndex(); - if (data.classStartIndex != -1) { - addReturnType(context, offset, data.returnEndIndex); - data.valid = true; - } else if (data.classEndIndex != -1) { - context.setClassName(parser.getSource().get(offset, - data.classEndIndex - offset)); - data.valid = true; - } else if (data.functionEndIndex != -1) { - context.setFunctionName(parser.getSource().get(offset, - data.functionEndIndex - offset)); - data.valid = true; - } - // Finished flag is set. If function name was not found, the valid flag - // remains false - data.finished = true; - } - - /** - * Adds a return type to the context - * - * @param context - * the context to be searched - * @param start - * the start index - * @param end - * the end index - * @throws SourceParserException - * if return type cannot be added - */ - private void addReturnType(SourceContext context, int start, int end) - throws SourceParserException { - context.addReturnType(parser.getSource().get(start, end - start + 1)); - } -}