View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.jxpath.ri;
19  
20  import java.io.StringReader;
21  
22  import org.apache.commons.jxpath.JXPathInvalidSyntaxException;
23  import org.apache.commons.jxpath.ri.parser.ParseException;
24  import org.apache.commons.jxpath.ri.parser.TokenMgrError;
25  import org.apache.commons.jxpath.ri.parser.XPathParser;
26  
27  /**
28   * XPath parser.
29   */
30  public class Parser {
31  
32      private static final XPathParser PARSER = new XPathParser(new StringReader(""));
33  
34      /**
35       * Add escapes to the specified String.
36       *
37       * @param string incoming String
38       * @return String
39       */
40      private static String addEscapes(final String string) {
41          // Piggy-back on the code generated by JavaCC
42          return TokenMgrError.addEscapes(string);
43      }
44  
45      /**
46       * Describe a parse position.
47       *
48       * @param expression to parse
49       * @param position   parse position
50       * @return String
51       */
52      private static String describePosition(final String expression, final int position) {
53          if (position <= 0) {
54              return "at the beginning of the expression";
55          }
56          if (position >= expression.length()) {
57              return "- expression incomplete";
58          }
59          return "after: '" + addEscapes(expression.substring(0, position)) + "'";
60      }
61  
62      /**
63       * Parses the XPath expression. Throws a JXPathException in case of a syntax error.
64       *
65       * @param expression to parse
66       * @param compiler   the compiler
67       * @return parsed Object
68       */
69      public static Object parseExpression(final String expression, final Compiler compiler) {
70          synchronized (PARSER) {
71              PARSER.setCompiler(compiler);
72              Object expr;
73              try {
74                  PARSER.ReInit(new StringReader(expression));
75                  expr = PARSER.parseExpression();
76              } catch (final TokenMgrError e) {
77                  throw new JXPathInvalidSyntaxException("Invalid XPath: '" + addEscapes(expression) + "'. Invalid symbol '"
78                          + addEscapes(String.valueOf(e.getCharacter())) + "' " + describePosition(expression, e.getPosition()));
79              } catch (final ParseException e) {
80                  throw new JXPathInvalidSyntaxException(
81                          "Invalid XPath: '" + addEscapes(expression) + "'. Syntax error " + describePosition(expression, e.currentToken.beginColumn));
82              }
83              return expr;
84          }
85      }
86  
87      /**
88       * Constructs a new instance.
89       *
90       *@deprecated Will be private in the next major version.
91       */
92      @Deprecated
93      public Parser() {
94          // empty
95      }
96  }