2022-01-04 10:21:08 +01:00
|
|
|
// Copyright (c) 2019-2022 Alexander Medvednikov. All rights reserved.
|
2019-12-22 02:34:37 +01:00
|
|
|
// Use of this source code is governed by an MIT license
|
|
|
|
// that can be found in the LICENSE file.
|
|
|
|
module token
|
|
|
|
|
2019-12-28 09:15:32 +01:00
|
|
|
pub struct Token {
|
|
|
|
pub:
|
2021-02-04 08:18:38 +01:00
|
|
|
kind Kind // the token number/enum; for quick comparisons
|
2019-12-29 06:50:08 +01:00
|
|
|
lit string // literal representation of the token
|
2021-02-04 08:18:38 +01:00
|
|
|
line_nr int // the line number in the source where the token occured
|
2021-03-23 06:23:46 +01:00
|
|
|
col int // the column in the source where the token occured
|
2019-12-28 09:15:32 +01:00
|
|
|
// name_idx int // name table index for O(1) lookup
|
2021-02-04 08:18:38 +01:00
|
|
|
pos int // the position of the token in scanner text
|
|
|
|
len int // length of the literal
|
|
|
|
tidx int // the index of the token
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2019-12-31 10:53:30 +01:00
|
|
|
pub enum Kind {
|
2020-06-06 11:49:50 +02:00
|
|
|
unknown
|
2019-12-22 02:34:37 +01:00
|
|
|
eof
|
|
|
|
name // user
|
|
|
|
number // 123
|
2020-03-15 00:46:08 +01:00
|
|
|
string // 'foo'
|
2019-12-22 02:34:37 +01:00
|
|
|
str_inter // 'name=$user.name'
|
2021-01-01 17:23:32 +01:00
|
|
|
chartoken // `A` - rune
|
2021-02-04 08:18:38 +01:00
|
|
|
plus // +
|
|
|
|
minus // -
|
|
|
|
mul // *
|
|
|
|
div // /
|
|
|
|
mod // %
|
2019-12-22 02:34:37 +01:00
|
|
|
xor // ^
|
|
|
|
pipe // |
|
|
|
|
inc // ++
|
|
|
|
dec // --
|
|
|
|
and // &&
|
2021-02-04 08:18:38 +01:00
|
|
|
logical_or // ||
|
|
|
|
not // !
|
|
|
|
bit_not // ~
|
|
|
|
question // ?
|
|
|
|
comma // ,
|
|
|
|
semicolon // ;
|
|
|
|
colon // :
|
2020-08-17 20:12:00 +02:00
|
|
|
arrow // <-
|
2021-02-04 08:18:38 +01:00
|
|
|
amp // &
|
|
|
|
hash // #
|
|
|
|
dollar // $
|
2020-11-05 09:12:32 +01:00
|
|
|
at // @
|
2019-12-22 02:34:37 +01:00
|
|
|
str_dollar
|
2021-02-04 08:18:38 +01:00
|
|
|
left_shift // <<
|
|
|
|
right_shift // >>
|
2021-09-21 13:02:17 +02:00
|
|
|
unsigned_right_shift // >>>
|
2020-04-11 21:31:54 +02:00
|
|
|
not_in // !in
|
2020-06-02 16:18:12 +02:00
|
|
|
not_is // !is
|
2019-12-22 02:34:37 +01:00
|
|
|
assign // =
|
|
|
|
decl_assign // :=
|
|
|
|
plus_assign // +=
|
|
|
|
minus_assign // -=
|
2021-01-13 03:31:14 +01:00
|
|
|
div_assign // /=
|
|
|
|
mult_assign // *=
|
|
|
|
xor_assign // ^=
|
|
|
|
mod_assign // %=
|
|
|
|
or_assign // |=
|
2021-02-04 08:18:38 +01:00
|
|
|
and_assign // &=
|
|
|
|
right_shift_assign // <<=
|
|
|
|
left_shift_assign // >>=
|
2021-09-21 13:02:17 +02:00
|
|
|
unsigned_right_shift_assign // >>>=
|
2021-02-04 08:18:38 +01:00
|
|
|
lcbr // {
|
|
|
|
rcbr // }
|
|
|
|
lpar // (
|
|
|
|
rpar // )
|
|
|
|
lsbr // [
|
2021-12-22 14:34:02 +01:00
|
|
|
nilsbr // #[
|
2021-02-04 08:18:38 +01:00
|
|
|
rsbr // ]
|
|
|
|
eq // ==
|
|
|
|
ne // !=
|
|
|
|
gt // >
|
|
|
|
lt // <
|
|
|
|
ge // >=
|
|
|
|
le // <=
|
2020-04-05 02:08:10 +02:00
|
|
|
comment
|
2019-12-22 02:34:37 +01:00
|
|
|
nl
|
2021-02-04 08:18:38 +01:00
|
|
|
dot // .
|
|
|
|
dotdot // ..
|
|
|
|
ellipsis // ...
|
2019-12-22 02:34:37 +01:00
|
|
|
keyword_beg
|
|
|
|
key_as
|
|
|
|
key_asm
|
|
|
|
key_assert
|
|
|
|
key_atomic
|
|
|
|
key_break
|
|
|
|
key_const
|
|
|
|
key_continue
|
|
|
|
key_defer
|
|
|
|
key_else
|
|
|
|
key_enum
|
|
|
|
key_false
|
|
|
|
key_for
|
|
|
|
key_fn
|
|
|
|
key_global
|
|
|
|
key_go
|
|
|
|
key_goto
|
|
|
|
key_if
|
|
|
|
key_import
|
|
|
|
key_in
|
|
|
|
key_interface
|
2021-02-04 08:18:38 +01:00
|
|
|
key_is
|
2019-12-22 02:34:37 +01:00
|
|
|
key_match
|
|
|
|
key_module
|
|
|
|
key_mut
|
2020-07-04 12:44:25 +02:00
|
|
|
key_shared
|
|
|
|
key_lock
|
|
|
|
key_rlock
|
2019-12-22 02:34:37 +01:00
|
|
|
key_none
|
|
|
|
key_return
|
|
|
|
key_select
|
|
|
|
key_sizeof
|
2021-06-13 05:26:13 +02:00
|
|
|
key_isreftype
|
2020-06-09 16:36:18 +02:00
|
|
|
key_likely
|
2020-06-09 17:08:31 +02:00
|
|
|
key_unlikely
|
2019-12-22 02:34:37 +01:00
|
|
|
key_offsetof
|
|
|
|
key_struct
|
|
|
|
key_true
|
|
|
|
key_type
|
2020-03-19 12:15:39 +01:00
|
|
|
key_typeof
|
2021-03-06 18:09:28 +01:00
|
|
|
key_dump
|
2019-12-22 02:34:37 +01:00
|
|
|
key_orelse
|
|
|
|
key_union
|
|
|
|
key_pub
|
|
|
|
key_static
|
2021-09-22 12:06:30 +02:00
|
|
|
key_volatile
|
2019-12-22 02:34:37 +01:00
|
|
|
key_unsafe
|
|
|
|
keyword_end
|
2020-04-01 12:12:25 +02:00
|
|
|
_end_
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2021-10-28 14:09:41 +02:00
|
|
|
pub const assign_tokens = [Kind.assign, .plus_assign, .minus_assign, .mult_assign, .div_assign,
|
|
|
|
.xor_assign, .mod_assign, .or_assign, .and_assign, .right_shift_assign, .left_shift_assign,
|
|
|
|
.unsigned_right_shift_assign]
|
2021-02-03 09:17:13 +01:00
|
|
|
|
2021-10-28 14:09:41 +02:00
|
|
|
const nr_tokens = int(Kind._end_)
|
2020-11-05 09:12:32 +01:00
|
|
|
|
|
|
|
// @FN => will be substituted with the name of the current V function
|
2021-02-05 15:30:58 +01:00
|
|
|
// @METHOD => will be substituted with ReceiverType.MethodName
|
2020-11-05 09:12:32 +01:00
|
|
|
// @MOD => will be substituted with the name of the current V module
|
|
|
|
// @STRUCT => will be substituted with the name of the current V struct
|
|
|
|
// @FILE => will be substituted with the path of the V source file
|
|
|
|
// @LINE => will be substituted with the V line number where it appears (as a string).
|
|
|
|
// @COLUMN => will be substituted with the column where it appears (as a string).
|
|
|
|
// @VHASH => will be substituted with the shortened commit hash of the V compiler (as a string).
|
|
|
|
// @VMOD_FILE => will be substituted with the contents of the nearest v.mod file (as a string).
|
2021-04-19 18:01:47 +02:00
|
|
|
// @VMODROOT => will be substituted with the *folder* where the nearest v.mod file is (as a string).
|
|
|
|
// @VEXE => will be substituted with the path to the V compiler
|
|
|
|
// @VEXEROOT => will be substituted with the *folder* where the V executable is (as a string).
|
|
|
|
// @VROOT => the old name for @VMODROOT; sometimes it was used as @VEXEROOT;
|
2022-03-06 18:01:22 +01:00
|
|
|
// Note: @VROOT is now deprecated, use either @VMODROOT or @VEXEROOT instead.
|
|
|
|
// Note: @VEXEROOT & @VMODROOT are used for compilation options like this:
|
2021-04-19 18:01:47 +02:00
|
|
|
// #include "@VMODROOT/include/abc.h"
|
|
|
|
// #flag -L@VEXEROOT/thirdparty/libgc
|
|
|
|
//
|
|
|
|
// The @XYZ tokens allow for code like this:
|
2020-11-05 09:12:32 +01:00
|
|
|
// println( 'file: ' + @FILE + ' | line: ' + @LINE + ' | fn: ' + @MOD + '.' + @FN)
|
2021-04-19 18:01:47 +02:00
|
|
|
// ... which is useful while debugging/tracing.
|
2020-11-05 09:12:32 +01:00
|
|
|
//
|
|
|
|
// @<type> is allowed for keyword variable names. E.g. 'type'
|
|
|
|
pub enum AtKind {
|
|
|
|
unknown
|
|
|
|
fn_name
|
2021-02-05 15:30:58 +01:00
|
|
|
method_name
|
2020-11-05 09:12:32 +01:00
|
|
|
mod_name
|
|
|
|
struct_name
|
|
|
|
vexe_path
|
|
|
|
file_path
|
|
|
|
line_nr
|
|
|
|
column_nr
|
|
|
|
vhash
|
|
|
|
vmod_file
|
2021-04-19 18:01:47 +02:00
|
|
|
vmodroot_path
|
|
|
|
vroot_path // obsolete
|
|
|
|
vexeroot_path
|
2020-11-05 09:12:32 +01:00
|
|
|
}
|
2020-11-30 03:11:37 +01:00
|
|
|
|
2021-10-28 14:09:41 +02:00
|
|
|
pub const valid_at_tokens = ['@VROOT', '@VMODROOT', '@VEXEROOT', '@FN', '@METHOD', '@MOD', '@STRUCT',
|
|
|
|
'@VEXE', '@FILE', '@LINE', '@COLUMN', '@VHASH', '@VMOD_FILE']
|
2020-11-05 09:12:32 +01:00
|
|
|
|
2019-12-22 02:34:37 +01:00
|
|
|
// build_keys genereates a map with keywords' string values:
|
|
|
|
// Keywords['return'] == .key_return
|
2020-06-06 11:49:50 +02:00
|
|
|
fn build_keys() map[string]Kind {
|
2020-11-30 03:11:37 +01:00
|
|
|
mut res := map[string]Kind{}
|
2020-04-01 16:50:56 +02:00
|
|
|
for t in int(Kind.keyword_beg) + 1 .. int(Kind.keyword_end) {
|
2021-02-04 08:18:38 +01:00
|
|
|
key := token.token_str[t]
|
2021-01-08 17:41:52 +01:00
|
|
|
res[key] = Kind(t)
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
return res
|
|
|
|
}
|
|
|
|
|
2019-12-31 10:53:30 +01:00
|
|
|
// TODO remove once we have `enum Kind { name('name') if('if') ... }`
|
2019-12-22 02:34:37 +01:00
|
|
|
fn build_token_str() []string {
|
2021-02-04 08:18:38 +01:00
|
|
|
mut s := []string{len: token.nr_tokens}
|
2020-06-06 11:49:50 +02:00
|
|
|
s[Kind.unknown] = 'unknown'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.eof] = 'eof'
|
|
|
|
s[Kind.name] = 'name'
|
|
|
|
s[Kind.number] = 'number'
|
2020-05-07 16:26:22 +02:00
|
|
|
s[Kind.string] = 'string'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.chartoken] = 'char'
|
|
|
|
s[Kind.plus] = '+'
|
|
|
|
s[Kind.minus] = '-'
|
|
|
|
s[Kind.mul] = '*'
|
|
|
|
s[Kind.div] = '/'
|
|
|
|
s[Kind.mod] = '%'
|
|
|
|
s[Kind.xor] = '^'
|
|
|
|
s[Kind.bit_not] = '~'
|
|
|
|
s[Kind.pipe] = '|'
|
|
|
|
s[Kind.hash] = '#'
|
|
|
|
s[Kind.amp] = '&'
|
|
|
|
s[Kind.inc] = '++'
|
|
|
|
s[Kind.dec] = '--'
|
|
|
|
s[Kind.and] = '&&'
|
|
|
|
s[Kind.logical_or] = '||'
|
|
|
|
s[Kind.not] = '!'
|
|
|
|
s[Kind.dot] = '.'
|
|
|
|
s[Kind.dotdot] = '..'
|
|
|
|
s[Kind.ellipsis] = '...'
|
|
|
|
s[Kind.comma] = ','
|
2020-04-11 21:31:54 +02:00
|
|
|
s[Kind.not_in] = '!in'
|
2020-06-02 16:18:12 +02:00
|
|
|
s[Kind.not_is] = '!is'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.semicolon] = ';'
|
|
|
|
s[Kind.colon] = ':'
|
2020-08-17 20:12:00 +02:00
|
|
|
s[Kind.arrow] = '<-'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.assign] = '='
|
|
|
|
s[Kind.decl_assign] = ':='
|
|
|
|
s[Kind.plus_assign] = '+='
|
|
|
|
s[Kind.minus_assign] = '-='
|
|
|
|
s[Kind.mult_assign] = '*='
|
|
|
|
s[Kind.div_assign] = '/='
|
|
|
|
s[Kind.xor_assign] = '^='
|
|
|
|
s[Kind.mod_assign] = '%='
|
|
|
|
s[Kind.or_assign] = '|='
|
|
|
|
s[Kind.and_assign] = '&='
|
2020-02-28 17:16:24 +01:00
|
|
|
s[Kind.right_shift_assign] = '>>='
|
2021-09-21 13:02:17 +02:00
|
|
|
s[Kind.unsigned_right_shift_assign] = '>>>='
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.left_shift_assign] = '<<='
|
|
|
|
s[Kind.lcbr] = '{'
|
|
|
|
s[Kind.rcbr] = '}'
|
|
|
|
s[Kind.lpar] = '('
|
|
|
|
s[Kind.rpar] = ')'
|
|
|
|
s[Kind.lsbr] = '['
|
2021-12-22 14:34:02 +01:00
|
|
|
s[Kind.nilsbr] = '#['
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.rsbr] = ']'
|
|
|
|
s[Kind.eq] = '=='
|
|
|
|
s[Kind.ne] = '!='
|
|
|
|
s[Kind.gt] = '>'
|
|
|
|
s[Kind.lt] = '<'
|
|
|
|
s[Kind.ge] = '>='
|
|
|
|
s[Kind.le] = '<='
|
|
|
|
s[Kind.question] = '?'
|
|
|
|
s[Kind.left_shift] = '<<'
|
2020-02-04 12:50:58 +01:00
|
|
|
s[Kind.right_shift] = '>>'
|
2021-09-21 13:02:17 +02:00
|
|
|
s[Kind.unsigned_right_shift] = '>>>'
|
2021-01-10 11:19:59 +01:00
|
|
|
s[Kind.comment] = 'comment'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.nl] = 'NLL'
|
|
|
|
s[Kind.dollar] = '$'
|
2020-11-05 09:12:32 +01:00
|
|
|
s[Kind.at] = '@'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.str_dollar] = '$2'
|
|
|
|
s[Kind.key_assert] = 'assert'
|
|
|
|
s[Kind.key_struct] = 'struct'
|
|
|
|
s[Kind.key_if] = 'if'
|
|
|
|
// s[Kind.key_it] = 'it'
|
|
|
|
s[Kind.key_else] = 'else'
|
|
|
|
s[Kind.key_asm] = 'asm'
|
|
|
|
s[Kind.key_return] = 'return'
|
|
|
|
s[Kind.key_module] = 'module'
|
|
|
|
s[Kind.key_sizeof] = 'sizeof'
|
2021-06-13 05:26:13 +02:00
|
|
|
s[Kind.key_isreftype] = 'isreftype'
|
2020-06-09 16:36:18 +02:00
|
|
|
s[Kind.key_likely] = '_likely_'
|
2020-06-09 17:08:31 +02:00
|
|
|
s[Kind.key_unlikely] = '_unlikely_'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.key_go] = 'go'
|
|
|
|
s[Kind.key_goto] = 'goto'
|
|
|
|
s[Kind.key_const] = 'const'
|
|
|
|
s[Kind.key_mut] = 'mut'
|
2020-07-04 12:44:25 +02:00
|
|
|
s[Kind.key_shared] = 'shared'
|
|
|
|
s[Kind.key_lock] = 'lock'
|
|
|
|
s[Kind.key_rlock] = 'rlock'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.key_type] = 'type'
|
|
|
|
s[Kind.key_for] = 'for'
|
|
|
|
s[Kind.key_fn] = 'fn'
|
|
|
|
s[Kind.key_true] = 'true'
|
|
|
|
s[Kind.key_false] = 'false'
|
|
|
|
s[Kind.key_continue] = 'continue'
|
|
|
|
s[Kind.key_break] = 'break'
|
|
|
|
s[Kind.key_import] = 'import'
|
|
|
|
s[Kind.key_unsafe] = 'unsafe'
|
2020-03-19 12:15:39 +01:00
|
|
|
s[Kind.key_typeof] = 'typeof'
|
2021-03-06 18:09:28 +01:00
|
|
|
s[Kind.key_dump] = 'dump'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.key_enum] = 'enum'
|
|
|
|
s[Kind.key_interface] = 'interface'
|
|
|
|
s[Kind.key_pub] = 'pub'
|
|
|
|
s[Kind.key_in] = 'in'
|
|
|
|
s[Kind.key_atomic] = 'atomic'
|
|
|
|
s[Kind.key_orelse] = 'or'
|
|
|
|
s[Kind.key_global] = '__global'
|
|
|
|
s[Kind.key_union] = 'union'
|
|
|
|
s[Kind.key_static] = 'static'
|
2021-09-22 12:06:30 +02:00
|
|
|
s[Kind.key_volatile] = 'volatile'
|
2019-12-31 10:53:30 +01:00
|
|
|
s[Kind.key_as] = 'as'
|
|
|
|
s[Kind.key_defer] = 'defer'
|
|
|
|
s[Kind.key_match] = 'match'
|
|
|
|
s[Kind.key_select] = 'select'
|
|
|
|
s[Kind.key_none] = 'none'
|
|
|
|
s[Kind.key_offsetof] = '__offsetof'
|
2020-04-16 15:32:11 +02:00
|
|
|
s[Kind.key_is] = 'is'
|
2022-03-07 17:07:14 +01:00
|
|
|
// The following kinds are not for tokens returned by the V scanner.
|
|
|
|
// They are used just for organisation/ease of checking:
|
|
|
|
s[Kind.keyword_beg] = 'keyword_beg'
|
|
|
|
s[Kind.keyword_end] = 'keyword_end'
|
|
|
|
s[Kind.str_inter] = 'str_inter'
|
|
|
|
$if debug_build_token_str ? {
|
|
|
|
for k, v in s {
|
|
|
|
if v == '' {
|
|
|
|
eprintln('>>> ${@MOD}.${@METHOD} missing k: $k | .${kind_to_string(Kind(k))}')
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2019-12-22 02:34:37 +01:00
|
|
|
return s
|
|
|
|
}
|
|
|
|
|
2022-03-07 17:07:14 +01:00
|
|
|
pub const token_str = build_token_str()
|
2021-02-03 09:17:13 +01:00
|
|
|
|
2021-10-28 14:09:41 +02:00
|
|
|
pub const keywords = build_keys()
|
|
|
|
|
2021-11-07 15:02:37 +01:00
|
|
|
pub const matcher = new_keywords_matcher<Kind>(keywords)
|
2019-12-22 02:34:37 +01:00
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-22 02:34:37 +01:00
|
|
|
pub fn is_key(key string) bool {
|
2021-05-31 13:21:06 +02:00
|
|
|
return int(token.keywords[key]) > 0
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-31 10:53:30 +01:00
|
|
|
pub fn is_decl(t Kind) bool {
|
2021-02-04 08:18:38 +01:00
|
|
|
return t in [.key_enum, .key_interface, .key_fn, .key_struct, .key_type, .key_const, .key_pub,
|
2021-09-21 15:20:09 +02:00
|
|
|
.eof]
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2020-01-06 16:13:12 +01:00
|
|
|
pub fn (t Kind) is_assign() bool {
|
2021-02-04 08:18:38 +01:00
|
|
|
return t in token.assign_tokens
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2021-02-09 16:07:30 +01:00
|
|
|
// note: used for some code generation, so no quoting
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-31 10:53:30 +01:00
|
|
|
pub fn (t Kind) str() string {
|
2021-02-04 08:18:38 +01:00
|
|
|
return token.token_str[int(t)]
|
2019-12-22 02:34:37 +01:00
|
|
|
}
|
|
|
|
|
2019-12-28 09:15:32 +01:00
|
|
|
pub fn (t Token) str() string {
|
2021-02-07 03:40:00 +01:00
|
|
|
mut s := t.kind.str()
|
|
|
|
if s.len == 0 {
|
|
|
|
eprintln('missing token kind string')
|
2021-02-09 16:07:30 +01:00
|
|
|
} else if !s[0].is_letter() {
|
2021-02-07 03:40:00 +01:00
|
|
|
// punctuation, operators
|
2021-02-09 16:07:30 +01:00
|
|
|
return 'token `$s`'
|
|
|
|
}
|
|
|
|
if is_key(t.lit) {
|
|
|
|
s = 'keyword'
|
|
|
|
}
|
|
|
|
if t.lit != '' {
|
|
|
|
// string contents etc
|
|
|
|
s += ' `$t.lit`'
|
2021-02-07 03:40:00 +01:00
|
|
|
}
|
|
|
|
return s
|
2019-12-28 09:15:32 +01:00
|
|
|
}
|
|
|
|
|
2022-03-07 17:07:14 +01:00
|
|
|
pub fn (t Token) debug() string {
|
|
|
|
ks := kind_to_string(t.kind)
|
|
|
|
s := if t.lit == '' { t.kind.str() } else { t.lit }
|
|
|
|
return 'tok: .${ks:-12} | lit: `$s`'
|
|
|
|
}
|
|
|
|
|
2019-12-25 13:39:58 +01:00
|
|
|
// Representation of highest and lowest precedence
|
2020-02-20 12:16:18 +01:00
|
|
|
/*
|
2021-10-28 14:09:41 +02:00
|
|
|
pub const lowest_prec = 0
|
|
|
|
pub const highest_prec = 8
|
2020-02-20 12:16:18 +01:00
|
|
|
*/
|
2020-01-06 16:13:12 +01:00
|
|
|
pub enum Precedence {
|
|
|
|
lowest
|
|
|
|
cond // OR or AND
|
2020-02-20 12:16:18 +01:00
|
|
|
in_as
|
2020-01-06 16:13:12 +01:00
|
|
|
assign // =
|
|
|
|
eq // == or !=
|
2020-02-20 12:16:18 +01:00
|
|
|
// less_greater // > or <
|
2020-04-08 17:21:36 +02:00
|
|
|
sum // + - | ^
|
2021-09-21 13:02:17 +02:00
|
|
|
product // * / << >> >>> &
|
2020-02-20 12:16:18 +01:00
|
|
|
// mod // %
|
2020-01-06 16:13:12 +01:00
|
|
|
prefix // -X or !X
|
2020-04-08 13:53:11 +02:00
|
|
|
postfix // ++ or --
|
2020-01-06 16:13:12 +01:00
|
|
|
call // func(X) or foo.method(X)
|
|
|
|
index // array[index], map[key]
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn build_precedences() []Precedence {
|
2020-12-06 16:48:23 +01:00
|
|
|
mut p := []Precedence{len: int(Kind._end_)}
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.lsbr] = .index
|
2021-12-22 14:34:02 +01:00
|
|
|
p[Kind.nilsbr] = .index
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.dot] = .call
|
2020-09-18 00:58:54 +02:00
|
|
|
// `++` | `--` | `?`
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.inc] = .postfix
|
|
|
|
p[Kind.dec] = .postfix
|
2020-09-18 00:58:54 +02:00
|
|
|
p[Kind.question] = .postfix
|
2021-09-21 13:02:17 +02:00
|
|
|
// `*` | `/` | `%` | `<<` | `>>` | `>>>` | `&`
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.mul] = .product
|
|
|
|
p[Kind.div] = .product
|
|
|
|
p[Kind.mod] = .product
|
|
|
|
p[Kind.left_shift] = .product
|
|
|
|
p[Kind.right_shift] = .product
|
2021-09-21 13:02:17 +02:00
|
|
|
p[Kind.unsigned_right_shift] = .product
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.amp] = .product
|
2020-08-17 20:12:00 +02:00
|
|
|
p[Kind.arrow] = .product
|
2020-06-25 11:36:13 +02:00
|
|
|
// `+` | `-` | `|` | `^`
|
2020-01-06 16:13:12 +01:00
|
|
|
p[Kind.plus] = .sum
|
|
|
|
p[Kind.minus] = .sum
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.pipe] = .sum
|
|
|
|
p[Kind.xor] = .sum
|
|
|
|
// `==` | `!=` | `<` | `<=` | `>` | `>=`
|
|
|
|
p[Kind.eq] = .eq
|
|
|
|
p[Kind.ne] = .eq
|
|
|
|
p[Kind.lt] = .eq
|
|
|
|
p[Kind.le] = .eq
|
|
|
|
p[Kind.gt] = .eq
|
|
|
|
p[Kind.ge] = .eq
|
|
|
|
// `=` | `+=` | ...
|
|
|
|
p[Kind.assign] = .assign
|
|
|
|
p[Kind.plus_assign] = .assign
|
|
|
|
p[Kind.minus_assign] = .assign
|
|
|
|
p[Kind.div_assign] = .assign
|
|
|
|
p[Kind.mod_assign] = .assign
|
|
|
|
p[Kind.or_assign] = .assign
|
|
|
|
p[Kind.and_assign] = .assign
|
|
|
|
// <<= | *= | ...
|
|
|
|
p[Kind.left_shift_assign] = .assign
|
|
|
|
p[Kind.right_shift_assign] = .assign
|
2021-09-21 13:02:17 +02:00
|
|
|
p[Kind.unsigned_right_shift_assign] = .assign
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.mult_assign] = .assign
|
|
|
|
p[Kind.xor_assign] = .assign
|
|
|
|
p[Kind.key_in] = .in_as
|
|
|
|
p[Kind.not_in] = .in_as
|
|
|
|
p[Kind.key_as] = .in_as
|
|
|
|
p[Kind.key_is] = .in_as
|
|
|
|
p[Kind.not_is] = .in_as
|
2020-01-06 16:13:12 +01:00
|
|
|
p[Kind.logical_or] = .cond
|
2020-06-25 11:36:13 +02:00
|
|
|
p[Kind.and] = .cond
|
2020-01-06 16:13:12 +01:00
|
|
|
return p
|
|
|
|
}
|
|
|
|
|
2021-10-28 14:09:41 +02:00
|
|
|
const precedences = build_precedences()
|
2020-06-25 11:36:13 +02:00
|
|
|
|
2020-01-06 16:13:12 +01:00
|
|
|
// precedence returns a tokens precedence if defined, otherwise lowest_prec
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-25 13:39:58 +01:00
|
|
|
pub fn (tok Token) precedence() int {
|
2021-02-04 08:18:38 +01:00
|
|
|
return int(token.precedences[tok.kind])
|
2019-12-25 13:39:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// is_scalar returns true if the token is a scalar
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-25 13:39:58 +01:00
|
|
|
pub fn (tok Token) is_scalar() bool {
|
2020-03-15 00:46:08 +01:00
|
|
|
return tok.kind in [.number, .string]
|
2019-12-25 13:39:58 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// is_unary returns true if the token can be in a unary expression
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2019-12-25 13:39:58 +01:00
|
|
|
pub fn (tok Token) is_unary() bool {
|
2021-01-23 09:33:22 +01:00
|
|
|
// `+` | `-` | `!` | `~` | `*` | `&` | `<-`
|
2021-02-04 08:18:38 +01:00
|
|
|
return tok.kind in [.plus, .minus, .not, .bit_not, .mul, .amp, .arrow]
|
2019-12-25 13:39:58 +01:00
|
|
|
}
|
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2020-01-06 16:13:12 +01:00
|
|
|
pub fn (tok Kind) is_relational() bool {
|
2021-01-23 09:33:22 +01:00
|
|
|
// `<` | `<=` | `>` | `>=` | `==` | `!=`
|
|
|
|
return tok in [.lt, .le, .gt, .ge, .eq, .ne]
|
2019-12-30 15:06:56 +01:00
|
|
|
}
|
2020-01-06 16:13:12 +01:00
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2020-02-11 13:21:41 +01:00
|
|
|
pub fn (k Kind) is_start_of_type() bool {
|
2021-02-06 19:41:52 +01:00
|
|
|
return k in [.name, .lpar, .amp, .lsbr, .question, .key_shared]
|
2020-02-11 13:21:41 +01:00
|
|
|
}
|
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2020-09-29 03:13:10 +02:00
|
|
|
pub fn (kind Kind) is_prefix() bool {
|
|
|
|
return kind in [.minus, .amp, .mul, .not, .bit_not]
|
|
|
|
}
|
|
|
|
|
2021-05-31 13:21:06 +02:00
|
|
|
[inline]
|
2020-01-06 16:13:12 +01:00
|
|
|
pub fn (kind Kind) is_infix() bool {
|
2021-02-04 08:18:38 +01:00
|
|
|
return kind in [.plus, .minus, .mod, .mul, .div, .eq, .ne, .gt, .lt, .key_in, .key_as, .ge,
|
|
|
|
.le, .logical_or, .xor, .not_in, .key_is, .not_is, .and, .dot, .pipe, .amp, .left_shift,
|
2021-09-21 13:02:17 +02:00
|
|
|
.right_shift, .unsigned_right_shift, .arrow]
|
2020-01-06 16:13:12 +01:00
|
|
|
}
|
2022-03-07 17:07:14 +01:00
|
|
|
|
2022-04-04 08:21:54 +02:00
|
|
|
[inline]
|
|
|
|
pub fn (kind Kind) is_postfix() bool {
|
|
|
|
return kind in [.inc, .dec, .question]
|
|
|
|
}
|
|
|
|
|
2022-03-07 17:07:14 +01:00
|
|
|
pub fn kind_to_string(k Kind) string {
|
|
|
|
return match k {
|
|
|
|
.unknown { 'unknown' }
|
|
|
|
.eof { 'eof' }
|
|
|
|
.name { 'name' }
|
|
|
|
.number { 'number' }
|
|
|
|
.string { 'string' }
|
|
|
|
.str_inter { 'str_inter' }
|
|
|
|
.chartoken { 'chartoken' }
|
|
|
|
.plus { 'plus' }
|
|
|
|
.minus { 'minus' }
|
|
|
|
.mul { 'mul' }
|
|
|
|
.div { 'div' }
|
|
|
|
.mod { 'mod' }
|
|
|
|
.xor { 'xor' }
|
|
|
|
.pipe { 'pipe' }
|
|
|
|
.inc { 'inc' }
|
|
|
|
.dec { 'dec' }
|
|
|
|
.and { 'and' }
|
|
|
|
.logical_or { 'logical_or' }
|
|
|
|
.not { 'not' }
|
|
|
|
.bit_not { 'bit_not' }
|
|
|
|
.question { 'question' }
|
|
|
|
.comma { 'comma' }
|
|
|
|
.semicolon { 'semicolon' }
|
|
|
|
.colon { 'colon' }
|
|
|
|
.arrow { 'arrow' }
|
|
|
|
.amp { 'amp' }
|
|
|
|
.hash { 'hash' }
|
|
|
|
.dollar { 'dollar' }
|
|
|
|
.at { 'at' }
|
|
|
|
.str_dollar { 'str_dollar' }
|
|
|
|
.left_shift { 'left_shift' }
|
|
|
|
.right_shift { 'right_shift' }
|
|
|
|
.unsigned_right_shift { 'unsigned_right_shift' }
|
|
|
|
.not_in { 'not_in' }
|
|
|
|
.not_is { 'not_is' }
|
|
|
|
.assign { 'assign' }
|
|
|
|
.decl_assign { 'decl_assign' }
|
|
|
|
.plus_assign { 'plus_assign' }
|
|
|
|
.minus_assign { 'minus_assign' }
|
|
|
|
.div_assign { 'div_assign' }
|
|
|
|
.mult_assign { 'mult_assign' }
|
|
|
|
.xor_assign { 'xor_assign' }
|
|
|
|
.mod_assign { 'mod_assign' }
|
|
|
|
.or_assign { 'or_assign' }
|
|
|
|
.and_assign { 'and_assign' }
|
|
|
|
.right_shift_assign { 'right_shift_assign' }
|
|
|
|
.left_shift_assign { 'left_shift_assign' }
|
|
|
|
.unsigned_right_shift_assign { 'unsigned_right_shift_assign' }
|
|
|
|
.lcbr { 'lcbr' }
|
|
|
|
.rcbr { 'rcbr' }
|
|
|
|
.lpar { 'lpar' }
|
|
|
|
.rpar { 'rpar' }
|
|
|
|
.lsbr { 'lsbr' }
|
|
|
|
.nilsbr { 'nilsbr' }
|
|
|
|
.rsbr { 'rsbr' }
|
|
|
|
.eq { 'eq' }
|
|
|
|
.ne { 'ne' }
|
|
|
|
.gt { 'gt' }
|
|
|
|
.lt { 'lt' }
|
|
|
|
.ge { 'ge' }
|
|
|
|
.le { 'le' }
|
|
|
|
.comment { 'comment' }
|
|
|
|
.nl { 'nl' }
|
|
|
|
.dot { 'dot' }
|
|
|
|
.dotdot { 'dotdot' }
|
|
|
|
.ellipsis { 'ellipsis' }
|
|
|
|
.keyword_beg { 'keyword_beg' }
|
|
|
|
.key_as { 'key_as' }
|
|
|
|
.key_asm { 'key_asm' }
|
|
|
|
.key_assert { 'key_assert' }
|
|
|
|
.key_atomic { 'key_atomic' }
|
|
|
|
.key_break { 'key_break' }
|
|
|
|
.key_const { 'key_const' }
|
|
|
|
.key_continue { 'key_continue' }
|
|
|
|
.key_defer { 'key_defer' }
|
|
|
|
.key_else { 'key_else' }
|
|
|
|
.key_enum { 'key_enum' }
|
|
|
|
.key_false { 'key_false' }
|
|
|
|
.key_for { 'key_for' }
|
|
|
|
.key_fn { 'key_fn' }
|
|
|
|
.key_global { 'key_global' }
|
|
|
|
.key_go { 'key_go' }
|
|
|
|
.key_goto { 'key_goto' }
|
|
|
|
.key_if { 'key_if' }
|
|
|
|
.key_import { 'key_import' }
|
|
|
|
.key_in { 'key_in' }
|
|
|
|
.key_interface { 'key_interface' }
|
|
|
|
.key_is { 'key_is' }
|
|
|
|
.key_match { 'key_match' }
|
|
|
|
.key_module { 'key_module' }
|
|
|
|
.key_mut { 'key_mut' }
|
|
|
|
.key_shared { 'key_shared' }
|
|
|
|
.key_lock { 'key_lock' }
|
|
|
|
.key_rlock { 'key_rlock' }
|
|
|
|
.key_none { 'key_none' }
|
|
|
|
.key_return { 'key_return' }
|
|
|
|
.key_select { 'key_select' }
|
|
|
|
.key_sizeof { 'key_sizeof' }
|
|
|
|
.key_isreftype { 'key_isreftype' }
|
|
|
|
.key_likely { 'key_likely' }
|
|
|
|
.key_unlikely { 'key_unlikely' }
|
|
|
|
.key_offsetof { 'key_offsetof' }
|
|
|
|
.key_struct { 'key_struct' }
|
|
|
|
.key_true { 'key_true' }
|
|
|
|
.key_type { 'key_type' }
|
|
|
|
.key_typeof { 'key_typeof' }
|
|
|
|
.key_dump { 'key_dump' }
|
|
|
|
.key_orelse { 'key_orelse' }
|
|
|
|
.key_union { 'key_union' }
|
|
|
|
.key_pub { 'key_pub' }
|
|
|
|
.key_static { 'key_static' }
|
|
|
|
.key_volatile { 'key_volatile' }
|
|
|
|
.key_unsafe { 'key_unsafe' }
|
|
|
|
.keyword_end { 'keyword_end' }
|
|
|
|
._end_ { '_end_' }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn kind_from_string(s string) ?Kind {
|
|
|
|
match s {
|
|
|
|
'unknown' { return .unknown }
|
|
|
|
'eof' { return .eof }
|
|
|
|
'name' { return .name }
|
|
|
|
'number' { return .number }
|
|
|
|
'string' { return .string }
|
|
|
|
'str_inter' { return .str_inter }
|
|
|
|
'chartoken' { return .chartoken }
|
|
|
|
'plus' { return .plus }
|
|
|
|
'minus' { return .minus }
|
|
|
|
'mul' { return .mul }
|
|
|
|
'div' { return .div }
|
|
|
|
'mod' { return .mod }
|
|
|
|
'xor' { return .xor }
|
|
|
|
'pipe' { return .pipe }
|
|
|
|
'inc' { return .inc }
|
|
|
|
'dec' { return .dec }
|
|
|
|
'and' { return .and }
|
|
|
|
'logical_or' { return .logical_or }
|
|
|
|
'not' { return .not }
|
|
|
|
'bit_not' { return .bit_not }
|
|
|
|
'question' { return .question }
|
|
|
|
'comma' { return .comma }
|
|
|
|
'semicolon' { return .semicolon }
|
|
|
|
'colon' { return .colon }
|
|
|
|
'arrow' { return .arrow }
|
|
|
|
'amp' { return .amp }
|
|
|
|
'hash' { return .hash }
|
|
|
|
'dollar' { return .dollar }
|
|
|
|
'at' { return .at }
|
|
|
|
'str_dollar' { return .str_dollar }
|
|
|
|
'left_shift' { return .left_shift }
|
|
|
|
'right_shift' { return .right_shift }
|
|
|
|
'unsigned_right_shift' { return .unsigned_right_shift }
|
|
|
|
'not_in' { return .not_in }
|
|
|
|
'not_is' { return .not_is }
|
|
|
|
'assign' { return .assign }
|
|
|
|
'decl_assign' { return .decl_assign }
|
|
|
|
'plus_assign' { return .plus_assign }
|
|
|
|
'minus_assign' { return .minus_assign }
|
|
|
|
'div_assign' { return .div_assign }
|
|
|
|
'mult_assign' { return .mult_assign }
|
|
|
|
'xor_assign' { return .xor_assign }
|
|
|
|
'mod_assign' { return .mod_assign }
|
|
|
|
'or_assign' { return .or_assign }
|
|
|
|
'and_assign' { return .and_assign }
|
|
|
|
'right_shift_assign' { return .right_shift_assign }
|
|
|
|
'left_shift_assign' { return .left_shift_assign }
|
|
|
|
'unsigned_right_shift_assign' { return .unsigned_right_shift_assign }
|
|
|
|
'lcbr' { return .lcbr }
|
|
|
|
'rcbr' { return .rcbr }
|
|
|
|
'lpar' { return .lpar }
|
|
|
|
'rpar' { return .rpar }
|
|
|
|
'lsbr' { return .lsbr }
|
|
|
|
'nilsbr' { return .nilsbr }
|
|
|
|
'rsbr' { return .rsbr }
|
|
|
|
'eq' { return .eq }
|
|
|
|
'ne' { return .ne }
|
|
|
|
'gt' { return .gt }
|
|
|
|
'lt' { return .lt }
|
|
|
|
'ge' { return .ge }
|
|
|
|
'le' { return .le }
|
|
|
|
'comment' { return .comment }
|
|
|
|
'nl' { return .nl }
|
|
|
|
'dot' { return .dot }
|
|
|
|
'dotdot' { return .dotdot }
|
|
|
|
'ellipsis' { return .ellipsis }
|
|
|
|
'keyword_beg' { return .keyword_beg }
|
|
|
|
'key_as' { return .key_as }
|
|
|
|
'key_asm' { return .key_asm }
|
|
|
|
'key_assert' { return .key_assert }
|
|
|
|
'key_atomic' { return .key_atomic }
|
|
|
|
'key_break' { return .key_break }
|
|
|
|
'key_const' { return .key_const }
|
|
|
|
'key_continue' { return .key_continue }
|
|
|
|
'key_defer' { return .key_defer }
|
|
|
|
'key_else' { return .key_else }
|
|
|
|
'key_enum' { return .key_enum }
|
|
|
|
'key_false' { return .key_false }
|
|
|
|
'key_for' { return .key_for }
|
|
|
|
'key_fn' { return .key_fn }
|
|
|
|
'key_global' { return .key_global }
|
|
|
|
'key_go' { return .key_go }
|
|
|
|
'key_goto' { return .key_goto }
|
|
|
|
'key_if' { return .key_if }
|
|
|
|
'key_import' { return .key_import }
|
|
|
|
'key_in' { return .key_in }
|
|
|
|
'key_interface' { return .key_interface }
|
|
|
|
'key_is' { return .key_is }
|
|
|
|
'key_match' { return .key_match }
|
|
|
|
'key_module' { return .key_module }
|
|
|
|
'key_mut' { return .key_mut }
|
|
|
|
'key_shared' { return .key_shared }
|
|
|
|
'key_lock' { return .key_lock }
|
|
|
|
'key_rlock' { return .key_rlock }
|
|
|
|
'key_none' { return .key_none }
|
|
|
|
'key_return' { return .key_return }
|
|
|
|
'key_select' { return .key_select }
|
|
|
|
'key_sizeof' { return .key_sizeof }
|
|
|
|
'key_isreftype' { return .key_isreftype }
|
|
|
|
'key_likely' { return .key_likely }
|
|
|
|
'key_unlikely' { return .key_unlikely }
|
|
|
|
'key_offsetof' { return .key_offsetof }
|
|
|
|
'key_struct' { return .key_struct }
|
|
|
|
'key_true' { return .key_true }
|
|
|
|
'key_type' { return .key_type }
|
|
|
|
'key_typeof' { return .key_typeof }
|
|
|
|
'key_dump' { return .key_dump }
|
|
|
|
'key_orelse' { return .key_orelse }
|
|
|
|
'key_union' { return .key_union }
|
|
|
|
'key_pub' { return .key_pub }
|
|
|
|
'key_static' { return .key_static }
|
|
|
|
'key_volatile' { return .key_volatile }
|
|
|
|
'key_unsafe' { return .key_unsafe }
|
|
|
|
'keyword_end' { return .keyword_end }
|
|
|
|
'_end_' { return ._end_ }
|
|
|
|
else { return error('unknown') }
|
|
|
|
}
|
|
|
|
}
|