| /******************************************************************************* |
| * Copyright (c) 2001, 2005 IBM Corporation 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 Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.jem.internal.proxy.initParser; |
| /* |
| |
| |
| */ |
| |
| |
| import java.util.ArrayList; |
| /** |
| * Insert the type's description here. |
| * Creation date: (11/01/00 8:53:45 PM) |
| * @author: Administrator |
| */ |
| public class InitializationStringParser implements IParserConstants { |
| protected ClassLoader fClassLoader; |
| protected boolean isComplete = false; |
| protected String fInitString; |
| protected int fSourceLength; |
| protected char[] fSource; |
| protected int fSourcePosition = -1; |
| private char[] fCurrentToken; |
| private char fCurrentTokenDelimiter = 0; |
| protected ArrayList fExpressionStack = new ArrayList(4); |
| protected Expression fExpression; |
| /** |
| * InitializationStringParser constructor comment. |
| */ |
| public InitializationStringParser(String initString){ |
| |
| fInitString = initString; |
| fSource = initString.toCharArray(); |
| fSourceLength = fSource.length; |
| |
| } |
| /** Look for a known token |
| */ |
| protected void createNextToken(){ |
| |
| fCurrentTokenDelimiter = 0; |
| if ( fSourcePosition >= fSourceLength - 1 ) { |
| isComplete = true; |
| return; |
| } |
| |
| fSourcePosition++; |
| // If we are not in a token then look for " " or else for a period |
| char[] fCurrentTokenSource = new char[fSourceLength]; |
| int i = 0; |
| scanner : for ( ; fSourcePosition < fSourceLength ; fSourcePosition++ , i++ ){ |
| // Advance the source position so when finding the next token we skip over the '.' or ' ' |
| // Record the delimiter that was found |
| switch ( fSource[fSourcePosition] ) { |
| case DelimiterPeriod: { |
| fCurrentTokenDelimiter = DelimiterPeriod; |
| break scanner; |
| } |
| case DelimiterOpenParen: { |
| fCurrentTokenDelimiter = DelimiterOpenParen; |
| break scanner; |
| } |
| case DelimiterCloseParen: { |
| fCurrentTokenDelimiter = DelimiterCloseParen; |
| break scanner; |
| } |
| case DelimiterComma: { |
| fCurrentTokenDelimiter = DelimiterComma; |
| break scanner; |
| } |
| case DelimiterSpace: { |
| fCurrentTokenDelimiter = DelimiterSpace; |
| break scanner; |
| } |
| case DelimiterQuote: { |
| fCurrentTokenDelimiter = DelimiterQuote; |
| break scanner; |
| } |
| case DelimiterSingleQuote: { |
| fCurrentTokenDelimiter = DelimiterSingleQuote; |
| break scanner; |
| } |
| case DelimiterEscape: { |
| fCurrentTokenDelimiter = DelimiterEscape; |
| break scanner; |
| } |
| case DelimiterOpenElipse:{ |
| fCurrentTokenDelimiter = DelimiterOpenElipse; |
| break scanner; |
| } |
| case DelimiterOpenSquareBrace:{ |
| fCurrentTokenDelimiter = DelimiterOpenSquareBrace; |
| break scanner; |
| } |
| case DelimiterCloseSquareBrace:{ |
| fCurrentTokenDelimiter = DelimiterCloseSquareBrace; |
| break scanner; |
| } |
| case DelimiterCloseElipse:{ |
| fCurrentTokenDelimiter = DelimiterCloseElipse; |
| break scanner; |
| } |
| // Do the math functions |
| case OperPlus: { |
| fCurrentTokenDelimiter = OperPlus; |
| break scanner; |
| } |
| case OperMinus: { |
| fCurrentTokenDelimiter = OperMinus; |
| break scanner; |
| } |
| case OperMultiply: { |
| fCurrentTokenDelimiter = OperMultiply; |
| break scanner; |
| } |
| case OperDivide: { |
| fCurrentTokenDelimiter = OperDivide; |
| break scanner; |
| } |
| // Do the primitive BitWise operations |
| case BitOR: { |
| fCurrentTokenDelimiter = BitOR; |
| break scanner; |
| } |
| case BitAND: { |
| fCurrentTokenDelimiter = BitAND; |
| break scanner; |
| } |
| default: { |
| fCurrentTokenSource[i] = fSource[fSourcePosition]; |
| } |
| } |
| } |
| |
| // Push the token onto the stack for later decoding |
| if ( i >= 1 ) { |
| fCurrentToken = new char[i]; |
| System.arraycopy( fCurrentTokenSource , 0 , fCurrentToken , 0 , i ); |
| } else { |
| fCurrentToken = new char[0]; |
| } |
| |
| } |
| /** Answer the result of evaluating the expression |
| */ |
| public Object evaluate() throws InitializationStringEvaluationException { |
| |
| try { |
| return fExpression.evaluate(); |
| } catch (java.lang.reflect.InvocationTargetException e) { |
| throw new EvaluationException(e); |
| } catch (EvaluationException e) { |
| throw e; // Don't loose these |
| } catch (Exception e) { |
| throw new InitializationStringEvaluationException(e); |
| } |
| |
| } |
| public static Object evaluate(String initString) throws InitializationStringEvaluationException { |
| |
| return evaluate(initString,null); |
| |
| } |
| public static Object evaluate(String initString,ClassLoader aClassLoader) throws InitializationStringEvaluationException { |
| |
| InitializationStringParser parser = null;; |
| try { |
| parser = new InitializationStringParser(initString); |
| parser.setClassLoader(aClassLoader); |
| parser.parse(); |
| } catch ( Throwable exc ) { |
| throw new InitializationStringEvaluationException(exc); |
| } |
| return parser.evaluate(); |
| } |
| |
| /** |
| * Return a parser already parsed. Use the default classloader (i.e. classloader that loaded InitializationStringParser). |
| * |
| * @param initString |
| * @return The parser, already parsed. |
| * @throws InitializationStringEvaluationException |
| */ |
| |
| public static InitializationStringParser createParser(String initString) throws InitializationStringEvaluationException { |
| return createParser(initString, null); |
| } |
| |
| /** |
| * Return a parser already parsed. Use the given classloader. |
| * |
| * @param initString |
| * @param classLoader |
| * @return The parser, already parsed. |
| * @throws InitializationStringEvaluationException |
| */ |
| public static InitializationStringParser createParser(String initString, ClassLoader classLoader) throws InitializationStringEvaluationException { |
| |
| try { |
| InitializationStringParser parser = new InitializationStringParser(initString); |
| parser.setClassLoader(classLoader); |
| parser.parse(); |
| return parser; |
| } catch ( Throwable exc ) { |
| throw new InitializationStringEvaluationException(exc); |
| } |
| |
| } |
| |
| /** Analyze the string |
| */ |
| public void parse(){ |
| |
| createFirstExpression(); |
| //int i =1; |
| while ( true ){ |
| createNextToken(); |
| if ( isComplete ) { |
| // If the current expression is incomplete it must be completed |
| // by the end, which is basically the equiavlent of a; |
| return; |
| } else { |
| //i++; |
| Expression result = fExpression.push( fCurrentToken , fCurrentTokenDelimiter ); |
| // If the result if a push then push the stack |
| if ( result.isComplete() ) { |
| popExpressionStack(); |
| } else if ( result != fExpression ) { |
| pushExpressionStack(result); |
| } |
| } |
| } |
| } |
| |
| /** |
| * Answer if the string results in a primitive. |
| */ |
| public boolean isPrimitive() throws InitializationStringEvaluationException { |
| try { |
| return fExpression.isPrimitive(); |
| } catch (Exception e) { |
| throw new InitializationStringEvaluationException(e); |
| } |
| } |
| |
| public Class getExpectedType() throws InitializationStringEvaluationException { |
| try { |
| return fExpression.getTypeClass(); |
| } catch (Exception e) { |
| throw new InitializationStringEvaluationException(e); |
| } |
| } |
| |
| /* Pop the top expression off the stack |
| */ |
| protected void popExpressionStack(){ |
| |
| if ( fExpressionStack.size() > 0 ) { |
| fExpression = (Expression) fExpressionStack.remove(fExpressionStack.size()-1); |
| } |
| } |
| /* Push the expression onto the stack |
| */ |
| protected void pushExpressionStack(Expression anExpression){ |
| |
| // The current expression should go onto the stack |
| fExpressionStack.add(fExpression); |
| // The current expression is replaced with the argument |
| fExpression = anExpression; |
| |
| } |
| protected void createFirstExpression(){ |
| if ( fExpression == null ) { |
| fExpression = new Statement(fClassLoader); |
| }; |
| } |
| public void setClassLoader(ClassLoader aClassLoader){ |
| fClassLoader = aClassLoader; |
| } |
| public String toString(){ |
| StringBuffer writer = new StringBuffer(); |
| writer.append("Parser. token=\""); //$NON-NLS-1$ |
| if ( fCurrentToken != null ) { |
| writer.append(fCurrentToken); |
| } |
| writer.append("\", delim=\""); //$NON-NLS-1$ |
| writer.append(fCurrentTokenDelimiter); |
| writer.append("\", initString=\""); //$NON-NLS-1$ |
| writer.append(fInitString); |
| return writer.toString(); |
| } |
| } |