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