| 1 | // Copyright (c) 2020-2024 Joe Conigliaro. All rights reserved. |
| 2 | // Use of this source code is governed by an MIT license |
| 3 | // that can be found in the LICENSE file. |
| 4 | module token |
| 5 | |
| 6 | pub enum Token { |
| 7 | amp // & |
| 8 | and // && |
| 9 | and_assign // &= |
| 10 | arrow // <- |
| 11 | assign // = |
| 12 | // at // @ |
| 13 | attribute |
| 14 | bit_not // ~ |
| 15 | char // `A` - rune |
| 16 | colon // : |
| 17 | comma // , |
| 18 | comment |
| 19 | dec // -- |
| 20 | decl_assign // := |
| 21 | div // / |
| 22 | div_assign // /= |
| 23 | dollar // $ |
| 24 | dot // . |
| 25 | dotdot // .. |
| 26 | ellipsis // ... |
| 27 | eof |
| 28 | eq // == |
| 29 | ge // >= |
| 30 | gt // > |
| 31 | hash // # |
| 32 | inc // ++ |
| 33 | key_as |
| 34 | key_asm |
| 35 | key_assert |
| 36 | key_atomic |
| 37 | key_break |
| 38 | key_const |
| 39 | key_continue |
| 40 | key_defer |
| 41 | key_dump |
| 42 | key_else |
| 43 | key_enum |
| 44 | key_false |
| 45 | key_fn |
| 46 | key_for |
| 47 | key_global |
| 48 | key_go |
| 49 | key_goto |
| 50 | key_if |
| 51 | key_import |
| 52 | key_in |
| 53 | key_interface |
| 54 | key_is |
| 55 | key_isreftype |
| 56 | key_likely |
| 57 | key_lock |
| 58 | key_match |
| 59 | key_module |
| 60 | key_mut |
| 61 | key_nil |
| 62 | key_none |
| 63 | key_offsetof |
| 64 | key_or |
| 65 | key_pub |
| 66 | key_return |
| 67 | key_rlock |
| 68 | key_select |
| 69 | key_shared |
| 70 | key_sizeof |
| 71 | key_spawn |
| 72 | key_static |
| 73 | key_struct |
| 74 | key_true |
| 75 | key_type |
| 76 | key_typeof |
| 77 | key_union |
| 78 | key_unlikely |
| 79 | key_unsafe |
| 80 | key_volatile |
| 81 | lcbr // { |
| 82 | le // <= |
| 83 | left_shift // << |
| 84 | left_shift_assign // >>= |
| 85 | logical_or // || |
| 86 | lpar // ( |
| 87 | lsbr // [ |
| 88 | lt // < |
| 89 | minus // - |
| 90 | minus_assign // -= |
| 91 | mod // % |
| 92 | mod_assign // %= |
| 93 | mul // * |
| 94 | mul_assign // *= |
| 95 | name // user |
| 96 | ne // != |
| 97 | not // ! |
| 98 | not_in // !in |
| 99 | not_is // !is |
| 100 | number // 123 |
| 101 | or_assign // |= |
| 102 | pipe // | |
| 103 | plus // + |
| 104 | plus_assign // += |
| 105 | question // ? |
| 106 | rcbr // } |
| 107 | right_shift // >> |
| 108 | right_shift_assign // <<= |
| 109 | right_shift_unsigned // >>> |
| 110 | right_shift_unsigned_assign // >>>= |
| 111 | rpar // ) |
| 112 | rsbr // ] |
| 113 | semicolon // ; |
| 114 | str_dollar |
| 115 | string // 'foo' |
| 116 | unknown |
| 117 | xor // ^ |
| 118 | xor_assign // ^= |
| 119 | } |
| 120 | |
| 121 | pub enum BindingPower { |
| 122 | lowest |
| 123 | logical_or // || |
| 124 | logical_and // && |
| 125 | compare // ==, !=, <, <=, >, >=, in, !in, is, !is |
| 126 | bit_or // | |
| 127 | bit_xor // ^ |
| 128 | shift // <<, >>, >>> |
| 129 | add // +, - |
| 130 | product // *, /, %, & |
| 131 | highest |
| 132 | } |
| 133 | |
| 134 | @[inline] |
| 135 | pub fn (t Token) left_binding_power() BindingPower { |
| 136 | return match t { |
| 137 | // `||` |
| 138 | .logical_or { |
| 139 | BindingPower.logical_or |
| 140 | } |
| 141 | // `&&` |
| 142 | .and { |
| 143 | BindingPower.logical_and |
| 144 | } |
| 145 | // `==` | `!=` | `<` | `<=` | `>` | `>=` | `in` | `!in` | `is` | `!is` |
| 146 | .eq, .ne, .lt, .le, .gt, .ge, .key_in, .not_in, .key_is, .not_is { |
| 147 | BindingPower.compare |
| 148 | } |
| 149 | // `|` |
| 150 | .pipe { |
| 151 | BindingPower.bit_or |
| 152 | } |
| 153 | // `^` |
| 154 | .xor { |
| 155 | BindingPower.bit_xor |
| 156 | } |
| 157 | // `<<` | `>>` | `>>>` |
| 158 | .left_shift, .right_shift, .right_shift_unsigned { |
| 159 | BindingPower.shift |
| 160 | } |
| 161 | // `+` | `-` |
| 162 | .plus, .minus { |
| 163 | BindingPower.add |
| 164 | } |
| 165 | // `*` | `/` | `%` | `&` |
| 166 | .mul, .div, .mod, .amp { |
| 167 | BindingPower.product |
| 168 | } |
| 169 | else { |
| 170 | BindingPower.lowest |
| 171 | } |
| 172 | } |
| 173 | } |
| 174 | |
| 175 | // TODO: double check / fix this. just use what is needed instead of this |
| 176 | @[inline] |
| 177 | pub fn (t Token) right_binding_power() BindingPower { |
| 178 | return unsafe { BindingPower((int(t.left_binding_power()) + 1)) } |
| 179 | } |
| 180 | |
| 181 | @[inline] |
| 182 | pub fn (t Token) is_keyword() bool { |
| 183 | return int(t) >= int(Token.key_as) && int(t) <= int(Token.key_volatile) |
| 184 | } |
| 185 | |
| 186 | @[inline] |
| 187 | pub fn (t Token) is_prefix() bool { |
| 188 | return t in [.minus, .amp, .mul, .not, .bit_not, .arrow] |
| 189 | } |
| 190 | |
| 191 | @[inline] |
| 192 | pub fn (t Token) is_infix() bool { |
| 193 | return t in [ |
| 194 | .amp, |
| 195 | .and, |
| 196 | .arrow, |
| 197 | .div, |
| 198 | // .dot, |
| 199 | .eq, |
| 200 | .ge, |
| 201 | .gt, |
| 202 | // .key_as, |
| 203 | .key_in, |
| 204 | .key_is, |
| 205 | .le, |
| 206 | .left_shift, |
| 207 | .logical_or, |
| 208 | .lt, |
| 209 | .minus, |
| 210 | .mod, |
| 211 | .mul, |
| 212 | .ne, |
| 213 | .not_in, |
| 214 | .not_is, |
| 215 | .pipe, |
| 216 | .plus, |
| 217 | .right_shift, |
| 218 | .right_shift_unsigned, |
| 219 | .xor, |
| 220 | ] |
| 221 | } |
| 222 | |
| 223 | @[inline] |
| 224 | pub fn (t Token) is_postfix() bool { |
| 225 | return t in [.dec, .inc] |
| 226 | // return t in [.dec, .inc, .not, .question] |
| 227 | } |
| 228 | |
| 229 | @[inline] |
| 230 | pub fn (t Token) is_assignment() bool { |
| 231 | return t in [ |
| 232 | .and_assign, |
| 233 | .assign, |
| 234 | .decl_assign, |
| 235 | .div_assign, |
| 236 | .left_shift_assign, |
| 237 | .minus_assign, |
| 238 | .mod_assign, |
| 239 | .mul_assign, |
| 240 | .or_assign, |
| 241 | .plus_assign, |
| 242 | .right_shift_assign, |
| 243 | .right_shift_unsigned_assign, |
| 244 | .xor_assign, |
| 245 | ] |
| 246 | } |
| 247 | |
| 248 | @[inline] |
| 249 | pub fn (t Token) is_overloadable() bool { |
| 250 | // `/` | `==` | `>=` | `>` | `<=` | `<` | `-` | `%` | `*` | `!=` | `|` | `+` | `^` |
| 251 | return t in [.div, .eq, .ge, .gt, .le, .lt, .minus, .mod, .mul, .ne, .pipe, .plus, .xor] |
| 252 | } |
| 253 | |
| 254 | @[inline] |
| 255 | pub fn (t Token) is_comparison() bool { |
| 256 | // `==` | `>=` | `>` | `in` | `is` | `<=` | `<` | `!=` | `!in` | `!is` |
| 257 | return t in [.eq, .ge, .gt, .key_in, .key_is, .le, .lt, .ne, .not_in, .not_is] |
| 258 | } |
| 259 | |
| 260 | // NOTE: probably switch back to map again later. |
| 261 | // for dev this is easier to see if any tokens are missing. |
| 262 | pub fn (t Token) str() string { |
| 263 | return match t { |
| 264 | .amp { '&' } |
| 265 | .and { '&&' } |
| 266 | .and_assign { '&=' } |
| 267 | .arrow { '<-' } |
| 268 | .assign { '=' } |
| 269 | // .at { '@' } |
| 270 | .attribute { '@[' } |
| 271 | .bit_not { '~' } |
| 272 | .char { 'char' } |
| 273 | .colon { ':' } |
| 274 | .comma { ',' } |
| 275 | .comment { '// comment' } |
| 276 | .dec { '--' } |
| 277 | .decl_assign { ':=' } |
| 278 | .div { '/' } |
| 279 | .div_assign { '/=' } |
| 280 | .dollar { '$' } |
| 281 | .dot { '.' } |
| 282 | .dotdot { '..' } |
| 283 | .ellipsis { '...' } |
| 284 | .eof { 'eof' } |
| 285 | .eq { '==' } |
| 286 | .ge { '>=' } |
| 287 | .gt { '>' } |
| 288 | .hash { '#' } |
| 289 | .inc { '++' } |
| 290 | .key_as { 'as' } |
| 291 | .key_asm { 'asm' } |
| 292 | .key_assert { 'assert' } |
| 293 | .key_atomic { 'atomic' } |
| 294 | .key_break { 'break' } |
| 295 | .key_const { 'const' } |
| 296 | .key_continue { 'continue' } |
| 297 | .key_defer { 'defer' } |
| 298 | .key_dump { 'dump' } |
| 299 | .key_else { 'else' } |
| 300 | .key_enum { 'enum' } |
| 301 | .key_false { 'false' } |
| 302 | .key_fn { 'fn' } |
| 303 | .key_for { 'for' } |
| 304 | .key_global { '__global' } |
| 305 | .key_go { 'go' } |
| 306 | .key_goto { 'goto' } |
| 307 | .key_if { 'if' } |
| 308 | .key_import { 'import' } |
| 309 | .key_in { 'in' } |
| 310 | .key_interface { 'interface' } |
| 311 | .key_is { 'is' } |
| 312 | .key_isreftype { 'isreftype' } |
| 313 | .key_likely { '_likely_' } |
| 314 | .key_lock { 'lock' } |
| 315 | .key_match { 'match' } |
| 316 | .key_module { 'module' } |
| 317 | .key_mut { 'mut' } |
| 318 | .key_nil { 'nil' } |
| 319 | .key_none { 'none' } |
| 320 | .key_offsetof { '__offsetof' } |
| 321 | .key_or { 'or' } |
| 322 | .key_pub { 'pub' } |
| 323 | .key_return { 'return' } |
| 324 | .key_rlock { 'rlock' } |
| 325 | .key_select { 'select' } |
| 326 | .key_shared { 'shared' } |
| 327 | .key_sizeof { 'sizeof' } |
| 328 | .key_spawn { 'spawn' } |
| 329 | .key_static { 'static' } |
| 330 | .key_struct { 'struct' } |
| 331 | .key_true { 'true' } |
| 332 | .key_type { 'type' } |
| 333 | .key_typeof { 'typeof' } |
| 334 | .key_union { 'union' } |
| 335 | .key_unlikely { '_unlikely_' } |
| 336 | .key_unsafe { 'unsafe' } |
| 337 | .key_volatile { 'volatile' } |
| 338 | .lcbr { '{' } |
| 339 | .le { '<=' } |
| 340 | .left_shift { '<<' } |
| 341 | .left_shift_assign { '<<=' } |
| 342 | .logical_or { '||' } |
| 343 | .lpar { '(' } |
| 344 | .lsbr { '[' } |
| 345 | .lt { '<' } |
| 346 | .minus { '-' } |
| 347 | .minus_assign { '-=' } |
| 348 | .mod { '%' } |
| 349 | .mod_assign { '%=' } |
| 350 | .mul { '*' } |
| 351 | .mul_assign { '*=' } |
| 352 | .name { 'name' } |
| 353 | .ne { '!=' } |
| 354 | .not { '!' } |
| 355 | .not_in { '!in' } |
| 356 | .not_is { '!is' } |
| 357 | .number { 'number' } |
| 358 | .or_assign { '|=' } |
| 359 | .pipe { '|' } |
| 360 | .plus { '+' } |
| 361 | .plus_assign { '+=' } |
| 362 | .question { '?' } |
| 363 | .rcbr { '}' } |
| 364 | .right_shift { '>>' } |
| 365 | .right_shift_assign { '>>=' } |
| 366 | .right_shift_unsigned { '>>>' } |
| 367 | .right_shift_unsigned_assign { '>>>=' } |
| 368 | .rpar { ')' } |
| 369 | .rsbr { ']' } |
| 370 | .semicolon { ';' } |
| 371 | .str_dollar { '\${' } |
| 372 | .string { 'string' } |
| 373 | .unknown { 'unknown' } |
| 374 | .xor { '^' } |
| 375 | .xor_assign { '^=' } |
| 376 | } |
| 377 | } |
| 378 | |