--- /dev/null
+/*\r
+\r
+ Derby - Class org.apache.derby.impl.sql.compile.ParserImpl\r
+\r
+ Licensed to the Apache Software Foundation (ASF) under one or more\r
+ contributor license agreements. See the NOTICE file distributed with\r
+ this work for additional information regarding copyright ownership.\r
+ The ASF licenses this file to you under the Apache License, Version 2.0\r
+ (the "License"); you may not use this file except in compliance with\r
+ the License. You may obtain a copy of the License at\r
+\r
+ http://www.apache.org/licenses/LICENSE-2.0\r
+\r
+ Unless required by applicable law or agreed to in writing, software\r
+ distributed under the License is distributed on an "AS IS" BASIS,\r
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
+ See the License for the specific language governing permissions and\r
+ limitations under the License.\r
+\r
+ */\r
+\r
+package org.apache.derby.impl.sql.compile;\r
+\r
+import org.apache.derby.impl.sql.compile.QueryTreeNode;\r
+import org.apache.derby.iapi.sql.compile.Parser;\r
+import org.apache.derby.iapi.sql.Statement;\r
+import org.apache.derby.iapi.sql.compile.CompilerContext;\r
+\r
+import org.apache.derby.iapi.reference.SQLState;\r
+import org.apache.derby.iapi.error.StandardException;\r
+import org.apache.derby.iapi.services.sanity.SanityManager;\r
+\r
+public class ParserImpl implements Parser\r
+{\r
+ /*\r
+ ** We will use the following constant to pass in to\r
+ ** our CharStream. It is the size of the internal\r
+ ** buffers that are used to buffer tokens. It\r
+ ** should be set to what is typically around the\r
+ ** largest token that is likely to be hit. Note\r
+ ** that if the size is exceeded, the buffer will\r
+ ** automatically be expanded by 2048, so it is ok\r
+ ** to choose something that is smaller than the\r
+ ** max token supported.\r
+ **\r
+ ** Since, JavaCC generates parser and tokenmanagers classes\r
+ ** tightly connected, to use another parser or tokenmanager\r
+ ** inherit this class, override the following methods\r
+ ** to use specific instances:<ul>\r
+ ** <li>getTokenManager()</li>\r
+ ** <li>getParser()</li>\r
+ ** <li>parseGoalProduction(...)</li>\r
+ ** </ul>\r
+ **\r
+ */\r
+ static final int LARGE_TOKEN_SIZE = 128;\r
+\r
+ /* Don't ever access these objects directly, call getParser(), and getTokenManager() */\r
+ private SQLParser cachedParser; \r
+ protected Object cachedTokenManager;\r
+\r
+ protected CharStream charStream;\r
+ protected String SQLtext;\r
+\r
+ protected final CompilerContext cc;\r
+\r
+ /**\r
+ * Constructor for Parser\r
+ */\r
+\r
+ public ParserImpl(CompilerContext cc)\r
+ {\r
+ this.cc = cc;\r
+ }\r
+\r
+ public StatementNode parseStatement(String statementSQLText) \r
+ throws StandardException\r
+ {\r
+ return parseStatement(statementSQLText, (Object[])null);\r
+ }\r
+\r
+ /**\r
+ * Returns a initialized (clean) TokenManager, paired w. the Parser in getParser,\r
+ * Appropriate for this ParserImpl object.\r
+ */\r
+ protected Object getTokenManager()\r
+ {\r
+ /* returned a cached tokenmanager if already exists, otherwise create */\r
+ SQLParserTokenManager tm = (SQLParserTokenManager) cachedTokenManager;\r
+ if (tm == null) {\r
+ tm = new SQLParserTokenManager(charStream);\r
+ cachedTokenManager = tm;\r
+ } else {\r
+ tm.ReInit(charStream);\r
+ }\r
+ return tm;\r
+ }\r
+\r
+ /**\r
+ * new parser, appropriate for the ParserImpl object.\r
+ */\r
+ private SQLParser getParser()\r
+ {\r
+ SQLParserTokenManager tm = (SQLParserTokenManager) getTokenManager();\r
+ /* returned a cached Parser if already exists, otherwise create */\r
+ SQLParser p = (SQLParser) cachedParser;\r
+ if (p == null) {\r
+ p = new SQLParser(tm);\r
+ p.setCompilerContext(cc);\r
+ cachedParser = p;\r
+ } else {\r
+ p.ReInit(tm);\r
+ }\r
+ return p;\r
+ }\r
+\r
+ /**\r
+ * Parse a statement and return a query tree. Implements the Parser\r
+ * interface\r
+ *\r
+ * @param statementSQLText Statement to parse\r
+ * @param paramDefaults parameter defaults. Passed around as an array\r
+ * of objects, but is really an array of StorableDataValues\r
+ * @return A QueryTree representing the parsed statement\r
+ *\r
+ * @exception StandardException Thrown on error\r
+ */\r
+\r
+ public StatementNode parseStatement(String statementSQLText, Object[] paramDefaults) \r
+ throws StandardException\r
+ {\r
+\r
+ java.io.Reader sqlText = new java.io.StringReader(statementSQLText);\r
+\r
+ /* Get a char stream if we don't have one already */\r
+ if (charStream == null)\r
+ {\r
+ charStream = new UCode_CharStream(sqlText, 1, 1, LARGE_TOKEN_SIZE);\r
+ }\r
+ else\r
+ {\r
+ charStream.ReInit(sqlText, 1, 1, LARGE_TOKEN_SIZE);\r
+ }\r
+\r
+ /* remember the string that we're parsing */\r
+ SQLtext = statementSQLText;\r
+\r
+ /* Parse the statement, and return the QueryTree */\r
+ try\r
+ {\r
+ return getParser().Statement(statementSQLText, paramDefaults);\r
+ }\r
+ catch (ParseException e)\r
+ {\r
+ throw StandardException.newException(SQLState.LANG_SYNTAX_ERROR, e.getMessage());\r
+ }\r
+ catch (TokenMgrError e)\r
+ {\r
+ // Derby - 2103.\r
+ // When the exception occurs cachedParser may live with\r
+ // some flags set inappropriately that may cause Exception\r
+ // in the subsequent compilation. This seems to be a javacc bug.\r
+ // Issue Javacc-152 has been raised.\r
+ // As a workaround, the cachedParser object is cleared to ensure\r
+ // that the exception does not have any side effect.\r
+ // TODO : Remove the following line if javacc-152 is fixed.\r
+ cachedParser = null;\r
+ throw StandardException.newException(SQLState.LANG_LEXICAL_ERROR, e.getMessage());\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Returns the current SQL text string that is being parsed.\r
+ *\r
+ * @return Current SQL text string.\r
+ *\r
+ */\r
+ public String getSQLtext()\r
+ { return SQLtext; }\r
+}\r