001: package org.jicengine.expression;
002:
003: import org.jicengine.operation.MethodInvocationOperation;
004: import org.jicengine.operation.ObjectInstantiationOperation;
005: import org.jicengine.operation.ArrayConstructionOperation;
006: import org.jicengine.operation.Operation;
007: import java.util.*;
008:
009: /**
010: * <p>
011: * Parses both method and constructor invocations.
012: * </p>
013: * <p>
014: * Copyright (C) 2004 Timo Laitinen
015: * </p>
016: * @author Timo Laitinen
017: * @created 2004-09-20
018: * @since JICE-0.10
019: */
020:
021: public class InvocationParser implements Parser {
022:
023: private static final String NEW_OPERATOR = "new ";
024: private static final String ARGUMENTS_PART_START = "(";
025: private static final String ARGUMENTS_PART_END = ")";
026: private static final String ARRAY_BRACKET_START = "[";
027: private static final String ARRAY_BRACKET_END = "]";
028: private static final String DOT = ".";
029:
030: private Parser elementParser;
031:
032: public InvocationParser(Parser elementParser) {
033: this .elementParser = elementParser;
034: }
035:
036: public Operation parse(String expression) throws SyntaxException {
037: int argumentsPartStart;
038:
039: if (expression.startsWith(NEW_OPERATOR)) {
040: // a 'new' operation, either:
041: // a) 'new full.class.name(parameters)'
042: // b) 'new full.class.name[arraySize]'
043:
044: argumentsPartStart = expression
045: .indexOf(ARGUMENTS_PART_START);
046:
047: if (argumentsPartStart != -1) {
048: // not an array
049: // extract class-name, like 'java.util.Date' from expression 'new java.util.Date()'.
050: String className = expression.substring(4,
051: argumentsPartStart);
052: String argumentsList = extractArguments(expression,
053: argumentsPartStart);
054: return new ObjectInstantiationOperation(expression,
055: elementParser.parse(className), parseArguments(
056: this .elementParser, argumentsList));
057: } else {
058: int arrayLengthStart = expression
059: .indexOf(ARRAY_BRACKET_START);
060:
061: if (arrayLengthStart != -1) {
062: // looks like an array creation..
063: String componentType = expression.substring(4,
064: arrayLengthStart);
065: String length = expression.substring(
066: arrayLengthStart + 1, expression
067: .lastIndexOf(ARRAY_BRACKET_END));
068: return new ArrayConstructionOperation(expression,
069: elementParser.parse(componentType),
070: elementParser.parse(length));
071: } else {
072: throw new SyntaxException(
073: "expected 'new full.class.name(parameters)' or 'new full.class.name[arraySize]', got '"
074: + expression + "'");
075: }
076: }
077: } else if ((argumentsPartStart = expression
078: .indexOf(ARGUMENTS_PART_START)) != -1) {
079: // if the 'new' operator is not used, then some method is called, either a static
080: // or a method of some instance.
081:
082: // extract the part before "()" marks.
083: String beforeMethodArguments = expression.substring(0,
084: argumentsPartStart);
085:
086: // extract the actor-part, a name of a variable or a class
087: int lastDotIndex = beforeMethodArguments.lastIndexOf(DOT);
088: String actorName = beforeMethodArguments.substring(0,
089: lastDotIndex);
090: String method = beforeMethodArguments
091: .substring(lastDotIndex + 1);
092:
093: Operation actor = elementParser.parse(actorName);
094:
095: Operation[] arguments = parseArguments(this .elementParser,
096: extractArguments(expression, argumentsPartStart));
097:
098: return new MethodInvocationOperation(expression, actor,
099: method, arguments);
100: } else {
101: return null;
102: }
103: }
104:
105: public static Operation[] parseArguments(Parser parser,
106: String argumentsExpression) throws SyntaxException {
107:
108: String[] params = Utils.parseArgumentlist(argumentsExpression);
109: Operation[] paramsAsOperations = new Operation[params.length];
110: for (int i = 0; i < params.length; i++) {
111: paramsAsOperations[i] = parser.parse(params[i]);
112: }
113: return paramsAsOperations;
114: }
115:
116: /**
117: * extracts arguments-list from an expression.
118: * Like 'param1,param2' from expression new full.package.name.ClassName(param1,param2)'
119: */
120: private static String extractArguments(String expression,
121: int argumentsPartStart) throws SyntaxException {
122: try {
123: return expression.substring(argumentsPartStart + 1,
124: expression.lastIndexOf(ARGUMENTS_PART_END));
125: } catch (StringIndexOutOfBoundsException e) {
126: throw new SyntaxException(
127: "Expression '"
128: + expression
129: + "' doesn't have valid arguments-part enclosed inside ()");
130: }
131: }
132:
133: }
|