- /*
- * Copyright 2003-2004 The Apache Software Foundation
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
- package org.apache.commons.attributes.compiler;
-
- import java.util.ArrayList;
- import java.util.List;
-
- import org.apache.tools.ant.BuildException;
-
- /**
- * Parser for attribute expressions.
- */
- public class AttributeExpressionParser {
-
- public static class Argument {
- public final String field;
- public final String text;
- public final int length;
-
- public Argument (String field, String text, int length) {
- this.field = field;
- this.text = text;
- this.length = length;
- }
-
- public boolean equalsOrNull (String a, String b) {
- if (a == null) {
- return b == null;
- } else {
- return b != null && a.equals (b);
- }
- }
-
- public boolean equals (Object o) {
- return o instanceof Argument &&
- equalsOrNull (field, ((Argument) o).field) &&
- ((Argument) o).text.equals (text);
- }
-
- public String toString () {
- return "[Argument: " + field + ", " + text + ", " + length + "]";
- }
- }
-
- public static class ParseResult {
- public final List arguments = new ArrayList ();
- public final String className;
-
- public ParseResult (String className) {
- this.className = className;
- }
-
- public boolean equals (Object o) {
- return o instanceof ParseResult &&
- className.equals (((ParseResult) o).className) &&
- arguments.equals (((ParseResult) o).arguments);
- }
-
- public String toString () {
- return "[ParseResult: " + className + ", " + arguments + "]";
- }
- }
-
- protected static Argument nextArgument (String string, int startPos, String filename, int line) {
- if (string.charAt (startPos) == ')') {
- return null;
- }
-
- StringBuffer sb = new StringBuffer ();
-
- int i = startPos;
- int depth = 0;
- while (!( (string.charAt (i) == ',' || string.charAt (i) == ')') && depth == 0)) {
- switch (string.charAt (i)) {
- case '[':
- case '{':
- case '(': depth++; break;
-
- case ']':
- case '}':
- case ')': depth--; break;
-
- case '\'':
- case '"': {
- // handle string literals
- char endChar = string.charAt (i);
- sb.append (string.charAt (i));
- i++;
- while (true) {
- char ch = string.charAt (i);
- if (ch == '\\') {
- sb.append (ch);
- i++;
- ch = string.charAt (i);
- sb.append (ch);
- } else {
- if (ch == endChar) {
- break;
- }
- sb.append (ch);
- }
- i++;
- }
- }
- }
-
- sb.append (string.charAt (i));
- i++;
- if (i == string.length ()) {
- throw new BuildException (filename + ":" + line + ": Unterminated argument: " + string);
- }
- }
-
- if (string.charAt (i) == ',') {
- i++;
- }
-
- String text = sb.toString ();
- String field = null;
- int eqPos = text.indexOf ('=');
- if (eqPos > -1) {
- boolean identifier = true;
- for (int j = 0; j < eqPos; j++) {
- char ch = text.charAt (j);
-
- if (Character.isJavaIdentifierPart (ch) || ch == ' ') {
- } else {
- identifier = false;
- }
- }
-
- if (identifier) {
- field = text.substring (0, eqPos).trim ();
- text = text.substring (eqPos + 1).trim ();
- }
- }
-
- Argument arg = new Argument (field, text, i - startPos);
-
- return arg;
- }
-
- public static ParseResult parse (String string, String filename, int line) {
- StringBuffer sb = new StringBuffer ();
- int i = 0;
- while (i < string.length () && (Character.isJavaIdentifierPart (string.charAt (i)) || string.charAt (i) == '.' || string.charAt (i) == ' ')) {
- sb.append (string.charAt (i));
- i++;
- }
-
- if (i == string.length () || string.charAt (i) != '(') {
- throw new BuildException (filename + ":" + line + ": Illegal expression: " + string);
- }
-
- ParseResult result = new ParseResult (sb.toString ());
-
- i++;
- Argument arg = null;
- boolean seenField = false;
- while ((arg = nextArgument (string, i, filename, line)) != null) {
- if (arg.field != null) {
- seenField = true;
- }
-
- if (seenField && arg.field == null) {
- throw new BuildException (filename + ":" + line + ": Un-named parameters must come before the named parameters: " + string);
- }
-
- result.arguments.add (arg);
- i += arg.length;
- }
-
- return result;
- }
- }