001 /*
002 // $Id: Syntax.java 247 2009-06-20 05:52:40Z jhyde $
003 // This software is subject to the terms of the Eclipse Public License v1.0
004 // Agreement, available at the following URL:
005 // http://www.eclipse.org/legal/epl-v10.html.
006 // Copyright (C) 2007-2008 Julian Hyde
007 // All Rights Reserved.
008 // You must accept the terms of that agreement to use this software.
009 */
010 package org.olap4j.mdx;
011
012 import java.io.PrintWriter;
013 import java.util.List;
014
015 /**
016 * Enumerated values describing the syntax of an expression.
017 *
018 * @author jhyde
019 * @since 21 July, 2003
020 * @version $Id: Syntax.java 247 2009-06-20 05:52:40Z jhyde $
021 */
022 public enum Syntax {
023 /**
024 * Defines syntax for expression invoked <code>FUNCTION()</code> or
025 * <code>FUNCTION(args)</code>.
026 */
027 Function {
028 public void unparse(
029 String operatorName,
030 List<ParseTreeNode> argList,
031 ParseTreeWriter writer)
032 {
033 unparseList(writer, argList, operatorName + "(", ", ", ")");
034 }
035 },
036
037 /**
038 * Defines syntax for expression invoked as <code>object.PROPERTY</code>.
039 */
040 Property {
041 public void unparse(
042 String operatorName,
043 List<ParseTreeNode> argList,
044 ParseTreeWriter writer)
045 {
046 assert argList.size() == 1;
047 argList.get(0).unparse(writer); // 'this'
048 writer.getPrintWriter().print(".");
049 writer.getPrintWriter().print(operatorName);
050 }
051 },
052
053 /**
054 * Defines syntax for expression invoked invoked as
055 * <code>object.METHOD()</code> or
056 * <code>object.METHOD(args)</code>.
057 */
058 Method {
059 public void unparse(
060 String operatorName,
061 List<ParseTreeNode> argList,
062 ParseTreeWriter writer)
063 {
064 assert argList.size() >= 1;
065 argList.get(0).unparse(writer); // 'this'
066 final PrintWriter pw = writer.getPrintWriter();
067 pw.print(".");
068 pw.print(operatorName);
069 pw.print("(");
070 for (int i = 1; i < argList.size(); i++) {
071 if (i > 1) {
072 pw.print(", ");
073 }
074 argList.get(i).unparse(writer);
075 }
076 pw.print(")");
077 }
078 },
079
080 /**
081 * Defines syntax for expression invoked as <code>arg OPERATOR arg</code>
082 * (like '+' or 'AND').
083 */
084 Infix {
085 public void unparse(
086 String operatorName,
087 List<ParseTreeNode> argList,
088 ParseTreeWriter writer)
089 {
090 if (needParen(argList)) {
091 unparseList(
092 writer,
093 argList,
094 "(",
095 " " + operatorName + " ",
096 ")");
097 } else {
098 unparseList(
099 writer,
100 argList,
101 "",
102 " " + operatorName + " ",
103 "");
104 }
105 }
106 },
107
108 /**
109 * Defines syntax for expression invoked as <code>OPERATOR arg</code>
110 * (like unary '-').
111 */
112 Prefix {
113 public void unparse(
114 String operatorName,
115 List<ParseTreeNode> argList,
116 ParseTreeWriter writer)
117 {
118 if (needParen(argList)) {
119 unparseList(
120 writer,
121 argList,
122 "(" + operatorName + " ",
123 null,
124 ")");
125 } else {
126 unparseList(
127 writer,
128 argList,
129 operatorName + " ",
130 null,
131 "");
132 }
133 }
134 },
135
136 /**
137 * Defines syntax for expression invoked as <code>arg OPERATOR</code>
138 * (like <code>IS EMPTY</code>).
139 */
140 Postfix {
141 public void unparse(
142 String operatorName,
143 List<ParseTreeNode> argList,
144 ParseTreeWriter writer)
145 {
146 if (needParen(argList)) {
147 unparseList(
148 writer,
149 argList,
150 "(",
151 null,
152 " " + operatorName + ")");
153 } else {
154 unparseList(
155 writer,
156 argList,
157 "",
158 null,
159 " " + operatorName);
160 }
161 }
162 },
163
164 /**
165 * Defines syntax for expression invoked as
166 * <code>{ARG, ...}</code>; that
167 * is, the set construction operator.
168 */
169 Braces {
170 public void unparse(
171 String operatorName,
172 List<ParseTreeNode> argList,
173 ParseTreeWriter writer)
174 {
175 unparseList(
176 writer,
177 argList,
178 "{",
179 ", ",
180 "}");
181 }
182 },
183
184 /**
185 * Defines syntax for expression invoked as <code>(ARG)</code> or
186 * <code>(ARG, ...)</code>; that is, parentheses for grouping
187 * expressions, and the tuple construction operator.
188 */
189 Parentheses {
190 public void unparse(
191 String operatorName,
192 List<ParseTreeNode> argList,
193 ParseTreeWriter writer)
194 {
195 unparseList(
196 writer,
197 argList,
198 "(",
199 ", ",
200 ")");
201 }
202 },
203
204 /**
205 * Defines syntax for expression invoked as <code>CASE ... END</code>.
206 */
207 Case {
208 public void unparse(
209 String operatorName,
210 List<ParseTreeNode> argList,
211 ParseTreeWriter writer)
212 {
213 final PrintWriter pw = writer.getPrintWriter();
214 if (operatorName.equals("_CaseTest")) {
215 pw.print("CASE");
216 int j = 0;
217 int clauseCount = (argList.size() - j) / 2;
218 for (int i = 0; i < clauseCount; i++) {
219 pw.print(" WHEN ");
220 argList.get(j++).unparse(writer);
221 pw.print(" THEN ");
222 argList.get(j++).unparse(writer);
223 }
224 if (j < argList.size()) {
225 pw.print(" ELSE ");
226 argList.get(j++).unparse(writer);
227 }
228 assert j == argList.size();
229 pw.print(" END");
230 } else {
231 assert operatorName.equals("_CaseMatch");
232
233 pw.print("CASE ");
234 int j = 0;
235 argList.get(j++).unparse(writer);
236 int clauseCount = (argList.size() - j) / 2;
237 for (int i = 0; i < clauseCount; i++) {
238 pw.print(" WHEN ");
239 argList.get(j++).unparse(writer);
240 pw.print(" THEN ");
241 argList.get(j++).unparse(writer);
242 }
243 if (j < argList.size()) {
244 pw.print(" ELSE ");
245 argList.get(j++).unparse(writer);
246 }
247 assert j == argList.size();
248 pw.print(" END");
249 }
250 }
251 },
252
253 /**
254 * Defines syntax for expression generated by the system which
255 * cannot be specified syntactically.
256 */
257 Internal,
258
259 /**
260 * Defines syntax for a CAST expression
261 * <code>CAST(expression AS type)</code>.
262 */
263 Cast {
264 public void unparse(
265 String operatorName,
266 List<ParseTreeNode> argList,
267 ParseTreeWriter writer)
268 {
269 writer.getPrintWriter().print("CAST(");
270 argList.get(0).unparse(writer);
271 writer.getPrintWriter().print(" AS ");
272 argList.get(1).unparse(writer);
273 writer.getPrintWriter().print(")");
274 }
275 },
276
277 /**
278 * Defines syntax for expression invoked <code>object.&PROPERTY</code>
279 * (a variant of {@link #Property}).
280 */
281 QuotedProperty,
282
283 /**
284 * Defines syntax for expression invoked <code>object.[&PROPERTY]</code>
285 * (a variant of {@link #Property}).
286 */
287 AmpersandQuotedProperty;
288
289 /**
290 * Converts a call to a function of this syntax into source code.
291 *
292 * @param operatorName Operator name
293 * @param argList List of arguments
294 * @param writer Writer
295 */
296 public void unparse(
297 String operatorName,
298 List<ParseTreeNode> argList,
299 ParseTreeWriter writer)
300 {
301 throw new UnsupportedOperationException();
302 }
303
304 /**
305 * Returns whether a collection of parse tree nodes need to be enclosed
306 * in parentheses.
307 *
308 * @param args Parse tree nodes
309 * @return Whether nodes need to be enclosed in parentheses
310 */
311 private static boolean needParen(List<ParseTreeNode> args) {
312 return !(args.size() == 1
313 && args.get(0) instanceof CallNode
314 && ((CallNode) args.get(0)).getSyntax() == Parentheses);
315 }
316
317 private static void unparseList(
318 ParseTreeWriter writer,
319 List<ParseTreeNode> argList,
320 String start,
321 String mid,
322 String end)
323 {
324 final PrintWriter pw = writer.getPrintWriter();
325 pw.print(start);
326 for (int i = 0; i < argList.size(); i++) {
327 if (i > 0) {
328 pw.print(mid);
329 }
330 argList.get(i).unparse(writer);
331 }
332 pw.print(end);
333 }
334 }
335
336 // End Syntax.java