1 //
2 // Copyright (c) 2006, Brian Frank and Andy Frank
3 // Licensed under the Academic Free License version 3.0
4 //
5 // History:
6 // 16 Apr 06 Brian Frank Creation
7 //
8
9 **
10 ** Token is the enum for all the token types.
11 **
12 enum Token
13 {
14
15 //////////////////////////////////////////////////////////////////////////
16 // Enum
17 //////////////////////////////////////////////////////////////////////////
18
19 // identifer/literals
20 identifier ("identifier"),
21 strLiteral ("Str literal"),
22 intLiteral ("Int literal"),
23 floatLiteral ("Float literal"),
24 durationLiteral ("Duration literal"),
25 uriLiteral ("Uri literal"),
26
27 // operators
28 dot("."),
29 semicolon (";"),
30 comma (","),
31 colon (":"),
32 doubleColon ("::"),
33 plus ("+"),
34 minus ("-"),
35 star ("*"),
36 slash ("/"),
37 percent ("%"),
38 pound ("#"),
39 increment ("++"),
40 decrement ("--"),
41 bang ("!"),
42 question ("?"),
43 tilde ("~"),
44 pipe ("|"),
45 amp ("&"),
46 caret ("^"),
47 at ("@"),
48 doublePipe ("||"),
49 doubleAmp ("&&"),
50 same ("==="),
51 notSame ("!=="),
52 eq ("=="),
53 notEq ("!="),
54 cmp ("<=>"),
55 lt ("<"),
56 ltEq ("<="),
57 gt (">"),
58 gtEq (">="),
59 lshift ("<<"),
60 rshift (">>"),
61 lbrace ("{"),
62 rbrace ("}"),
63 lparen ("("),
64 rparen (")"),
65 lbracket ("["),
66 rbracket ("]"),
67 dotDot (".."),
68 dotDotDot ("..."),
69 defAssign (":="),
70 assign ("="),
71 assignPlus ("+="),
72 assignMinus ("-="),
73 assignStar ("*="),
74 assignSlash ("/="),
75 assignPercent ("%="),
76 assignAmp ("&="),
77 assignPipe ("|="),
78 assignCaret ("^="),
79 assignLshift ("<<="),
80 assignRshift (">>="),
81 arrow ("->"),
docComment ("**"),
83
84 // keywords
85 abstractKeyword,
86 asKeyword,
87 assertKeyword,
88 breakKeyword,
89 caseKeyword,
90 catchKeyword,
91 classKeyword,
92 constKeyword,
93 continueKeyword,
94 defaultKeyword,
95 doKeyword,
96 elseKeyword,
97 enumKeyword,
98 falseKeyword,
99 finalKeyword,
100 finallyKeyword,
101 forKeyword,
102 foreachKeyword,
103 gotoKeyword,
104 ifKeyword,
105 internalKeyword,
106 isKeyword,
107 mixinKeyword,
108 nativeKeyword,
109 newKeyword,
110 nullKeyword,
111 overrideKeyword,
112 privateKeyword,
113 protectedKeyword,
114 publicKeyword,
115 readonlyKeyword,
116 returnKeyword,
117 staticKeyword,
118 superKeyword,
119 switchKeyword,
120 thisKeyword,
121 throwKeyword,
122 trueKeyword,
123 tryKeyword,
124 usingKeyword,
125 virtualKeyword,
126 volatileKeyword,
127 voidKeyword,
128 whileKeyword,
129
130 // misc
131 eof("eof");
132
133 // potential keywords:
134 // async, checked, contract, decimal, duck, def, isnot,
135 // namespace, once, unchecked, unless, when, var, with
136
137 //////////////////////////////////////////////////////////////////////////
138 // Constructor
139 //////////////////////////////////////////////////////////////////////////
140
141 **
142 ** Construct with symbol str, or null symbol for keyword.
143 **
144 private new make(Str symbol := null)
145 {
146 if (symbol == null)
147 {
148 if (!name.endsWith("Keyword")) throw Err.make(name)
149 this.symbol = name[0..-8]
150 this.keyword = true
151 this.isAssign = false
152 }
153 else
154 {
155 this.symbol = symbol
156 this.keyword = false
157 this.isAssign = name.startsWith("assign") ||
158 name == "increment" ||
159 name == "decrement"
160 }
161 }
162
163 //////////////////////////////////////////////////////////////////////////
164 // Methods
165 //////////////////////////////////////////////////////////////////////////
166
167 **
168 ** Get this Token as a ExprId or throw Err.
169 **
170 ExprId toExprId()
171 {
172 switch (this)
173 {
174 // unary
175 case bang: return ExprId.boolNot
176
177 // binary
178 case assign: return ExprId.assign
179 case doubleAmp: return ExprId.boolAnd
180 case doublePipe: return ExprId.boolOr
181 case same: return ExprId.same
182 case notSame: return ExprId.notSame
183 case asKeyword: return ExprId.asExpr
184 case isKeyword: return ExprId.isExpr
185
186 // default
187 default: throw Err.make(toStr)
188 }
189 }
190
191 /**
192
193
194
195 ShortcutOp toShortcutOp(Int degree)
196 {
197 switch (this)
198 {
199 case plus: return ShortcutOp.plus // a + b
200 case minus: return degree == 1 ? ShortcutOp.negate : ShortcutOp.minus // -a; a - b
201 case star: return ShortcutOp.star // a * b
202 case slash: return ShortcutOp.slash // a / b
203 case percent: return ShortcutOp.percent // a % b
204 case lshift: return ShortcutOp.lshift // a << b
205 case rshift: return ShortcutOp.rshift // a >> b
206 case amp: return ShortcutOp.amp // a & b
207 case pipe: return ShortcutOp.pipe // a | b
208 case caret: return ShortcutOp.caret // a ^ b
209 case tilde: return ShortcutOp.tilde // ~a
210 case increment: return ShortcutOp.increment // ++a, a++
211 case decrement: return ShortcutOp.decrement // --a, a--
212 case eq: return ShortcutOp.eq // a == b
213 case notEq: return ShortcutOp.eq // a != b
214 case cmp: return ShortcutOp.cmp // a <=> b
215 case gt: return ShortcutOp.cmp // a > b
216 case gtEq: return ShortcutOp.cmp // a >= b
217 case lt: return ShortcutOp.cmp // a < b
218 case ltEq: return ShortcutOp.cmp // a <= b
219 case assignPlus: return ShortcutOp.plus // a += b
220 case assignMinus: return ShortcutOp.minus // a -= b
221 case assignStar: return ShortcutOp.star // a *= b
222 case assignSlash: return ShortcutOp.slash // a /= b
223 case assignPercent: return ShortcutOp.percent // a %= b
224 case assignAmp: return ShortcutOp.amp // a &= b
225 case assignPipe: return ShortcutOp.pipe // a |= b
226 case assignCaret: return ShortcutOp.caret // a ^= b
227 case assignLshift: return ShortcutOp.lshift // a <<= b
228 case assignRshift: return ShortcutOp.rshift // a >>= b
229 default: throw Err.make(toStr)
230 }
231 }
232
233 //////////////////////////////////////////////////////////////////////////
234 // Keyword Lookup
235 //////////////////////////////////////////////////////////////////////////
236
237 **
238 ** Get a map of the keywords
239 **
240 const static Str:Token keywords
241 static
242 {
243 map := Str:Token[:]
244 values.each |Token t|
245 {
246 if (t.keyword) map[t.symbol] = t
247 }
248 keywords = map.toImmutable
249 }
250
251 //////////////////////////////////////////////////////////////////////////
252 // Test
253 //////////////////////////////////////////////////////////////////////////
254
255 static Void main()
256 {
257 values.each |Token t|
258 {
259 echo(t.name + " '" + t.symbol + "'")
260 }
261
262 echo(keywords)
263 }
264
265 //////////////////////////////////////////////////////////////////////////
266 // Fields
267 //////////////////////////////////////////////////////////////////////////
268
269 ** Get string used to display token to user in error messages
270 const Str symbol
271
272 ** Is this a keyword token such as "null"
273 const Bool keyword
274
275 ** Is this an assignment token such as "=", etc "+=", etc
276 const Bool isAssign
277
278 }