vfmt: format scanner.v
parent
5b93b4f37d
commit
d2a2db7bff
|
@ -12,8 +12,8 @@ import v.vmod
|
||||||
const (
|
const (
|
||||||
single_quote = `\'`
|
single_quote = `\'`
|
||||||
double_quote = `"`
|
double_quote = `"`
|
||||||
// char used as number separator
|
// char used as number separator
|
||||||
num_sep = `_`
|
num_sep = `_`
|
||||||
)
|
)
|
||||||
|
|
||||||
pub struct Scanner {
|
pub struct Scanner {
|
||||||
|
@ -49,6 +49,7 @@ pub mut:
|
||||||
tidx int
|
tidx int
|
||||||
eofs int
|
eofs int
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
How the .toplevel_comments mode works:
|
How the .toplevel_comments mode works:
|
||||||
|
|
||||||
|
@ -76,7 +77,6 @@ to true, again refilling the lookahead buffer => calling .next() in this
|
||||||
mode, will again ignore all the comment tokens, till the top level statement
|
mode, will again ignore all the comment tokens, till the top level statement
|
||||||
is finished.
|
is finished.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// The different kinds of scanner modes:
|
// The different kinds of scanner modes:
|
||||||
//
|
//
|
||||||
// .skip_comments - simplest/fastest, just ignores all comments early.
|
// .skip_comments - simplest/fastest, just ignores all comments early.
|
||||||
|
@ -98,7 +98,7 @@ pub fn new_scanner_file(file_path string, comments_mode CommentsMode, is_fmt boo
|
||||||
if !os.exists(file_path) {
|
if !os.exists(file_path) {
|
||||||
verror("$file_path doesn't exist")
|
verror("$file_path doesn't exist")
|
||||||
}
|
}
|
||||||
raw_text := util.read_file( file_path ) or {
|
raw_text := util.read_file(file_path) or {
|
||||||
verror(err)
|
verror(err)
|
||||||
return voidptr(0)
|
return voidptr(0)
|
||||||
}
|
}
|
||||||
|
@ -121,22 +121,24 @@ pub fn new_scanner(text string, comments_mode CommentsMode, is_fmt bool) &Scanne
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[inline]
|
[inline]
|
||||||
fn (s &Scanner) should_parse_comment() bool {
|
fn (s &Scanner) should_parse_comment() bool {
|
||||||
res := (s.comments_mode == .parse_comments) || (s.comments_mode == .toplevel_comments && !s.is_inside_toplvl_statement)
|
res := (s.comments_mode == .parse_comments) ||
|
||||||
|
(s.comments_mode == .toplevel_comments && !s.is_inside_toplvl_statement)
|
||||||
return res
|
return res
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB: this is called by v's parser
|
// NB: this is called by v's parser
|
||||||
pub fn (mut s Scanner) set_is_inside_toplevel_statement(newstate bool) {
|
pub fn (mut s Scanner) set_is_inside_toplevel_statement(newstate bool) {
|
||||||
s.is_inside_toplvl_statement = newstate
|
s.is_inside_toplvl_statement = newstate
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut s Scanner) set_current_tidx(cidx int) {
|
pub fn (mut s Scanner) set_current_tidx(cidx int) {
|
||||||
mut tidx := if cidx < 0 { 0 } else { cidx }
|
mut tidx := if cidx < 0 { 0 } else { cidx }
|
||||||
tidx = if tidx > s.all_tokens.len { s.all_tokens.len } else { tidx }
|
tidx = if tidx > s.all_tokens.len { s.all_tokens.len } else { tidx }
|
||||||
s.tidx = tidx
|
s.tidx = tidx
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut s Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Token {
|
fn (mut s Scanner) new_token(tok_kind token.Kind, lit string, len int) token.Token {
|
||||||
cidx := s.tidx
|
cidx := s.tidx
|
||||||
s.tidx++
|
s.tidx++
|
||||||
|
@ -166,13 +168,10 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
pos++
|
pos++
|
||||||
|
|
||||||
if s.current_column() - 2 != 0 {
|
if s.current_column() - 2 != 0 {
|
||||||
return s.fn_name
|
return s.fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
has_struct_name := s.struct_name != ''
|
has_struct_name := s.struct_name != ''
|
||||||
|
|
||||||
if has_struct_name {
|
if has_struct_name {
|
||||||
for pos < s.text.len && s.text[pos] != `(` {
|
for pos < s.text.len && s.text[pos] != `(` {
|
||||||
pos++
|
pos++
|
||||||
|
@ -182,7 +181,6 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
}
|
}
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
|
|
||||||
for pos < s.text.len && s.text[pos] != `(` {
|
for pos < s.text.len && s.text[pos] != `(` {
|
||||||
pos++
|
pos++
|
||||||
}
|
}
|
||||||
|
@ -190,7 +188,6 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
pos--
|
pos--
|
||||||
|
|
||||||
// Eat whitespaces
|
// Eat whitespaces
|
||||||
for pos > start && s.text[pos].is_space() {
|
for pos > start && s.text[pos].is_space() {
|
||||||
pos--
|
pos--
|
||||||
|
@ -198,36 +195,31 @@ fn (mut s Scanner) ident_fn_name() string {
|
||||||
if pos < start {
|
if pos < start {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
end_pos := pos + 1
|
end_pos := pos + 1
|
||||||
|
|
||||||
pos--
|
pos--
|
||||||
// Search for the start position
|
// Search for the start position
|
||||||
for pos > start && util.is_func_char(s.text[pos]) {
|
for pos > start && util.is_func_char(s.text[pos]) {
|
||||||
pos--
|
pos--
|
||||||
}
|
}
|
||||||
pos++
|
pos++
|
||||||
|
|
||||||
start_pos := pos
|
start_pos := pos
|
||||||
|
if pos <= start || pos >= s.text.len {
|
||||||
if pos <= start || pos >= s.text.len {
|
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
if s.text[start_pos].is_digit() || end_pos > s.text.len || end_pos <= start_pos || end_pos <= start || start_pos < start {
|
if s.text[start_pos].is_digit() || end_pos > s.text.len ||
|
||||||
|
end_pos <= start_pos || end_pos <= start ||
|
||||||
|
start_pos < start {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_name := s.text[start_pos..end_pos]
|
fn_name := s.text[start_pos..end_pos]
|
||||||
return fn_name
|
return fn_name
|
||||||
}
|
}
|
||||||
|
|
||||||
// ident_mod_name look ahead and return name of module this file belongs to if possible, otherwise empty string
|
// ident_mod_name look ahead and return name of module this file belongs to if possible, otherwise empty string
|
||||||
fn (mut s Scanner) ident_mod_name() string {
|
fn (mut s Scanner) ident_mod_name() string {
|
||||||
|
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
pos++
|
pos++
|
||||||
|
|
||||||
// Eat whitespaces
|
// Eat whitespaces
|
||||||
for pos < s.text.len && s.text[pos].is_space() {
|
for pos < s.text.len && s.text[pos].is_space() {
|
||||||
pos++
|
pos++
|
||||||
|
@ -235,9 +227,7 @@ fn (mut s Scanner) ident_mod_name() string {
|
||||||
if pos >= s.text.len {
|
if pos >= s.text.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
start_pos := pos
|
start_pos := pos
|
||||||
|
|
||||||
// Search for next occurrence of a whitespace or newline
|
// Search for next occurrence of a whitespace or newline
|
||||||
for pos < s.text.len && !s.text[pos].is_space() && !util.is_nl(s.text[pos]) {
|
for pos < s.text.len && !s.text[pos].is_space() && !util.is_nl(s.text[pos]) {
|
||||||
pos++
|
pos++
|
||||||
|
@ -245,13 +235,10 @@ fn (mut s Scanner) ident_mod_name() string {
|
||||||
if pos >= s.text.len {
|
if pos >= s.text.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
end_pos := pos
|
end_pos := pos
|
||||||
|
|
||||||
if end_pos > s.text.len || end_pos <= start_pos || end_pos <= start || start_pos <= start {
|
if end_pos > s.text.len || end_pos <= start_pos || end_pos <= start || start_pos <= start {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
mod_name := s.text[start_pos..end_pos]
|
mod_name := s.text[start_pos..end_pos]
|
||||||
return mod_name
|
return mod_name
|
||||||
}
|
}
|
||||||
|
@ -260,14 +247,11 @@ fn (mut s Scanner) ident_mod_name() string {
|
||||||
fn (mut s Scanner) ident_struct_name() string {
|
fn (mut s Scanner) ident_struct_name() string {
|
||||||
start := s.pos
|
start := s.pos
|
||||||
mut pos := s.pos
|
mut pos := s.pos
|
||||||
|
|
||||||
// Return last known stuct_name encountered to avoid using high order/anonymous function definitions
|
// Return last known stuct_name encountered to avoid using high order/anonymous function definitions
|
||||||
if s.current_column() - 2 != 0 {
|
if s.current_column() - 2 != 0 {
|
||||||
return s.struct_name
|
return s.struct_name
|
||||||
}
|
}
|
||||||
|
|
||||||
pos++
|
pos++
|
||||||
|
|
||||||
// Eat whitespaces
|
// Eat whitespaces
|
||||||
for pos < s.text.len && s.text[pos].is_space() {
|
for pos < s.text.len && s.text[pos].is_space() {
|
||||||
pos++
|
pos++
|
||||||
|
@ -275,12 +259,10 @@ fn (mut s Scanner) ident_struct_name() string {
|
||||||
if pos >= s.text.len {
|
if pos >= s.text.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return if `(` is not the first character after "fn ..."
|
// Return if `(` is not the first character after "fn ..."
|
||||||
if s.text[pos] != `(` {
|
if s.text[pos] != `(` {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// Search for closing parenthesis
|
// Search for closing parenthesis
|
||||||
for pos < s.text.len && s.text[pos] != `)` {
|
for pos < s.text.len && s.text[pos] != `)` {
|
||||||
pos++
|
pos++
|
||||||
|
@ -288,7 +270,6 @@ fn (mut s Scanner) ident_struct_name() string {
|
||||||
if pos >= s.text.len {
|
if pos >= s.text.len {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
pos--
|
pos--
|
||||||
// Search backwards for end position of struct name
|
// Search backwards for end position of struct name
|
||||||
// Eat whitespaces
|
// Eat whitespaces
|
||||||
|
@ -299,7 +280,6 @@ fn (mut s Scanner) ident_struct_name() string {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
end_pos := pos + 1
|
end_pos := pos + 1
|
||||||
|
|
||||||
// Go back while we have a name character or digit
|
// Go back while we have a name character or digit
|
||||||
for pos > start && (util.is_name_char(s.text[pos]) || s.text[pos].is_digit()) {
|
for pos > start && (util.is_name_char(s.text[pos]) || s.text[pos].is_digit()) {
|
||||||
pos--
|
pos--
|
||||||
|
@ -307,30 +287,28 @@ fn (mut s Scanner) ident_struct_name() string {
|
||||||
if pos < start {
|
if pos < start {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
start_pos := pos + 1
|
start_pos := pos + 1
|
||||||
|
if s.text[start_pos].is_digit() || end_pos > s.text.len ||
|
||||||
if s.text[start_pos].is_digit() || end_pos > s.text.len || end_pos <= start_pos || end_pos <= start || start_pos <= start {
|
end_pos <= start_pos || end_pos <= start ||
|
||||||
|
start_pos <= start {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
struct_name := s.text[start_pos..end_pos]
|
struct_name := s.text[start_pos..end_pos]
|
||||||
return struct_name
|
return struct_name
|
||||||
}
|
}
|
||||||
|
|
||||||
fn filter_num_sep(txt byteptr, start int, end int) string {
|
fn filter_num_sep(txt byteptr, start, end int) string {
|
||||||
unsafe{
|
unsafe {
|
||||||
mut b := malloc(end - start + 1) // add a byte for the endstring 0
|
mut b := malloc(end - start + 1) // add a byte for the endstring 0
|
||||||
mut i := start
|
|
||||||
mut i1 := 0
|
mut i1 := 0
|
||||||
for i < end {
|
for i := start; i < end; i++ {
|
||||||
if txt[i] != num_sep {
|
if txt[i] != num_sep {
|
||||||
b[i1] = txt[i]
|
b[i1] = txt[i]
|
||||||
i1++
|
i1++
|
||||||
}
|
}
|
||||||
i++
|
|
||||||
}
|
}
|
||||||
b[i1] = 0 // C string compatibility
|
b[i1] = 0 // C string compatibility
|
||||||
return string(b,i1)
|
return string(b)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -345,8 +323,7 @@ fn (mut s Scanner) ident_bin_number() string {
|
||||||
if !c.is_bin_digit() && c != num_sep {
|
if !c.is_bin_digit() && c != num_sep {
|
||||||
if (!c.is_digit() && !c.is_letter()) || s.is_inside_string {
|
if (!c.is_digit() && !c.is_letter()) || s.is_inside_string {
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -357,10 +334,9 @@ fn (mut s Scanner) ident_bin_number() string {
|
||||||
if start_pos + 2 == s.pos {
|
if start_pos + 2 == s.pos {
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this binary is not provided')
|
s.error('number part of this binary is not provided')
|
||||||
}
|
} else if has_wrong_digit {
|
||||||
else if has_wrong_digit {
|
|
||||||
s.pos = first_wrong_digit_pos // adjust error position
|
s.pos = first_wrong_digit_pos // adjust error position
|
||||||
s.error('this binary number has unsuitable digit `${first_wrong_digit.str()}`')
|
s.error('this binary number has unsuitable digit `$first_wrong_digit.str()`')
|
||||||
}
|
}
|
||||||
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
||||||
s.pos--
|
s.pos--
|
||||||
|
@ -378,8 +354,7 @@ fn (mut s Scanner) ident_hex_number() string {
|
||||||
if !c.is_hex_digit() && c != num_sep {
|
if !c.is_hex_digit() && c != num_sep {
|
||||||
if !c.is_letter() || s.is_inside_string {
|
if !c.is_letter() || s.is_inside_string {
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -390,10 +365,9 @@ fn (mut s Scanner) ident_hex_number() string {
|
||||||
if start_pos + 2 == s.pos {
|
if start_pos + 2 == s.pos {
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this hexadecimal is not provided')
|
s.error('number part of this hexadecimal is not provided')
|
||||||
}
|
} else if has_wrong_digit {
|
||||||
else if has_wrong_digit {
|
|
||||||
s.pos = first_wrong_digit_pos // adjust error position
|
s.pos = first_wrong_digit_pos // adjust error position
|
||||||
s.error('this hexadecimal number has unsuitable digit `${first_wrong_digit.str()}`')
|
s.error('this hexadecimal number has unsuitable digit `$first_wrong_digit.str()`')
|
||||||
}
|
}
|
||||||
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
||||||
s.pos--
|
s.pos--
|
||||||
|
@ -411,8 +385,7 @@ fn (mut s Scanner) ident_oct_number() string {
|
||||||
if !c.is_oct_digit() && c != num_sep {
|
if !c.is_oct_digit() && c != num_sep {
|
||||||
if (!c.is_digit() && !c.is_letter()) || s.is_inside_string {
|
if (!c.is_digit() && !c.is_letter()) || s.is_inside_string {
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -423,10 +396,9 @@ fn (mut s Scanner) ident_oct_number() string {
|
||||||
if start_pos + 2 == s.pos {
|
if start_pos + 2 == s.pos {
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('number part of this octal is not provided')
|
s.error('number part of this octal is not provided')
|
||||||
}
|
} else if has_wrong_digit {
|
||||||
else if has_wrong_digit {
|
|
||||||
s.pos = first_wrong_digit_pos // adjust error position
|
s.pos = first_wrong_digit_pos // adjust error position
|
||||||
s.error('this octal number has unsuitable digit `${first_wrong_digit.str()}`')
|
s.error('this octal number has unsuitable digit `$first_wrong_digit.str()`')
|
||||||
}
|
}
|
||||||
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
number := filter_num_sep(s.text.str, start_pos, s.pos)
|
||||||
s.pos--
|
s.pos--
|
||||||
|
@ -444,8 +416,7 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
if !c.is_digit() && c != num_sep {
|
if !c.is_digit() && c != num_sep {
|
||||||
if !c.is_letter() || c in [`e`, `E`] || s.is_inside_string {
|
if !c.is_letter() || c in [`e`, `E`] || s.is_inside_string {
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -453,9 +424,9 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
}
|
}
|
||||||
mut call_method := false // true for, e.g., 5.str(), 5.5.str(), 5e5.str()
|
mut call_method := false // true for, e.g., 5.str(), 5.5.str(), 5e5.str()
|
||||||
mut is_range := false // true for, e.g., 5..10
|
mut is_range := false // true for, e.g., 5..10
|
||||||
mut is_float_without_fraction := false // true for, e.g. 5.
|
mut is_float_without_fraction := false // true for, e.g. 5.
|
||||||
// scan fractional part
|
// scan fractional part
|
||||||
if s.pos < s.text.len && s.text[s.pos] == `.` {
|
if s.pos < s.text.len && s.text[s.pos] == `.` {
|
||||||
s.pos++
|
s.pos++
|
||||||
|
@ -471,8 +442,7 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
call_method = true
|
call_method = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -480,22 +450,18 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
}
|
}
|
||||||
}
|
} else if s.text[s.pos] == `.` {
|
||||||
else if s.text[s.pos] == `.` {
|
// 5.. (a range)
|
||||||
// 5.. (a range)
|
|
||||||
is_range = true
|
is_range = true
|
||||||
s.pos--
|
s.pos--
|
||||||
}
|
} else if s.text[s.pos] in [`e`, `E`] {
|
||||||
else if s.text[s.pos] in [`e`, `E`] {
|
// 5.e5
|
||||||
// 5.e5
|
} else if s.text[s.pos].is_letter() {
|
||||||
}
|
// 5.str()
|
||||||
else if s.text[s.pos].is_letter() {
|
|
||||||
// 5.str()
|
|
||||||
call_method = true
|
call_method = true
|
||||||
s.pos--
|
s.pos--
|
||||||
}
|
} else if s.text[s.pos] != `)` {
|
||||||
else if s.text[s.pos] != `)` {
|
// 5.
|
||||||
// 5.
|
|
||||||
is_float_without_fraction = true
|
is_float_without_fraction = true
|
||||||
s.pos--
|
s.pos--
|
||||||
}
|
}
|
||||||
|
@ -518,8 +484,7 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
call_method = true
|
call_method = true
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
} else if !has_wrong_digit {
|
||||||
else if !has_wrong_digit {
|
|
||||||
has_wrong_digit = true
|
has_wrong_digit = true
|
||||||
first_wrong_digit_pos = s.pos
|
first_wrong_digit_pos = s.pos
|
||||||
first_wrong_digit = c
|
first_wrong_digit = c
|
||||||
|
@ -529,21 +494,19 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if has_wrong_digit {
|
if has_wrong_digit {
|
||||||
// error check: wrong digit
|
// error check: wrong digit
|
||||||
s.pos = first_wrong_digit_pos // adjust error position
|
s.pos = first_wrong_digit_pos // adjust error position
|
||||||
s.error('this number has unsuitable digit `${first_wrong_digit.str()}`')
|
s.error('this number has unsuitable digit `$first_wrong_digit.str()`')
|
||||||
}
|
} else if s.text[s.pos - 1] in [`e`, `E`] {
|
||||||
else if s.text[s.pos - 1] in [`e`, `E`] {
|
// error check: 5e
|
||||||
// error check: 5e
|
|
||||||
s.pos-- // adjust error position
|
s.pos-- // adjust error position
|
||||||
s.error('exponent has no digits')
|
s.error('exponent has no digits')
|
||||||
}
|
} else if s.pos < s.text.len &&
|
||||||
else if s.pos < s.text.len && s.text[s.pos] == `.` && !is_range && !is_float_without_fraction && !call_method {
|
s.text[s.pos] == `.` && !is_range && !is_float_without_fraction && !call_method {
|
||||||
// error check: 1.23.4, 123.e+3.4
|
// error check: 1.23.4, 123.e+3.4
|
||||||
if has_exp {
|
if has_exp {
|
||||||
s.error('exponential part should be integer')
|
s.error('exponential part should be integer')
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
s.error('too many decimal points in number')
|
s.error('too many decimal points in number')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -555,14 +518,11 @@ fn (mut s Scanner) ident_dec_number() string {
|
||||||
fn (mut s Scanner) ident_number() string {
|
fn (mut s Scanner) ident_number() string {
|
||||||
if s.expect('0b', s.pos) {
|
if s.expect('0b', s.pos) {
|
||||||
return s.ident_bin_number()
|
return s.ident_bin_number()
|
||||||
}
|
} else if s.expect('0x', s.pos) {
|
||||||
else if s.expect('0x', s.pos) {
|
|
||||||
return s.ident_hex_number()
|
return s.ident_hex_number()
|
||||||
}
|
} else if s.expect('0o', s.pos) {
|
||||||
else if s.expect('0o', s.pos) {
|
|
||||||
return s.ident_oct_number()
|
return s.ident_oct_number()
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.ident_dec_number()
|
return s.ident_dec_number()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -586,9 +546,8 @@ fn (mut s Scanner) end_of_file() token.Token {
|
||||||
if s.eofs > 50 {
|
if s.eofs > 50 {
|
||||||
s.line_nr--
|
s.line_nr--
|
||||||
s.error('the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
|
s.error('the end of file `$s.file_path` has been reached 50 times already, the v parser is probably stuck.\n' +
|
||||||
'This should not happen. Please report the bug here, and include the last 2-3 lines of your source code:\n' +
|
'This should not happen. Please report the bug here, and include the last 2-3 lines of your source code:\n' +
|
||||||
'https://github.com/vlang/v/issues/new?labels=Bug&template=bug_report.md'
|
'https://github.com/vlang/v/issues/new?labels=Bug&template=bug_report.md')
|
||||||
)
|
|
||||||
}
|
}
|
||||||
if s.pos != s.text.len && s.eofs == 1 {
|
if s.pos != s.text.len && s.eofs == 1 {
|
||||||
s.inc_line_number()
|
s.inc_line_number()
|
||||||
|
@ -597,7 +556,7 @@ fn (mut s Scanner) end_of_file() token.Token {
|
||||||
return s.new_token(.eof, '', 1)
|
return s.new_token(.eof, '', 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut s Scanner) scan_all_tokens_in_buffer(){
|
pub fn (mut s Scanner) scan_all_tokens_in_buffer() {
|
||||||
// s.scan_all_tokens_in_buffer is used mainly by vdoc,
|
// s.scan_all_tokens_in_buffer is used mainly by vdoc,
|
||||||
// in order to implement the .toplevel_comments mode.
|
// in order to implement the .toplevel_comments mode.
|
||||||
cmode := s.comments_mode
|
cmode := s.comments_mode
|
||||||
|
@ -613,7 +572,7 @@ pub fn (mut s Scanner) scan_all_tokens_in_buffer(){
|
||||||
s.tidx = 0
|
s.tidx = 0
|
||||||
$if debugscanner ? {
|
$if debugscanner ? {
|
||||||
for t in s.all_tokens {
|
for t in s.all_tokens {
|
||||||
eprintln('> tidx:${t.tidx:-5} | kind: ${t.kind:-10} | lit: ${t.lit}')
|
eprintln('> tidx:${t.tidx:-5} | kind: ${t.kind:-10} | lit: $t.lit')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -686,7 +645,6 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
// handle each char
|
// handle each char
|
||||||
c := s.text[s.pos]
|
c := s.text[s.pos]
|
||||||
nextc := s.look_ahead(1)
|
nextc := s.look_ahead(1)
|
||||||
|
|
||||||
// name or keyword
|
// name or keyword
|
||||||
if util.is_name_char(c) {
|
if util.is_name_char(c) {
|
||||||
name := s.ident_name()
|
name := s.ident_name()
|
||||||
|
@ -724,9 +682,8 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.pos++
|
s.pos++
|
||||||
}
|
}
|
||||||
return s.new_token(.name, name, name.len)
|
return s.new_token(.name, name, name.len)
|
||||||
}
|
} else if c.is_digit() || (c == `.` && nextc.is_digit()) {
|
||||||
else if c.is_digit() || (c == `.` && nextc.is_digit()) {
|
// `123`, `.123`
|
||||||
// `123`, `.123`
|
|
||||||
if !s.is_inside_string {
|
if !s.is_inside_string {
|
||||||
// In C ints with `0` prefix are octal (in V they're decimal), so discarding heading zeros is needed.
|
// In C ints with `0` prefix are octal (in V they're decimal), so discarding heading zeros is needed.
|
||||||
mut start_pos := s.pos
|
mut start_pos := s.pos
|
||||||
|
@ -761,8 +718,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `+` {
|
if nextc == `+` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.inc, '', 2)
|
return s.new_token(.inc, '', 2)
|
||||||
}
|
} else if nextc == `=` {
|
||||||
else if nextc == `=` {
|
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.plus_assign, '', 2)
|
return s.new_token(.plus_assign, '', 2)
|
||||||
}
|
}
|
||||||
|
@ -772,8 +728,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `-` {
|
if nextc == `-` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.dec, '', 2)
|
return s.new_token(.dec, '', 2)
|
||||||
}
|
} else if nextc == `=` {
|
||||||
else if nextc == `=` {
|
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.minus_assign, '', 2)
|
return s.new_token(.minus_assign, '', 2)
|
||||||
}
|
}
|
||||||
|
@ -834,8 +789,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
`$` {
|
`$` {
|
||||||
if s.is_inside_string {
|
if s.is_inside_string {
|
||||||
return s.new_token(.str_dollar, '', 1)
|
return s.new_token(.str_dollar, '', 1)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.dollar, '', 1)
|
return s.new_token(.dollar, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -850,8 +804,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
}
|
}
|
||||||
ident_string := s.ident_string()
|
ident_string := s.ident_string()
|
||||||
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
|
return s.new_token(.string, ident_string, ident_string.len + 2) // + two quotes
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.rcbr, '', 1)
|
return s.new_token(.rcbr, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -860,7 +813,6 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.and_assign, '', 2)
|
return s.new_token(.and_assign, '', 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
afternextc := s.look_ahead(2)
|
afternextc := s.look_ahead(2)
|
||||||
if nextc == `&` && afternextc.is_space() {
|
if nextc == `&` && afternextc.is_space() {
|
||||||
s.pos++
|
s.pos++
|
||||||
|
@ -886,7 +838,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.pos++
|
s.pos++
|
||||||
name := s.ident_name()
|
name := s.ident_name()
|
||||||
if s.is_fmt {
|
if s.is_fmt {
|
||||||
return s.new_token(.name, '@' + name, name.len+1)
|
return s.new_token(.name, '@' + name, name.len + 1)
|
||||||
}
|
}
|
||||||
// @FN => will be substituted with the name of the current V function
|
// @FN => will be substituted with the name of the current V function
|
||||||
// @MOD => will be substituted with the name of the current V module
|
// @MOD => will be substituted with the name of the current V module
|
||||||
|
@ -914,7 +866,8 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
return s.new_token(.string, util.cescaped_path(vexe), 5)
|
return s.new_token(.string, util.cescaped_path(vexe), 5)
|
||||||
}
|
}
|
||||||
if name == 'FILE' {
|
if name == 'FILE' {
|
||||||
return s.new_token(.string, util.cescaped_path(os.real_path(s.file_path)), 5)
|
fpath := os.real_path(s.file_path)
|
||||||
|
return s.new_token(.string, util.cescaped_path(fpath), 5)
|
||||||
}
|
}
|
||||||
if name == 'LINE' {
|
if name == 'LINE' {
|
||||||
return s.new_token(.string, (s.line_nr + 1).str(), 5)
|
return s.new_token(.string, (s.line_nr + 1).str(), 5)
|
||||||
|
@ -928,11 +881,13 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if name == 'VMOD_FILE' {
|
if name == 'VMOD_FILE' {
|
||||||
if s.vmod_file_content.len == 0 {
|
if s.vmod_file_content.len == 0 {
|
||||||
mcache := vmod.get_cache()
|
mcache := vmod.get_cache()
|
||||||
vmod_file_location := mcache.get_by_file( s.file_path )
|
vmod_file_location := mcache.get_by_file(s.file_path)
|
||||||
if vmod_file_location.vmod_file.len == 0 {
|
if vmod_file_location.vmod_file.len == 0 {
|
||||||
s.error('@VMOD_FILE can be used only in projects, that have v.mod file')
|
s.error('@VMOD_FILE can be used only in projects, that have v.mod file')
|
||||||
}
|
}
|
||||||
vmod_content := os.read_file(vmod_file_location.vmod_file) or {''}
|
vmod_content := os.read_file(vmod_file_location.vmod_file) or {
|
||||||
|
''
|
||||||
|
}
|
||||||
$if windows {
|
$if windows {
|
||||||
s.vmod_file_content = vmod_content.replace('\r\n', '\n')
|
s.vmod_file_content = vmod_content.replace('\r\n', '\n')
|
||||||
} $else {
|
} $else {
|
||||||
|
@ -947,7 +902,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
return s.new_token(.name, name, name.len)
|
return s.new_token(.name, name, name.len)
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
case `\r`:
|
case `\r`:
|
||||||
if nextc == `\n` {
|
if nextc == `\n` {
|
||||||
s.pos++
|
s.pos++
|
||||||
s.last_nl_pos = s.pos
|
s.last_nl_pos = s.pos
|
||||||
|
@ -958,8 +913,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
s.last_nl_pos = s.pos
|
s.last_nl_pos = s.pos
|
||||||
return s.new_token(.nl, '')
|
return s.new_token(.nl, '')
|
||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
|
|
||||||
`.` {
|
`.` {
|
||||||
if nextc == `.` {
|
if nextc == `.` {
|
||||||
s.pos++
|
s.pos++
|
||||||
|
@ -987,30 +941,26 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.ge, '', 2)
|
return s.new_token(.ge, '', 2)
|
||||||
}
|
} else if nextc == `>` {
|
||||||
else if nextc == `>` {
|
|
||||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.right_shift_assign, '', 3)
|
return s.new_token(.right_shift_assign, '', 3)
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.right_shift, '', 2)
|
return s.new_token(.right_shift, '', 2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.gt, '', 1)
|
return s.new_token(.gt, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
0xE2 {
|
0xE2 {
|
||||||
if nextc == 0x89 && s.text[s.pos + 2] == 0xA0 {
|
if nextc == 0x89 && s.text[s.pos + 2] == 0xA0 {
|
||||||
// case `≠`:
|
// case `≠`:
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.ne, '', 3)
|
return s.new_token(.ne, '', 3)
|
||||||
}
|
} else if nextc == 0x89 && s.text[s.pos + 2] == 0xBD {
|
||||||
else if nextc == 0x89 && s.text[s.pos + 2] == 0xBD {
|
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.le, '', 3)
|
return s.new_token(.le, '', 3)
|
||||||
}
|
} else if nextc == 0xA9 && s.text[s.pos + 2] == 0xBE {
|
||||||
else if nextc == 0xA9 && s.text[s.pos + 2] == 0xBE {
|
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.ge, '', 3)
|
return s.new_token(.ge, '', 3)
|
||||||
}
|
}
|
||||||
|
@ -1019,16 +969,14 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.le, '', 2)
|
return s.new_token(.le, '', 2)
|
||||||
}
|
} else if nextc == `<` {
|
||||||
else if nextc == `<` {
|
|
||||||
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
if s.pos + 2 < s.text.len && s.text[s.pos + 2] == `=` {
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.left_shift_assign, '', 3)
|
return s.new_token(.left_shift_assign, '', 3)
|
||||||
}
|
}
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.left_shift, '', 2)
|
return s.new_token(.left_shift, '', 2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.lt, '', 1)
|
return s.new_token(.lt, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1036,12 +984,10 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.eq, '', 2)
|
return s.new_token(.eq, '', 2)
|
||||||
}
|
} else if nextc == `>` {
|
||||||
else if nextc == `>` {
|
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.arrow, '', 2)
|
return s.new_token(.arrow, '', 2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.assign, '', 1)
|
return s.new_token(.assign, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1049,8 +995,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.decl_assign, '', 2)
|
return s.new_token(.decl_assign, '', 2)
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
return s.new_token(.colon, '', 1)
|
return s.new_token(.colon, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1061,17 +1006,13 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if nextc == `=` {
|
if nextc == `=` {
|
||||||
s.pos++
|
s.pos++
|
||||||
return s.new_token(.ne, '', 2)
|
return s.new_token(.ne, '', 2)
|
||||||
}
|
} else if nextc == `i` && s.text[s.pos + 2] == `n` && s.text[s.pos + 3].is_space() {
|
||||||
else if nextc == `i` && s.text[s.pos+2] == `n` && s.text[s.pos+3].is_space() {
|
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.not_in, '', 3)
|
return s.new_token(.not_in, '', 3)
|
||||||
}
|
} else if nextc == `i` && s.text[s.pos + 2] == `s` && s.text[s.pos + 3].is_space() {
|
||||||
else if nextc == `i` && s.text[s.pos+2] == `s` && s.text[s.pos+3].is_space() {
|
|
||||||
s.pos += 2
|
s.pos += 2
|
||||||
return s.new_token(.not_is, '', 3)
|
return s.new_token(.not_is, '', 3)
|
||||||
}
|
} else {
|
||||||
//
|
|
||||||
else {
|
|
||||||
return s.new_token(.not, '', 1)
|
return s.new_token(.not, '', 1)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1095,7 +1036,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
if s.should_parse_comment() {
|
if s.should_parse_comment() {
|
||||||
// Find out if this comment is on its own line (for vfmt)
|
// Find out if this comment is on its own line (for vfmt)
|
||||||
mut is_separate_line_comment := true
|
mut is_separate_line_comment := true
|
||||||
for j := start-2; j >= 0 && s.text[j] != `\n`; j-- {
|
for j := start - 2; j >= 0 && s.text[j] != `\n`; j-- {
|
||||||
if s.text[j] !in [`\t`, ` `] {
|
if s.text[j] !in [`\t`, ` `] {
|
||||||
is_separate_line_comment = false
|
is_separate_line_comment = false
|
||||||
}
|
}
|
||||||
|
@ -1149,7 +1090,7 @@ fn (mut s Scanner) text_scan() token.Token {
|
||||||
return s.end_of_file()
|
return s.end_of_file()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
s.error('invalid character `${c.str()}`')
|
s.error('invalid character `$c.str()`')
|
||||||
return s.end_of_file()
|
return s.end_of_file()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,8 +1144,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
}
|
}
|
||||||
// Don't allow \0
|
// Don't allow \0
|
||||||
if c == `0` && s.pos > 2 && s.text[s.pos - 1] == slash {
|
if c == `0` && s.pos > 2 && s.text[s.pos - 1] == slash {
|
||||||
if s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit() {}
|
if s.pos < s.text.len - 1 && s.text[s.pos + 1].is_digit() {
|
||||||
else {
|
} else {
|
||||||
s.error('0 character in a string literal')
|
s.error('0 character in a string literal')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1220,7 +1161,8 @@ fn (mut s Scanner) ident_string() string {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
// $var
|
// $var
|
||||||
if util.is_name_char(c) && prevc == `$` && !is_raw && s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
if util.is_name_char(c) && prevc == `$` && !is_raw &&
|
||||||
|
s.count_symbol_before(s.pos - 2, slash) % 2 == 0 {
|
||||||
s.is_inside_string = true
|
s.is_inside_string = true
|
||||||
s.is_inter_start = true
|
s.is_inter_start = true
|
||||||
s.pos -= 2
|
s.pos -= 2
|
||||||
|
@ -1255,7 +1197,7 @@ fn trim_slash_line_break(s string) string {
|
||||||
for {
|
for {
|
||||||
idx := ret_str.index_after('\\\n', start)
|
idx := ret_str.index_after('\\\n', start)
|
||||||
if idx != -1 {
|
if idx != -1 {
|
||||||
ret_str = ret_str[..idx] + ret_str[idx+2..].trim_left(' \n\t\v\f\r')
|
ret_str = ret_str[..idx] + ret_str[idx + 2..].trim_left(' \n\t\v\f\r')
|
||||||
start = idx
|
start = idx
|
||||||
} else {
|
} else {
|
||||||
break
|
break
|
||||||
|
@ -1294,7 +1236,11 @@ fn (mut s Scanner) ident_char() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Escapes a `'` character
|
// Escapes a `'` character
|
||||||
return if c == "\'" { '\\' + c } else { c }
|
return if c == "\'" {
|
||||||
|
'\\' + c
|
||||||
|
} else {
|
||||||
|
c
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (s &Scanner) expect(want string, start_pos int) bool {
|
fn (s &Scanner) expect(want string, start_pos int) bool {
|
||||||
|
@ -1326,8 +1272,7 @@ fn (mut s Scanner) debug_tokens() {
|
||||||
print(tok_kind.str())
|
print(tok_kind.str())
|
||||||
if lit != '' {
|
if lit != '' {
|
||||||
println(' `$lit`')
|
println(' `$lit`')
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
println('')
|
println('')
|
||||||
}
|
}
|
||||||
if tok_kind == .eof {
|
if tok_kind == .eof {
|
||||||
|
|
Loading…
Reference in New Issue