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 
  41     private Symbol(Type type, Integer value) {
  42         this(type, value, false);
  43     }
  44 
  45     private Symbol(Type type) {
  46         this(type, null, false);
  47     }
  48 
  49     private Symbol(Type type, boolean isArithmetic) {
  50         this(type, null, isArithmetic);
  51     }
  52 
  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 
  61     public int value() {
  62         return value;
  63     }
  64 
  65     public String toString() {
  66         return type.name();
  67     }
  68 
  69     public boolean isArithmetic() {
  70         return isArithmetic;
  71     }
  72 
  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 
 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 }