From 9b9c1cc83410ff47f85495ff1bc16d62be27cfdf Mon Sep 17 00:00:00 2001 From: SleepyRoy <47302112+SleepyRoy@users.noreply.github.com> Date: Tue, 31 Mar 2020 18:47:32 +0800 Subject: [PATCH] scanner: fix number literal calling method --- vlib/compiler/scanner.v | 39 ++++++++++++++++------- vlib/compiler/tests/num_lit_call_method.v | 28 ++++++++++++++++ vlib/v/scanner/scanner.v | 39 ++++++++++++++++------- 3 files changed, 82 insertions(+), 24 deletions(-) create mode 100644 vlib/compiler/tests/num_lit_call_method.v diff --git a/vlib/compiler/scanner.v b/vlib/compiler/scanner.v index e17c9f61c1..277e64c126 100644 --- a/vlib/compiler/scanner.v +++ b/vlib/compiler/scanner.v @@ -214,6 +214,7 @@ fn (s mut Scanner) ident_oct_number() string { fn (s mut Scanner) ident_dec_number() string { mut has_wrong_digit := false mut first_wrong_digit := `\0` + mut call_method := false // true for, e.g., 12.str(), 12.3.str(), 12e-3.str() start_pos := s.pos // scan integer part for s.pos < s.text.len { @@ -239,19 +240,30 @@ fn (s mut Scanner) ident_dec_number() string { // scan fractional part if s.pos < s.text.len && s.text[s.pos] == `.` { s.pos++ - for s.pos < s.text.len { - c := s.text[s.pos] - if !c.is_digit() { - if !c.is_letter() || c in [`e`, `E`] || s.inside_string { - break - } - else if !has_wrong_digit { - has_wrong_digit = true - first_wrong_digit = c + if s.pos < s.text.len { + if s.text[s.pos].is_digit() { + for s.pos < s.text.len { + c := s.text[s.pos] + if !c.is_digit() { + if !c.is_letter() || c in [`e`, `E`] || s.inside_string { + if c == `.` && s.pos + 1 < s.text.len && !s.text[s.pos+1].is_digit() && s.text[s.pos+1] != `)` { + call_method = true + } + break + } + else if !has_wrong_digit { + has_wrong_digit = true + first_wrong_digit = c + } + } + s.pos++ } } - s.pos++ - } + else if !(s.text[s.pos] in [`)`, `e`, `E`]) { + call_method = true + s.pos-- + } + } } // scan exponential part mut has_exponential_part := false @@ -265,6 +277,9 @@ fn (s mut Scanner) ident_dec_number() string { c := s.text[s.pos] if !c.is_digit() { if !c.is_letter() || s.inside_string { + if c == `.` && s.pos + 1 < s.text.len && !s.text[s.pos+1].is_digit() && s.text[s.pos+1] != `)` { + call_method = true + } break } else if !has_wrong_digit { @@ -280,7 +295,7 @@ fn (s mut Scanner) ident_dec_number() string { has_exponential_part = true } // error check: 1.23.4, 123.e+3.4 - if s.pos < s.text.len && s.text[s.pos] == `.` { + if s.pos < s.text.len && s.text[s.pos] == `.` && !call_method { if has_exponential_part { s.error('exponential part should be integer') } diff --git a/vlib/compiler/tests/num_lit_call_method.v b/vlib/compiler/tests/num_lit_call_method.v new file mode 100644 index 0000000000..1e1e553966 --- /dev/null +++ b/vlib/compiler/tests/num_lit_call_method.v @@ -0,0 +1,28 @@ +fn int_lit_call_method() { + x1 := 1234.str() + assert x1 == '1234' + x2 := -0xffff.str() + assert x2 == '-65535' + x3 := 0b1001001.str() + assert x3 == '73' + x4 := 0o653262.str() + assert x4 == '218802' + x5 := 0.str() + assert x5 == '0' +} + +fn float_lit_call_method() { + x1 := -123.66.str() + assert x1 == '-1.2366e+02' + x2 := 12.5e-2.str() + assert x2 == '1.25e-01' + x3 := .789.str() + assert x3 == '7.89e-01' + x4 := .003e2.str() + assert x4 == '3.e-01' + x5 := 2.e-3.str() + assert x5 == '2.e-03' + x6 := 5.0.str() + assert x6 == '5.e+00' + // x7 := 5..str() Syntax `5.` is allowed, but do not call method on it (`5..str()` is parsed as a range). Use `5.0.str()` instead. +} diff --git a/vlib/v/scanner/scanner.v b/vlib/v/scanner/scanner.v index 72e7744641..6899d85c56 100644 --- a/vlib/v/scanner/scanner.v +++ b/vlib/v/scanner/scanner.v @@ -221,6 +221,7 @@ fn (s mut Scanner) ident_oct_number() string { fn (s mut Scanner) ident_dec_number() string { mut has_wrong_digit := false mut first_wrong_digit := `\0` + mut call_method := false // true for, e.g., 12.str(), 12.3.str(), 12e-3.str() start_pos := s.pos // scan integer part for s.pos < s.text.len { @@ -246,19 +247,30 @@ fn (s mut Scanner) ident_dec_number() string { // scan fractional part if s.pos < s.text.len && s.text[s.pos] == `.` { s.pos++ - for s.pos < s.text.len { - c := s.text[s.pos] - if !c.is_digit() { - if !c.is_letter() || c in [`e`, `E`] || s.inside_string { - break - } - else if !has_wrong_digit { - has_wrong_digit = true - first_wrong_digit = c + if s.pos < s.text.len { + if s.text[s.pos].is_digit() { + for s.pos < s.text.len { + c := s.text[s.pos] + if !c.is_digit() { + if !c.is_letter() || c in [`e`, `E`] || s.inside_string { + if c == `.` && s.pos + 1 < s.text.len && !s.text[s.pos+1].is_digit() && s.text[s.pos+1] != `)` { + call_method = true + } + break + } + else if !has_wrong_digit { + has_wrong_digit = true + first_wrong_digit = c + } + } + s.pos++ } } - s.pos++ - } + else if !(s.text[s.pos] in [`)`, `e`, `E`]) { + call_method = true + s.pos-- + } + } } // scan exponential part mut has_exponential_part := false @@ -272,6 +284,9 @@ fn (s mut Scanner) ident_dec_number() string { c := s.text[s.pos] if !c.is_digit() { if !c.is_letter() || s.inside_string { + if c == `.` && s.pos + 1 < s.text.len && !s.text[s.pos+1].is_digit() && s.text[s.pos+1] != `)` { + call_method = true + } break } else if !has_wrong_digit { @@ -287,7 +302,7 @@ fn (s mut Scanner) ident_dec_number() string { has_exponential_part = true } // error check: 1.23.4, 123.e+3.4 - if s.pos < s.text.len && s.text[s.pos] == `.` { + if s.pos < s.text.len && s.text[s.pos] == `.` && !call_method { if has_exponential_part { s.error('exponential part should be integer') }