001 /*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.commons.jxpath.ri;
018
019 import java.io.StringReader;
020
021 import org.apache.commons.jxpath.JXPathInvalidSyntaxException;
022 import org.apache.commons.jxpath.ri.parser.ParseException;
023 import org.apache.commons.jxpath.ri.parser.TokenMgrError;
024 import org.apache.commons.jxpath.ri.parser.XPathParser;
025
026 /**
027 * XPath parser
028 *
029 * @author Dmitri Plotnikov
030 * @version $Revision: 652845 $ $Date: 2008-05-02 12:46:46 -0500 (Fri, 02 May 2008) $
031 */
032 public class Parser {
033
034 private static XPathParser parser = new XPathParser(new StringReader(""));
035
036 /**
037 * Parses the XPath expression. Throws a JXPathException in case
038 * of a syntax error.
039 * @param expression to parse
040 * @param compiler the compiler
041 * @return parsed Object
042 */
043 public static Object parseExpression(
044 String expression,
045 Compiler compiler) {
046 synchronized (parser) {
047 parser.setCompiler(compiler);
048 Object expr = null;
049 try {
050 parser.ReInit(new StringReader(expression));
051 expr = parser.parseExpression();
052 }
053 catch (TokenMgrError e) {
054 throw new JXPathInvalidSyntaxException(
055 "Invalid XPath: '"
056 + addEscapes(expression)
057 + "'. Invalid symbol '"
058 + addEscapes(String.valueOf(e.getCharacter()))
059 + "' "
060 + describePosition(expression, e.getPosition()));
061 }
062 catch (ParseException e) {
063 throw new JXPathInvalidSyntaxException(
064 "Invalid XPath: '"
065 + addEscapes(expression)
066 + "'. Syntax error "
067 + describePosition(
068 expression,
069 e.currentToken.beginColumn));
070 }
071 return expr;
072 }
073 }
074
075 /**
076 * Describe a parse position.
077 * @param expression to parse
078 * @param position parse position
079 * @return String
080 */
081 private static String describePosition(String expression, int position) {
082 if (position <= 0) {
083 return "at the beginning of the expression";
084 }
085 if (position >= expression.length()) {
086 return "- expression incomplete";
087 }
088 return "after: '"
089 + addEscapes(expression.substring(0, position)) + "'";
090 }
091
092 /**
093 * Add escapes to the specified String.
094 * @param string incoming String
095 * @return String
096 */
097 private static String addEscapes(String string) {
098 // Piggy-back on the code generated by JavaCC
099 return TokenMgrError.addEscapes(string);
100 }
101 }