001: /*
002:
003: Derby - Class org.apache.derby.impl.sql.compile.ParserImpl
004:
005: Licensed to the Apache Software Foundation (ASF) under one or more
006: contributor license agreements. See the NOTICE file distributed with
007: this work for additional information regarding copyright ownership.
008: The ASF licenses this file to you under the Apache License, Version 2.0
009: (the "License"); you may not use this file except in compliance with
010: the License. You may obtain a copy of the License at
011:
012: http://www.apache.org/licenses/LICENSE-2.0
013:
014: Unless required by applicable law or agreed to in writing, software
015: distributed under the License is distributed on an "AS IS" BASIS,
016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
017: See the License for the specific language governing permissions and
018: limitations under the License.
019:
020: */
021:
022: package org.apache.derby.impl.sql.compile;
023:
024: import org.apache.derby.impl.sql.compile.QueryTreeNode;
025: import org.apache.derby.iapi.sql.compile.Parser;
026: import org.apache.derby.iapi.sql.Statement;
027: import org.apache.derby.iapi.sql.compile.CompilerContext;
028:
029: import org.apache.derby.iapi.reference.SQLState;
030: import org.apache.derby.iapi.error.StandardException;
031: import org.apache.derby.iapi.services.sanity.SanityManager;
032:
033: public class ParserImpl implements Parser {
034: /*
035: ** We will use the following constant to pass in to
036: ** our CharStream. It is the size of the internal
037: ** buffers that are used to buffer tokens. It
038: ** should be set to what is typically around the
039: ** largest token that is likely to be hit. Note
040: ** that if the size is exceeded, the buffer will
041: ** automatically be expanded by 2048, so it is ok
042: ** to choose something that is smaller than the
043: ** max token supported.
044: **
045: ** Since, JavaCC generates parser and tokenmanagers classes
046: ** tightly connected, to use another parser or tokenmanager
047: ** inherit this class, override the following methods
048: ** to use specific instances:<ul>
049: ** <li>getTokenManager()</li>
050: ** <li>getParser()</li>
051: ** <li>parseGoalProduction(...)</li>
052: ** </ul>
053: **
054: */
055: static final int LARGE_TOKEN_SIZE = 128;
056:
057: /* Don't ever access these objects directly, call getParser(), and getTokenManager() */
058: protected Object cachedParser;
059: protected Object cachedTokenManager;
060:
061: protected CharStream charStream;
062: protected String SQLtext;
063:
064: protected final CompilerContext cc;
065:
066: /**
067: * Constructor for Parser
068: */
069:
070: public ParserImpl(CompilerContext cc) {
071: this .cc = cc;
072: }
073:
074: public QueryTreeNode parseStatement(String statementSQLText)
075: throws StandardException {
076: return parseStatement(statementSQLText, (Object[]) null);
077: }
078:
079: /**
080: * Returns a initialized (clean) TokenManager, paired w. the Parser in getParser,
081: * Appropriate for this ParserImpl object.
082: */
083: protected Object getTokenManager() {
084: /* returned a cached tokenmanager if already exists, otherwise create */
085: SQLParserTokenManager tm = (SQLParserTokenManager) cachedTokenManager;
086: if (tm == null) {
087: tm = new SQLParserTokenManager(charStream);
088: cachedTokenManager = tm;
089: } else {
090: tm.ReInit(charStream);
091: }
092: return tm;
093: }
094:
095: /**
096: * new parser, appropriate for the ParserImpl object.
097: */
098: protected Object getParser() {
099: SQLParserTokenManager tm = (SQLParserTokenManager) getTokenManager();
100: /* returned a cached Parser if already exists, otherwise create */
101: SQLParser p = (SQLParser) cachedParser;
102: if (p == null) {
103: p = new SQLParser(tm);
104: p.setCompilerContext(cc);
105: cachedParser = p;
106: } else {
107: p.ReInit(tm);
108: }
109: return p;
110: }
111:
112: /**
113: * Parse a statement and return a query tree. Implements the Parser
114: * interface
115: *
116: * @param statementSQLText Statement to parse
117: * @param paramDefaults parameter defaults. Passed around as an array
118: * of objects, but is really an array of StorableDataValues
119: * @return A QueryTree representing the parsed statement
120: *
121: * @exception StandardException Thrown on error
122: */
123:
124: public QueryTreeNode parseStatement(String statementSQLText,
125: Object[] paramDefaults) throws StandardException {
126:
127: java.io.Reader sqlText = new java.io.StringReader(
128: statementSQLText);
129:
130: /* Get a char stream if we don't have one already */
131: if (charStream == null) {
132: charStream = new UCode_CharStream(sqlText, 1, 1,
133: LARGE_TOKEN_SIZE);
134: } else {
135: charStream.ReInit(sqlText, 1, 1, LARGE_TOKEN_SIZE);
136: }
137:
138: /* remember the string that we're parsing */
139: SQLtext = statementSQLText;
140:
141: /* Parse the statement, and return the QueryTree */
142: try {
143: return parseGoalProduction(statementSQLText, paramDefaults);
144: } catch (ParseException e) {
145: throw StandardException.newException(
146: SQLState.LANG_SYNTAX_ERROR, e.getMessage());
147: } catch (TokenMgrError e) {
148: throw StandardException.newException(
149: SQLState.LANG_LEXICAL_ERROR, e.getMessage());
150: }
151: }
152:
153: /**
154: * Parse the goal production, e.g. "statement" for the normal SQL parser.
155: *
156: * @param statementSQLText The Statement to parse
157: * @param paramDefaults parameter defaults. Passed around as an array
158: * of objects, but is really an array of StorableDataValues
159: *
160: * @return A QueryTree representing the parsed statement
161: *
162: * @exception ParseException
163: * @exception TokenMgrError
164: */
165: protected QueryTreeNode parseGoalProduction(
166: String statementSQLText, Object[] paramDefaults)
167: throws ParseException, TokenMgrError, StandardException {
168: SQLParser p = (SQLParser) getParser();
169: return p.Statement(statementSQLText, paramDefaults);
170: } // End of parseGoalProduction
171:
172: /**
173: * Returns the current SQL text string that is being parsed.
174: *
175: * @return Current SQL text string.
176: *
177: */
178: public String getSQLtext() {
179: return SQLtext;
180: }
181: }
|