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