changeset 20624:7c0e10f035bd

Extend parser to accept binary constants that begin with '0b' or '0B'. * NEWS: Announce change: * lex.ll: Define NUMBIN to be 0[bB] followed by 0,1, or '_'. Define NUMBER to be NUMREAL|NUMHEX|NUMBIN. *lex.ll (looks_like_bin): New function to detect 0[bB] prefix. *lex.ll (handle_numbe): Call looks_like_bin() and if found then convert binary string to double. * parser.tst: Add tests for new behavior.
author Rik <rik@octave.org>
date Fri, 09 Oct 2015 18:52:58 -0700
parents e34692daf663
children 5fc798a9b32c
files NEWS libinterp/parse-tree/lex.ll test/parser.tst
diffstat 3 files changed, 35 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/NEWS	Mon Oct 05 14:05:58 2015 -0700
+++ b/NEWS	Fri Oct 09 18:52:58 2015 -0700
@@ -7,6 +7,13 @@
 
     Examples: 1_000_000 == 1e6 or 0xDE_AD_BE_EF
 
+ ** The parser has been extended to understand binary numbers which begin
+    with the prefix '0b' or '0B'.  The value returned is Octave's default
+    numeric class of double, not at unsigned integer class.  Therefore numbers
+    greater than flintmax (2^53) will lose some precision.
+
+    Examples: 0b101 == 5 or 0B1100_0001 == 0xC1
+
  ** The default colormap is now set to 'viridis' which is also
     the default colormap in matplotlib. This new colormap fixes
     some of the main issues with the old default colormap 'jet'
--- a/libinterp/parse-tree/lex.ll	Mon Oct 05 14:05:58 2015 -0700
+++ b/libinterp/parse-tree/lex.ll	Fri Oct 09 18:52:58 2015 -0700
@@ -64,6 +64,7 @@
 
 #include <cctype>
 #include <cstring>
+#include <stdint.h>
 
 #include <iostream>
 #include <set>
@@ -328,9 +329,10 @@
 IDENT   ([_$a-zA-Z][_$a-zA-Z0-9]*)
 FQIDENT ({IDENT}(\.{IDENT})*)
 EXPON   ([DdEe][+-]?{D}{D_}*)
-NUMREAL (({D}{D_}*\.?{D_}*{EXPON}?)|(\.{D}{D_}*{EXPON}?))
+NUMBIN  (0[bB][01_]+)
 NUMHEX  (0[xX][0-9a-fA-F][0-9a-fA-F_]*)
-NUMBER  ({NUMREAL}|{NUMHEX})
+NUMREAL (({D}{D_}*\.?{D_}*{EXPON}?)|(\.{D}{D_}*{EXPON}?))
+NUMBER  ({NUMREAL}|{NUMHEX}|{NUMBIN})
 
 ANY_EXCEPT_NL [^\r\n]
 ANY_INCLUDING_NL (.|{NL})
@@ -2658,6 +2660,12 @@
 }
 
 static inline bool
+looks_like_bin (const char *s, int len)
+{
+  return (len > 2 && s[0] == '0' && (s[1] == 'b' || s[1] == 'B'));
+}
+
+static inline bool
 looks_like_hex (const char *s, int len)
 {
   return (len > 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X'));
@@ -2690,6 +2698,19 @@
 
       value = static_cast<double> (ival);
     }
+  else if (looks_like_bin (tmptxt, strlen (tmptxt)))
+    {
+      uint64_t ivalue = 0;
+
+      for (int i = 0; i < strlen (tmptxt); i++)
+        {
+          ivalue <<= 1;
+          ivalue += static_cast<uint64_t> (tmptxt[i] == '1');
+        }
+
+      value = static_cast<double> (ivalue);
+      nread = 1;  // Just to pass the assert stmt below
+    }
   else
     {
       char *idx = strpbrk (tmptxt, "Dd");
--- a/test/parser.tst	Mon Oct 05 14:05:58 2015 -0700
+++ b/test/parser.tst	Fri Oct 09 18:52:58 2015 -0700
@@ -282,6 +282,11 @@
 %!assert (0xAB_CD, 43981)
 %!assert (2e0_1, 20);
 
+## Test binary constants
+%!assert (0b101, 5)
+%!assert (0B1100_0001, 0xC1)
+%!assert (class (0b1), "double")
+
 ## Test creation of anonymous functions
 
 %!test