1 /* 2 * Copyright (c) 2007, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 25 import java.util.HashMap; 26 import java.util.Locale; 27 import java.util.Map; 28 29 import static java.util.Calendar.*; 30 import static java.util.GregorianCalendar.*; 31 32 public class Symbol { 33 34 private static Map<String, Symbol> symbols; 35 36 String name; 37 Type type; 38 int value; 39 boolean isArithmetic; 40 Symbol(Type type, Integer value)41 private Symbol(Type type, Integer value) { 42 this(type, value, false); 43 } 44 Symbol(Type type)45 private Symbol(Type type) { 46 this(type, null, false); 47 } 48 Symbol(Type type, boolean isArithmetic)49 private Symbol(Type type, boolean isArithmetic) { 50 this(type, null, isArithmetic); 51 } 52 Symbol(Type type, Integer value, boolean isArithmetic)53 private Symbol(Type type, Integer value, boolean isArithmetic) { 54 this.name = type.toString().toLowerCase(Locale.ROOT); 55 this.type = type; 56 if (value != null) 57 this.value = value; 58 this.isArithmetic = isArithmetic; 59 } 60 value()61 public int value() { 62 return value; 63 } 64 toString()65 public String toString() { 66 return type.name(); 67 } 68 isArithmetic()69 public boolean isArithmetic() { 70 return isArithmetic; 71 } 72 get(String s)73 public static Symbol get(String s) { 74 return symbols.get(s); 75 } 76 77 public static enum Type { 78 // Directives 79 TEST, 80 // Commands 81 LOCALE, TIMEZONE, NEW, USE, ASSIGN, EVAL, 82 CLEAR, SET, GET, ADD, ROLL, CHECK, PRINT, EXCEPTION, 83 IF, 84 // Operands 85 INSTANCE, GREGORIAN, ALL, MILLIS, DATE, DATETIME, TIMEOFDAY, 86 LENIENT, NONLENIENT, 87 MINIMUM, GREATESTMINIMUM, ACTUALMINIMUM, 88 MAXIMUM, LEASTMAXIMUM, ACTUALMAXIMUM, 89 FIRSTDAYOFWEEK, MINIMALDAYSINFIRSTWEEK, 90 // Arithmetic operators 91 PLUS, MINUS, MULTIPLY, DIVIDE, MOD, 92 // Relational operators 93 GT, GE, EQ, NEQ, LE, LT, 94 // Calendar field indices 95 FIELD, 96 // Day of week 97 DAYOFWEEK, 98 // Month 99 MONTH, 100 // AM/PM 101 AMPM, 102 // Era values 103 ERA; 104 } 105 put(String key, Symbol sym)106 private static final void put(String key, Symbol sym) { 107 Symbol s = symbols.put(key, sym); 108 if (s != null) { 109 throw new RuntimeException("duplicated key: " + key); 110 } 111 } 112 113 static { 114 symbols = new HashMap<String, Symbol>(); 115 Symbol sym; 116 // Directives 117 put("test", new Symbol(Type.TEST)); 118 119 // Commands 120 put("locale", new Symbol(Type.LOCALE)); 121 sym = new Symbol(Type.TIMEZONE); 122 put("tz", sym); 123 put("timezone", sym); 124 put("new", new Symbol(Type.NEW)); 125 put("use", new Symbol(Type.USE)); 126 put("assign", new Symbol(Type.ASSIGN)); 127 put("eval", new Symbol(Type.EVAL)); 128 put("clear", new Symbol(Type.CLEAR)); 129 put("set", new Symbol(Type.SET)); 130 put("get", new Symbol(Type.GET)); 131 put("add", new Symbol(Type.ADD)); 132 put("roll", new Symbol(Type.ROLL)); 133 put("check", new Symbol(Type.CHECK)); 134 put("print", new Symbol(Type.PRINT)); 135 put("exception", new Symbol(Type.EXCEPTION)); 136 put("throw", get("exception")); 137 put("if", new Symbol(Type.IF)); 138 139 // Operands 140 put("instance", new Symbol(Type.INSTANCE)); 141 put("gregorian", new Symbol(Type.GREGORIAN)); 142 put("all", new Symbol(Type.ALL)); 143 put("millis", new Symbol(Type.MILLIS)); 144 put("date", new Symbol(Type.DATE)); 145 put("datetime", new Symbol(Type.DATETIME)); 146 put("timeofday", new Symbol(Type.TIMEOFDAY)); 147 put("lenient", new Symbol(Type.LENIENT)); 148 sym = new Symbol(Type.NONLENIENT); 149 put("non-lenient", sym); 150 put("nonlenient", sym); 151 put("firstdayofweek", new Symbol(Type.FIRSTDAYOFWEEK)); 152 put("minimaldaysinfirstweek", new Symbol(Type.MINIMALDAYSINFIRSTWEEK)); 153 154 sym = new Symbol(Type.MINIMUM); 155 put("minimum", sym); 156 put("min", sym); 157 sym = new Symbol(Type.GREATESTMINIMUM); 158 put("greatestminimum", sym); 159 put("greatestmin", sym); 160 sym = new Symbol(Type.ACTUALMINIMUM); 161 put("actualminimum", sym); 162 put("actualmin", sym); 163 sym = new Symbol(Type.MAXIMUM); 164 put("maximum", sym); 165 put("max", sym); 166 sym = new Symbol(Type.LEASTMAXIMUM); 167 put("leastmaximum", sym); 168 put("leastmax", sym); 169 sym = new Symbol(Type.ACTUALMAXIMUM); 170 put("actualmaximum", sym); 171 put("actualmax", sym); 172 173 // Arithmetic operators 174 put("+", new Symbol(Type.PLUS, true)); 175 put("-", new Symbol(Type.MINUS, true)); 176 put("*", new Symbol(Type.MULTIPLY, true)); 177 put("/", new Symbol(Type.DIVIDE, true)); 178 put("%", new Symbol(Type.MOD, true)); 179 180 // Relational operators 181 put(">", new Symbol(Type.GT, false)); 182 put(">=", new Symbol(Type.GE, false)); 183 put("==", new Symbol(Type.EQ, false)); 184 put("!=", new Symbol(Type.NEQ, false)); 185 put("<=", new Symbol(Type.LE, false)); 186 put("<", new Symbol(Type.LT, false)); 187 188 // Calendar Fields 189 put("era", new Symbol(Type.FIELD, ERA)); 190 put("year", new Symbol(Type.FIELD, YEAR)); 191 put("month", new Symbol(Type.FIELD, MONTH)); 192 sym = new Symbol(Type.FIELD, WEEK_OF_YEAR); 193 put("week_of_year", sym); 194 put("weekofyear", sym); 195 put("woy", sym); 196 sym = new Symbol(Type.FIELD, WEEK_OF_MONTH); 197 put("week_of_month", sym); 198 put("weekofmonth", sym); 199 put("wom", sym); 200 sym = new Symbol(Type.FIELD, DAY_OF_MONTH); 201 put("day_of_month", sym); 202 put("dayofmonth", sym); 203 put("dom", sym); 204 sym = new Symbol(Type.FIELD, DAY_OF_YEAR); 205 put("day_of_year", sym); 206 put("dayofyear", sym); 207 put("doy", sym); 208 209 sym = new Symbol(Type.FIELD, DAY_OF_WEEK); 210 put("day_of_week", sym); 211 put("dayofweek", sym); 212 put("dow", sym); 213 sym = new Symbol(Type.FIELD, DAY_OF_WEEK_IN_MONTH); 214 put("day_of_week_in_month", sym); 215 put("dayofweekinmonth", sym); 216 put("dowim", sym); 217 sym = new Symbol(Type.FIELD, AM_PM); 218 put("am_pm", sym); 219 put("ampm", sym); 220 put("hour", new Symbol(Type.FIELD, HOUR)); 221 sym = new Symbol(Type.FIELD, HOUR_OF_DAY); 222 put("hour_of_day", sym); 223 put("hourofday", sym); 224 put("hod", sym); 225 put("minute", new Symbol(Type.FIELD, MINUTE)); 226 put("second", new Symbol(Type.FIELD, SECOND)); 227 put("millisecond", new Symbol(Type.FIELD, MILLISECOND)); 228 sym = new Symbol(Type.FIELD, ZONE_OFFSET); 229 put("zone_offset", sym); 230 put("zoneoffset", sym); 231 put("zo", sym); 232 sym = new Symbol(Type.FIELD, DST_OFFSET); 233 put("dst_offset", sym); 234 put("dstoffset", sym); 235 put("do", sym); 236 237 // Day of week 238 sym = new Symbol(Type.DAYOFWEEK, SUNDAY); 239 put("sunday", sym); 240 put("sun", sym); 241 sym = new Symbol(Type.DAYOFWEEK, MONDAY); 242 put("monday", sym); 243 put("mon", sym); 244 sym = new Symbol(Type.DAYOFWEEK, TUESDAY); 245 put("tuesday", sym); 246 put("tue", sym); 247 sym = new Symbol(Type.DAYOFWEEK, WEDNESDAY); 248 put("wednesday", sym); 249 put("wed", sym); 250 sym = new Symbol(Type.DAYOFWEEK, THURSDAY); 251 put("thursday", sym); 252 put("thu", sym); 253 sym = new Symbol(Type.DAYOFWEEK, FRIDAY); 254 put("friday", sym); 255 put("fri", sym); 256 sym = new Symbol(Type.DAYOFWEEK, SATURDAY); 257 put("saturday", sym); 258 put("sat", sym); 259 260 261 // Month 262 sym = new Symbol(Type.MONTH, JANUARY); 263 put("january", sym); 264 put("jan", sym); 265 sym = new Symbol(Type.MONTH, FEBRUARY); 266 put("february", sym); 267 put("feb", sym); 268 sym = new Symbol(Type.MONTH, MARCH); 269 put("march", sym); 270 put("mar", sym); 271 sym = new Symbol(Type.MONTH, APRIL); 272 put("april", sym); 273 put("apr", sym); 274 sym = new Symbol(Type.MONTH, MAY); 275 put("may", sym); 276 sym = new Symbol(Type.MONTH, JUNE); 277 put("june", sym); 278 put("jun", sym); 279 sym = new Symbol(Type.MONTH, JULY); 280 put("july", sym); 281 put("jul", sym); 282 sym = new Symbol(Type.MONTH, AUGUST); 283 put("august", sym); 284 put("aug", sym); 285 sym = new Symbol(Type.MONTH, SEPTEMBER); 286 put("september", sym); 287 put("sep", sym); 288 sym = new Symbol(Type.MONTH, OCTOBER); 289 put("octobwe", sym); 290 put("oct", sym); 291 sym = new Symbol(Type.MONTH, NOVEMBER); 292 put("november", sym); 293 put("nov", sym); 294 sym = new Symbol(Type.MONTH, DECEMBER); 295 put("december", sym); 296 put("dec", sym); 297 sym = new Symbol(Type.MONTH, UNDECIMBER); 298 put("undecimber", sym); 299 300 // AM/PM 301 put("am", new Symbol(Type.AMPM, AM)); 302 put("pm", new Symbol(Type.AMPM, PM)); 303 304 // Eras 305 306 // Julian eras 307 sym = new Symbol(Type.ERA, BC); 308 put("bc", sym); 309 put("bce", sym); 310 sym = new Symbol(Type.ERA, AD); 311 put("ad", sym); 312 put("ce", sym); 313 314 // Buddhist era 315 put("be", new Symbol(Type.ERA, 1)); 316 317 // Japanese imperial eras 318 sym = new Symbol(Type.ERA, 0); 319 put("before_meiji", sym); 320 put("beforemeiji", sym); 321 put("meiji", new Symbol(Type.ERA, 1)); 322 put("taisho", new Symbol(Type.ERA, 2)); 323 put("showa", new Symbol(Type.ERA, 3)); 324 put("heisei", new Symbol(Type.ERA, 4)); 325 put("reiwa", new Symbol(Type.ERA, 5)); 326 327 } 328 } 329