[m-rev.] diff: fix bug #430

Julien Fischer jfischer at opturion.com
Sun Jan 29 14:36:13 AEDT 2017


Fix bug #430.

The lexer was not allowing underscores between leading zeros in decimal integer
literals and float literals (e.g. 0_0 or 0_0.0).

library/lexer.m:
      Allow underscores in the above cases.

tests/hard_coded/parse_number_from_io.{m,exp,exp2,exp3}:
tests/hard_coded/parse_number_from_string.{m,exp,exp2,exp3}:
      Extend these tests to cover the above cases.

tests/invalid/invalid_binary_literal.err_exp:
tests/invalid/invalid_octal_literal.err_exp:
tests/invalid/invalid_hex_literal.err_exp:
      Conform to the above change.

Julien.

diff --git a/library/lexer.m b/library/lexer.m
index 0e89668..1cb2427 100644
--- a/library/lexer.m
+++ b/library/lexer.m
@@ -1961,6 +1961,9 @@ get_zero(Stream, Token, !IO) :-
          ( if char.is_digit(Char) then
              LastDigit = last_digit_is_not_underscore,
              get_number(Stream, LastDigit, [Char], Token, !IO)
+        else if Char = '_' then
+            LastDigit = last_digit_is_underscore,
+            get_number(Stream, LastDigit, [], Token, !IO)
          else if Char = '''' then
              get_char_code(Stream, Token, !IO)
          else if Char = 'b' then
@@ -2001,6 +2004,10 @@ string_get_zero(String, Len, Posn0, Token, Context, !Posn) :-
              LastDigit = last_digit_is_not_underscore,
              string_get_number(String, LastDigit, Len, Posn0, Token, Context,
                  !Posn)
+        else if Char = '_' then
+            LastDigit = last_digit_is_underscore,
+            string_get_number(String, LastDigit, Len, Posn0, Token, Context,
+                !Posn)
          else if Char = '''' then
              string_get_char_code(String, Len, Posn0, Token, Context, !Posn)
          else if Char = 'b' then
diff --git a/tests/hard_coded/parse_number_from_io.exp b/tests/hard_coded/parse_number_from_io.exp
index b4aa73e..cef3e65 100644
--- a/tests/hard_coded/parse_number_from_io.exp
+++ b/tests/hard_coded/parse_number_from_io.exp
@@ -1,10 +1,16 @@
  Decimal:
  0
  0
+0
+0
  10
  -10
  10
  -10
+1
+1
+-1
+-1

  Binary:
  0
@@ -50,3 +56,5 @@ Float:
  1200000000000.0
  1.2e-10
  1.2e-10
+0.0
+1.01
diff --git a/tests/hard_coded/parse_number_from_io.exp2 b/tests/hard_coded/parse_number_from_io.exp2
index 33a2286..0a8763c 100644
--- a/tests/hard_coded/parse_number_from_io.exp2
+++ b/tests/hard_coded/parse_number_from_io.exp2
@@ -1,10 +1,16 @@
  Decimal:
  0
  0
+0
+0
  10
  -10
  10
  -10
+1
+1
+-1
+-1

  Binary:
  0
@@ -50,3 +56,5 @@ Float:
  1.2E12
  1.2E-10
  1.2E-10
+0.0
+1.01
diff --git a/tests/hard_coded/parse_number_from_io.exp3 b/tests/hard_coded/parse_number_from_io.exp3
index b6c52a6..5ca44b3 100644
--- a/tests/hard_coded/parse_number_from_io.exp3
+++ b/tests/hard_coded/parse_number_from_io.exp3
@@ -1,10 +1,16 @@
  Decimal:
  0
  0
+0
+0
  10
  -10
  10
  -10
+1
+1
+-1
+-1

  Binary:
  0
@@ -50,3 +56,5 @@ Float:
  1200000000000.0
  1.2E-10
  1.2E-10
+0.0
+1.01
diff --git a/tests/hard_coded/parse_number_from_io.m b/tests/hard_coded/parse_number_from_io.m
index e51b9c0..11e48d7 100644
--- a/tests/hard_coded/parse_number_from_io.m
+++ b/tests/hard_coded/parse_number_from_io.m
@@ -15,10 +15,16 @@ main(!IO) :-
      io.print_line("Decimal:", !IO),
      io.print_line(0, !IO),
      io.print_line(-0, !IO),
+    io.print_line(00, !IO),
+    io.print_line(0_0, !IO),
      io.print_line(10, !IO),
      io.print_line(-10, !IO),
      io.print_line(1_0, !IO),
      io.print_line(-1_0, !IO),
+    io.print_line(01, !IO),
+    io.print_line(0_1, !IO),
+    io.print_line(-01, !IO),
+    io.print_line(-0_1, !IO),
      io.nl(!IO),

      io.print_line("Binary:", !IO),
@@ -67,4 +73,6 @@ main(!IO) :-
      io.print_line(1_2e+1_1, !IO),
      io.print_line(1_2E+1_1, !IO),
      io.print_line(1_2e-1_1, !IO),
-    io.print_line(1_2E-1_1, !IO).
+    io.print_line(1_2E-1_1, !IO),
+    io.print_line(0_0.0, !IO),
+    io.print_line(0_1.0_1, !IO).
diff --git a/tests/hard_coded/parse_number_from_string.exp b/tests/hard_coded/parse_number_from_string.exp
index dc8623f..01eb941 100644
--- a/tests/hard_coded/parse_number_from_string.exp
+++ b/tests/hard_coded/parse_number_from_string.exp
@@ -1,10 +1,14 @@
  Valid decimal literals:
  read_term("0.") = functor(integer(0), [], context("", 1))
  read_term("-0.") = functor(integer(0), [], context("", 1))
+read_term("00.") = functor(integer(0), [], context("", 1))
+read_term("0_0.") = functor(integer(0), [], context("", 1))
  read_term("10.") = functor(integer(10), [], context("", 1))
  read_term("-10.") = functor(integer(-10), [], context("", 1))
  read_term("1_0.") = functor(integer(10), [], context("", 1))
  read_term("-1_0.") = functor(integer(-10), [], context("", 1))
+read_term("01.") = functor(integer(1), [], context("", 1))
+read_term("0_1.") = functor(integer(1), [], context("", 1))
  read_term("1_000_000_000_000_000_000_000.") = functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))
  read_term("-1_000_000_000_000_000_000_000.") = functor(atom("-"), [functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))], context("", 1))

@@ -84,6 +88,10 @@ read_term("1_2e+1_1.") = functor(float(1200000000000.0), [], context("", 1))
  read_term("1_2E+1_1.") = functor(float(1200000000000.0), [], context("", 1))
  read_term("1_2e-1_1.") = functor(float(1.2e-10), [], context("", 1))
  read_term("1_2E-1_1.") = functor(float(1.2e-10), [], context("", 1))
+read_term("00.0.") = functor(float(0.0), [], context("", 1))
+read_term("0_0.0.") = functor(float(0.0), [], context("", 1))
+read_term("01.0.") = functor(float(1.0), [], context("", 1))
+read_term("0_1.0.") = functor(float(1.0), [], context("", 1))

  Invalid float literals:
  read_term("1_2_3.1_2_3_.") = Syntax error: fractional part of float terminated by underscore
diff --git a/tests/hard_coded/parse_number_from_string.exp2 b/tests/hard_coded/parse_number_from_string.exp2
index 68f1c63..ad2e577 100644
--- a/tests/hard_coded/parse_number_from_string.exp2
+++ b/tests/hard_coded/parse_number_from_string.exp2
@@ -1,10 +1,14 @@
  Valid decimal literals:
  read_term("0.") = functor(integer(0), [], context("", 1))
  read_term("-0.") = functor(integer(0), [], context("", 1))
+read_term("00.") = functor(integer(0), [], context("", 1))
+read_term("0_0.") = functor(integer(0), [], context("", 1))
  read_term("10.") = functor(integer(10), [], context("", 1))
  read_term("-10.") = functor(integer(-10), [], context("", 1))
  read_term("1_0.") = functor(integer(10), [], context("", 1))
  read_term("-1_0.") = functor(integer(-10), [], context("", 1))
+read_term("01.") = functor(integer(1), [], context("", 1))
+read_term("0_1.") = functor(integer(1), [], context("", 1))
  read_term("1_000_000_000_000_000_000_000.") = functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))
  read_term("-1_000_000_000_000_000_000_000.") = functor(atom("-"), [functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))], context("", 1))

@@ -84,6 +88,10 @@ read_term("1_2e+1_1.") = functor(float(1.2E12), [], context("", 1))
  read_term("1_2E+1_1.") = functor(float(1.2E12), [], context("", 1))
  read_term("1_2e-1_1.") = functor(float(1.2E-10), [], context("", 1))
  read_term("1_2E-1_1.") = functor(float(1.2E-10), [], context("", 1))
+read_term("00.0.") = functor(float(0.0), [], context("", 1))
+read_term("0_0.0.") = functor(float(0.0), [], context("", 1))
+read_term("01.0.") = functor(float(1.0), [], context("", 1))
+read_term("0_1.0.") = functor(float(1.0), [], context("", 1))

  Invalid float literals:
  read_term("1_2_3.1_2_3_.") = Syntax error: fractional part of float terminated by underscore
diff --git a/tests/hard_coded/parse_number_from_string.exp3 b/tests/hard_coded/parse_number_from_string.exp3
index 258a76f..d518db3 100644
--- a/tests/hard_coded/parse_number_from_string.exp3
+++ b/tests/hard_coded/parse_number_from_string.exp3
@@ -1,10 +1,14 @@
  Valid decimal literals:
  read_term("0.") = functor(integer(0), [], context("", 1))
  read_term("-0.") = functor(integer(0), [], context("", 1))
+read_term("00.") = functor(integer(0), [], context("", 1))
+read_term("0_0.") = functor(integer(0), [], context("", 1))
  read_term("10.") = functor(integer(10), [], context("", 1))
  read_term("-10.") = functor(integer(-10), [], context("", 1))
  read_term("1_0.") = functor(integer(10), [], context("", 1))
  read_term("-1_0.") = functor(integer(-10), [], context("", 1))
+read_term("01.") = functor(integer(1), [], context("", 1))
+read_term("0_1.") = functor(integer(1), [], context("", 1))
  read_term("1_000_000_000_000_000_000_000.") = functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))
  read_term("-1_000_000_000_000_000_000_000.") = functor(atom("-"), [functor(big_integer(base_10, i(5, [13877, 12907, 7261, 14976, 0])), [], context("", 1))], context("", 1))

@@ -84,6 +88,10 @@ read_term("1_2e+1_1.") = functor(float(1200000000000.0), [], context("", 1))
  read_term("1_2E+1_1.") = functor(float(1200000000000.0), [], context("", 1))
  read_term("1_2e-1_1.") = functor(float(1.2E-10), [], context("", 1))
  read_term("1_2E-1_1.") = functor(float(1.2E-10), [], context("", 1))
+read_term("00.0.") = functor(float(0.0), [], context("", 1))
+read_term("0_0.0.") = functor(float(0.0), [], context("", 1))
+read_term("01.0.") = functor(float(1.0), [], context("", 1))
+read_term("0_1.0.") = functor(float(1.0), [], context("", 1))

  Invalid float literals:
  read_term("1_2_3.1_2_3_.") = Syntax error: fractional part of float terminated by underscore
diff --git a/tests/hard_coded/parse_number_from_string.m b/tests/hard_coded/parse_number_from_string.m
index 527532a..2635791 100644
--- a/tests/hard_coded/parse_number_from_string.m
+++ b/tests/hard_coded/parse_number_from_string.m
@@ -69,10 +69,14 @@ run_test(String, !IO) :-
  valid_decimal_cases = [
      "0.",
      "-0.",
+    "00.",
+    "0_0.",
      "10.",
      "-10.",
      "1_0.",
      "-1_0.",
+    "01.",
+    "0_1.",
      "1_000_000_000_000_000_000_000.",
      "-1_000_000_000_000_000_000_000."
  ].
@@ -175,7 +179,11 @@ valid_float_cases = [
      "1_2e+1_1.",
      "1_2E+1_1.",
      "1_2e-1_1.",
-    "1_2E-1_1."
+    "1_2E-1_1.",
+    "00.0.",
+    "0_0.0.",
+    "01.0.",
+    "0_1.0."
  ].

  :- func invalid_float_cases = list(string).
diff --git a/tests/invalid/invalid_binary_literal.err_exp b/tests/invalid/invalid_binary_literal.err_exp
index 216d695..27e0d3e 100644
--- a/tests/invalid/invalid_binary_literal.err_exp
+++ b/tests/invalid/invalid_binary_literal.err_exp
@@ -24,7 +24,9 @@ invalid_binary_literal.m:025: Syntax error: unterminated binary literal.
  invalid_binary_literal.m:027: Syntax error at token `. ': unexpected token at
  invalid_binary_literal.m:027:   start of (sub)term.
  invalid_binary_literal.m:027: Syntax error: unterminated binary literal.
-invalid_binary_literal.m:029: Syntax error at variable `_b11': operator or `.'
-invalid_binary_literal.m:029:   expected.
-invalid_binary_literal.m:031: Syntax error at variable `_b11': operator or `.'
-invalid_binary_literal.m:031:   expected.
+invalid_binary_literal.m:029: Syntax error: unterminated decimal literal.
+invalid_binary_literal.m:029: Error: clause for predicate
+invalid_binary_literal.m:029:   `invalid_binary_literal.b11'/0
+invalid_binary_literal.m:029:   without corresponding `:- pred' declaration.
+invalid_binary_literal.m:029: Inferred :- pred b11.
+invalid_binary_literal.m:031: Syntax error: unterminated decimal literal.
diff --git a/tests/invalid/invalid_hex_literal.err_exp b/tests/invalid/invalid_hex_literal.err_exp
index b2127ca..38bda41 100644
--- a/tests/invalid/invalid_hex_literal.err_exp
+++ b/tests/invalid/invalid_hex_literal.err_exp
@@ -24,7 +24,9 @@ invalid_hex_literal.m:025: Syntax error: unterminated hexadecimal literal.
  invalid_hex_literal.m:027: Syntax error at token `. ': unexpected token at
  invalid_hex_literal.m:027:   start of (sub)term.
  invalid_hex_literal.m:027: Syntax error: unterminated hexadecimal literal.
-invalid_hex_literal.m:029: Syntax error at variable `_xff': operator or `.'
-invalid_hex_literal.m:029:   expected.
-invalid_hex_literal.m:031: Syntax error at variable `_xff': operator or `.'
-invalid_hex_literal.m:031:   expected.
+invalid_hex_literal.m:029: Syntax error: unterminated decimal literal.
+invalid_hex_literal.m:029: Error: clause for predicate
+invalid_hex_literal.m:029:   `invalid_hex_literal.xff'/0
+invalid_hex_literal.m:029:   without corresponding `:- pred' declaration.
+invalid_hex_literal.m:029: Inferred :- pred xff.
+invalid_hex_literal.m:031: Syntax error: unterminated decimal literal.
diff --git a/tests/invalid/invalid_octal_literal.err_exp b/tests/invalid/invalid_octal_literal.err_exp
index 6c4ecd8..12a14d8 100644
--- a/tests/invalid/invalid_octal_literal.err_exp
+++ b/tests/invalid/invalid_octal_literal.err_exp
@@ -24,7 +24,9 @@ invalid_octal_literal.m:025: Syntax error: unterminated octal literal.
  invalid_octal_literal.m:027: Syntax error at token `. ': unexpected token at
  invalid_octal_literal.m:027:   start of (sub)term.
  invalid_octal_literal.m:027: Syntax error: unterminated octal literal.
-invalid_octal_literal.m:029: Syntax error at variable `_o77': operator or `.'
-invalid_octal_literal.m:029:   expected.
-invalid_octal_literal.m:031: Syntax error at variable `_o77': operator or `.'
-invalid_octal_literal.m:031:   expected.
+invalid_octal_literal.m:029: Syntax error: unterminated decimal literal.
+invalid_octal_literal.m:029: Error: clause for predicate
+invalid_octal_literal.m:029:   `invalid_octal_literal.o77'/0
+invalid_octal_literal.m:029:   without corresponding `:- pred' declaration.
+invalid_octal_literal.m:029: Inferred :- pred o77.
+invalid_octal_literal.m:031: Syntax error: unterminated decimal literal.


More information about the reviews mailing list