scanner: add check for wrong decimal numbers

pull/3840/head
SleepyRoy 2020-02-25 21:33:29 +08:00 committed by GitHub
parent f6c2b3a54b
commit 05ed6c57b6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 82 additions and 28 deletions

View File

@ -145,7 +145,7 @@ fn (s mut Scanner) ident_bin_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_bin_digit() && c != num_sep { if !c.is_bin_digit() && c != num_sep {
if !c.is_digit() && !c.is_letter() { if (!c.is_digit() && !c.is_letter()) || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -177,7 +177,7 @@ fn (s mut Scanner) ident_hex_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_hex_digit() && c != num_sep { if !c.is_hex_digit() && c != num_sep {
if !c.is_letter() { if !c.is_letter() || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -209,7 +209,7 @@ fn (s mut Scanner) ident_oct_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_oct_digit() && c != num_sep { if !c.is_oct_digit() && c != num_sep {
if !c.is_digit() && !c.is_letter() { if (!c.is_digit() && !c.is_letter()) || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -231,9 +231,20 @@ fn (s mut Scanner) ident_oct_number() string {
} }
fn (s mut Scanner) ident_dec_number() string { fn (s mut Scanner) ident_dec_number() string {
mut has_wrong_digit := false
mut first_wrong_digit := `\0`
start_pos := s.pos start_pos := s.pos
// scan integer part // scan integer part
for s.pos < s.text.len && (s.text[s.pos].is_digit() || s.text[s.pos] == num_sep) { for s.pos < s.text.len {
if !s.text[s.pos].is_digit() && s.text[s.pos] != num_sep {
if !s.text[s.pos].is_letter() || s.text[s.pos] in [`e`, `E`] || s.inside_string {
break
}
else if !has_wrong_digit {
has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++ s.pos++
} }
// e.g. 1..9 // e.g. 1..9
@ -246,11 +257,17 @@ fn (s mut Scanner) ident_dec_number() string {
// 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++
for s.pos < s.text.len && s.text[s.pos].is_digit() { for s.pos < s.text.len {
s.pos++ if !s.text[s.pos].is_digit() {
if !s.text[s.pos].is_letter() || s.text[s.pos] in [`e`, `E`] || s.inside_string {
break
} }
if !s.inside_string && s.pos < s.text.len && s.text[s.pos] == `f` { else if !has_wrong_digit {
s.error('no `f` is needed for floats') has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++
} }
} }
// scan exponential part // scan exponential part
@ -258,12 +275,19 @@ fn (s mut Scanner) ident_dec_number() string {
if s.expect('e', s.pos) || s.expect('E', s.pos) { if s.expect('e', s.pos) || s.expect('E', s.pos) {
s.pos++ s.pos++
exp_start_pos := s.pos exp_start_pos := s.pos
if s.pos < s.text.len && s.text[s.pos] in [`-`, `+`] { if s.pos < s.text.len && s.text[s.pos] in [`-`, `+`] {
s.pos++ s.pos++
} }
for s.pos < s.text.len {
for s.pos < s.text.len && s.text[s.pos].is_digit() { if !s.text[s.pos].is_digit() {
if !s.text[s.pos].is_letter() || s.inside_string {
break
}
else if !has_wrong_digit {
has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++ s.pos++
} }
if exp_start_pos == s.pos { if exp_start_pos == s.pos {
@ -280,6 +304,9 @@ fn (s mut Scanner) ident_dec_number() string {
s.error('too many decimal points in number') s.error('too many decimal points in number')
} }
} }
if has_wrong_digit {
s.error('this 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--
return number return number
@ -289,16 +316,15 @@ fn (s mut 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()
} }
if s.expect('0x', s.pos) { else if s.expect('0x', s.pos) {
return s.ident_hex_number() return s.ident_hex_number()
} }
if s.expect('0o', s.pos) { else if s.expect('0o', s.pos) {
return s.ident_oct_number() return s.ident_oct_number()
} }
if s.expect('0.', s.pos) || s.expect('0e', s.pos) { else {
return s.ident_dec_number() return s.ident_dec_number()
} }
return s.ident_dec_number()
} }
fn (s mut Scanner) skip_whitespace() { fn (s mut Scanner) skip_whitespace() {

View File

@ -141,7 +141,7 @@ fn (s mut Scanner) ident_bin_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_bin_digit() && c != num_sep { if !c.is_bin_digit() && c != num_sep {
if !c.is_digit() && !c.is_letter() { if (!c.is_digit() && !c.is_letter()) || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -173,7 +173,7 @@ fn (s mut Scanner) ident_hex_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_hex_digit() && c != num_sep { if !c.is_hex_digit() && c != num_sep {
if !c.is_letter() { if !c.is_letter() || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -205,7 +205,7 @@ fn (s mut Scanner) ident_oct_number() string {
} }
c := s.text[s.pos] c := s.text[s.pos]
if !c.is_oct_digit() && c != num_sep { if !c.is_oct_digit() && c != num_sep {
if !c.is_digit() && !c.is_letter() { if (!c.is_digit() && !c.is_letter()) || s.inside_string {
break break
} }
else if !has_wrong_digit { else if !has_wrong_digit {
@ -227,9 +227,20 @@ fn (s mut Scanner) ident_oct_number() string {
} }
fn (s mut Scanner) ident_dec_number() string { fn (s mut Scanner) ident_dec_number() string {
mut has_wrong_digit := false
mut first_wrong_digit := `\0`
start_pos := s.pos start_pos := s.pos
// scan integer part // scan integer part
for s.pos < s.text.len && (s.text[s.pos].is_digit() || s.text[s.pos] == num_sep) { for s.pos < s.text.len {
if !s.text[s.pos].is_digit() && s.text[s.pos] != num_sep {
if !s.text[s.pos].is_letter() || s.text[s.pos] in [`e`, `E`] || s.inside_string {
break
}
else if !has_wrong_digit {
has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++ s.pos++
} }
// e.g. 1..9 // e.g. 1..9
@ -242,11 +253,17 @@ fn (s mut Scanner) ident_dec_number() string {
// 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++
for s.pos < s.text.len && s.text[s.pos].is_digit() { for s.pos < s.text.len {
s.pos++ if !s.text[s.pos].is_digit() {
if !s.text[s.pos].is_letter() || s.text[s.pos] in [`e`, `E`] || s.inside_string {
break
} }
if !s.inside_string && s.pos < s.text.len && s.text[s.pos] == `f` { else if !has_wrong_digit {
s.error('no `f` is needed for floats') has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++
} }
} }
// scan exponential part // scan exponential part
@ -257,7 +274,16 @@ fn (s mut Scanner) ident_dec_number() string {
if s.pos < s.text.len && s.text[s.pos] in [`-`, `+`] { if s.pos < s.text.len && s.text[s.pos] in [`-`, `+`] {
s.pos++ s.pos++
} }
for s.pos < s.text.len && s.text[s.pos].is_digit() { for s.pos < s.text.len {
if !s.text[s.pos].is_digit() {
if !s.text[s.pos].is_letter() || s.inside_string {
break
}
else if !has_wrong_digit {
has_wrong_digit = true
first_wrong_digit = s.text[s.pos]
}
}
s.pos++ s.pos++
} }
if exp_start_pos == s.pos { if exp_start_pos == s.pos {
@ -274,6 +300,9 @@ fn (s mut Scanner) ident_dec_number() string {
s.error('too many decimal points in number') s.error('too many decimal points in number')
} }
} }
if has_wrong_digit {
s.error('this 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--
return number return number
@ -283,16 +312,15 @@ fn (s mut 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()
} }
if s.expect('0x', s.pos) { else if s.expect('0x', s.pos) {
return s.ident_hex_number() return s.ident_hex_number()
} }
if s.expect('0o', s.pos) { else if s.expect('0o', s.pos) {
return s.ident_oct_number() return s.ident_oct_number()
} }
if s.expect('0.', s.pos) || s.expect('0e', s.pos) { else {
return s.ident_dec_number() return s.ident_dec_number()
} }
return s.ident_dec_number()
} }
fn (s mut Scanner) skip_whitespace() { fn (s mut Scanner) skip_whitespace() {