Changeset: fc49679e99e2 for MonetDB
URL: https://dev.monetdb.org/hg/MonetDB/rev/fc49679e99e2
Modified Files:
        sql/server/sql_parser.y
        sql/server/sql_scan.c
Branch: literal_features
Log Message:

introduce literal binary integer


diffs (162 lines):

diff --git a/sql/server/sql_parser.y b/sql/server/sql_parser.y
--- a/sql/server/sql_parser.y
+++ b/sql/server/sql_parser.y
@@ -637,7 +637,7 @@ int yydebug=1;
 
 /* sql prefixes to avoid name clashes on various architectures */
 %token <sval>
-       IDENT UIDENT aTYPE ALIAS RANK sqlINT OIDNUM HEXADECIMAL OCTAL INTNUM 
APPROXNUM
+       IDENT UIDENT aTYPE ALIAS RANK sqlINT OIDNUM HEXADECIMALNUM OCTALNUM 
BINARYNUM INTNUM APPROXNUM
        USING
        GLOBAL CAST CONVERT
        CHARACTER VARYING LARGE OBJECT VARCHAR CLOB sqlTEXT BINARY sqlBLOB
@@ -4840,7 +4840,61 @@ literal:
                  sql_find_subtype(&t, "char", len, 0 );
                  $$ = _newAtomNode( _atom_string(&t, s)); }
 
- |  OCTAL { int len = _strlen($1), i = 2, err = 0;
+ |  BINARYNUM { int len = _strlen($1), i = 2, err = 0;
+                 char * binary = $1;
+                 sql_subtype t;
+#ifdef HAVE_HGE
+                 hge res = 0;
+#else
+                 lng res = 0;
+#endif
+                 /* skip leading '0' */
+                 while (i < len && binary[i] == '0')
+                       i++;
+
+                 if (len - i < MAX_OCT_DIGITS || (len - i == MAX_OCT_DIGITS && 
binary[i] < '2'))
+                       while (err == 0 && i < len)
+                       {
+                               res <<= 1;
+                               if (binary[i] == '0' || binary[i] == '1') // 
TODO: an be asserted
+                                       res = res + (binary[i] - '0');
+                               else
+                                       err = 1;
+                               i++;
+                       }
+                 else
+                       err = 1;
+
+                 if (err == 0) {
+                       assert(res >= 0);
+
+                       /* use smallest type that can accommodate the given 
value */
+                       if (res <= GDK_bte_max)
+                               sql_find_subtype(&t, "tinyint", 8, 0 );
+                       else if (res <= GDK_sht_max)
+                               sql_find_subtype(&t, "smallint", 16, 0 );
+                       else if (res <= GDK_int_max)
+                               sql_find_subtype(&t, "int", 32, 0 );
+                       else if (res <= GDK_lng_max)
+                               sql_find_subtype(&t, "bigint", 64, 0 );
+#ifdef HAVE_HGE
+                       else if (res <= GDK_hge_max)
+                               sql_find_subtype(&t, "hugeint", 128, 0 );
+#endif
+                       else
+                               err = 1;
+                 }
+
+                 if (err != 0) {
+                       sqlformaterror(m, SQLSTATE(22003) "Invalid binary 
number or binary too large (%s)", $1);
+                       $$ = NULL;
+                       YYABORT;
+                 } else {
+                       $$ = _newAtomNode( atom_int(SA, &t, res));
+                 }
+
+ }
+ |  OCTALNUM { int len = _strlen($1), i = 2, err = 0;
                  char * octal = $1;
                  sql_subtype t;
 #ifdef HAVE_HGE
@@ -4894,7 +4948,7 @@ literal:
                  }
 
  }
- |  HEXADECIMAL { int len = _strlen($1), i = 2, err = 0;
+ |  HEXADECIMALNUM { int len = _strlen($1), i = 2, err = 0;
                  char * hexa = $1;
                  sql_subtype t;
 #ifdef HAVE_HGE
diff --git a/sql/server/sql_scan.c b/sql/server/sql_scan.c
--- a/sql/server/sql_scan.c
+++ b/sql/server/sql_scan.c
@@ -976,17 +976,49 @@ number(mvc * c, int cur)
         * [0-9]+                           -- (decimal) INTEGER
         */
        lc->started = 1;
-       if (cur == '0' && (cur = scanner_getc(lc)) == 'o') {
+       int is_literal_integer = 0;
+       if (cur == '0') {
+               switch ((cur = scanner_getc(lc))) {
+               case 'b':
+                       is_literal_integer = BINARYNUM;
+                       break;
+               case 'o':
+                       is_literal_integer = OCTALNUM;
+                       break;
+               case 'x':
+                       is_literal_integer = HEXADECIMALNUM;
+                       break;
+               }
+       }
+
+       if (is_literal_integer == BINARYNUM) {
                cur = scanner_getc(lc);
-               while (cur != EOF && isdigit(cur) && cur < '8') {
-                       token = OCTAL;
+               while (cur != EOF && isdigit(cur) && cur < '2') {
+                       token = BINARYNUM;
                        cur = scanner_getc(lc);
                }
 
                if (cur == EOF)
                        return cur;
 
-               if (token != OCTAL) {
+               if (token != BINARYNUM) {
+                       /* 0b not followed by a binary digit: show 'b' as 
erroneous */
+                       utf8_putchar(lc, cur);
+                       cur = 'b';
+                       token = 0;
+               }
+       }
+       else if (is_literal_integer == OCTALNUM) {
+               cur = scanner_getc(lc);
+               while (cur != EOF && isdigit(cur) && cur < '8') {
+                       token = OCTALNUM;
+                       cur = scanner_getc(lc);
+               }
+
+               if (cur == EOF)
+                       return cur;
+
+               if (token != OCTALNUM) {
                        /* 0o not followed by a octal digit: show 'o' as 
erroneous */
                        utf8_putchar(lc, cur);
                        cur = 'o';
@@ -996,17 +1028,17 @@ number(mvc * c, int cur)
        /* after this block, cur contains the first character after the
         * parsed number (which may be the first causing it not to be a number);
         * it token == 0 after this block, a parse error was detected */
-       else if (cur == '0' && (cur = scanner_getc(lc)) == 'x') {
+       else if (is_literal_integer == HEXADECIMALNUM) {
                cur = scanner_getc(lc);
                while (cur != EOF && iswxdigit(cur)) {
-                       token = HEXADECIMAL;
+                       token = HEXADECIMALNUM;
                        cur = scanner_getc(lc);
                }
 
                if (cur == EOF)
                        return cur;
 
-               if (token != HEXADECIMAL) {
+               if (token != HEXADECIMALNUM) {
                        /* 0x not followed by a hex digit: show 'x' as 
erroneous */
                        utf8_putchar(lc, cur);
                        cur = 'x';
_______________________________________________
checkin-list mailing list -- checkin-list@monetdb.org
To unsubscribe send an email to checkin-list-le...@monetdb.org

Reply via email to