[PATCH 12/57][Arm][GAS] Add support for MVE instructions: vaddlv and vaddv
[binutils-gdb.git] / gdb / ada-lex.l
blob8ce7c3a99a9cb061d2a0e411074f242b95d5a3c7
1 /* FLEX lexer for Ada expressions, for GDB.
2    Copyright (C) 1994-2019 Free Software Foundation, Inc.
4    This file is part of GDB.
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 3 of the License, or
9    (at your option) any later version.
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
16    You should have received a copy of the GNU General Public License
17    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
19 /*----------------------------------------------------------------------*/
21 /* The converted version of this file is to be included in ada-exp.y, */
22 /* the Ada parser for gdb.  The function yylex obtains characters from */
23 /* the global pointer lexptr.  It returns a syntactic category for */
24 /* each successive token and places a semantic value into yylval */
25 /* (ada-lval), defined by the parser.   */
27 DIG     [0-9]
28 NUM10   ({DIG}({DIG}|_)*)
29 HEXDIG  [0-9a-f]
30 NUM16   ({HEXDIG}({HEXDIG}|_)*)
31 OCTDIG  [0-7]
32 LETTER  [a-z_]
33 ID      ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
34 WHITE   [ \t\n]
35 TICK    ("'"{WHITE}*)
36 GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
37 OPER    ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
39 EXP     (e[+-]{NUM10})
40 POSEXP  (e"+"?{NUM10})
44 #include "diagnostics.h"
46 /* Some old versions of flex generate code that uses the "register" keyword,
47    which clang warns about.  This was observed for example with flex 2.5.35,
48    as shipped with macOS 10.12.  */
49 DIAGNOSTIC_PUSH
50 DIAGNOSTIC_IGNORE_DEPRECATED_REGISTER
52 #define NUMERAL_WIDTH 256
53 #define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
55 /* Temporary staging for numeric literals.  */
56 static char numbuf[NUMERAL_WIDTH];
57  static void canonicalizeNumeral (char *s1, const char *);
58 static struct stoken processString (const char*, int);
59 static int processInt (struct parser_state *, const char *, const char *,
60                        const char *);
61 static int processReal (struct parser_state *, const char *);
62 static struct stoken processId (const char *, int);
63 static int processAttribute (const char *);
64 static int find_dot_all (const char *);
65 static void rewind_to_char (int);
67 #undef YY_DECL
68 #define YY_DECL static int yylex ( void )
70 /* Flex generates a static function "input" which is not used.
71    Defining YY_NO_INPUT comments it out.  */
72 #define YY_NO_INPUT
74 #undef YY_INPUT
75 #define YY_INPUT(BUF, RESULT, MAX_SIZE) \
76     if ( *pstate->lexptr == '\000' ) \
77       (RESULT) = YY_NULL; \
78     else \
79       { \
80         *(BUF) = *pstate->lexptr; \
81         (RESULT) = 1; \
82         pstate->lexptr += 1; \
83       }
85 static int find_dot_all (const char *);
87 /* Depth of parentheses.  */
88 static int paren_depth;
92 %option case-insensitive interactive nodefault noyywrap
94 %s BEFORE_QUAL_QUOTE
98 {WHITE}          { }
100 "--".*           { yyterminate(); }
102 {NUM10}{POSEXP}  {
103                    canonicalizeNumeral (numbuf, yytext);
104                    return processInt (pstate, NULL, numbuf,
105                                       strrchr (numbuf, 'e') + 1);
106                  }
108 {NUM10}          {
109                    canonicalizeNumeral (numbuf, yytext);
110                    return processInt (pstate, NULL, numbuf, NULL);
111                  }
113 {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
114                    canonicalizeNumeral (numbuf, yytext);
115                    return processInt (pstate, numbuf,
116                                       strchr (numbuf, '#') + 1,
117                                       strrchr(numbuf, '#') + 1);
118                  }
120 {NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
121                    canonicalizeNumeral (numbuf, yytext);
122                    return processInt (pstate, numbuf, strchr (numbuf, '#') + 1,
123                                       NULL);
124                  }
126 "0x"{HEXDIG}+   {
127                   canonicalizeNumeral (numbuf, yytext+2);
128                   return processInt (pstate, "16#", numbuf, NULL);
129                 }
132 {NUM10}"."{NUM10}{EXP} {
133                    canonicalizeNumeral (numbuf, yytext);
134                    return processReal (pstate, numbuf);
135                 }
137 {NUM10}"."{NUM10} {
138                    canonicalizeNumeral (numbuf, yytext);
139                    return processReal (pstate, numbuf);
140                 }
142 {NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
143                    error (_("Based real literals not implemented yet."));
144                 }
146 {NUM10}"#"{NUM16}"."{NUM16}"#" {
147                    error (_("Based real literals not implemented yet."));
148                 }
150 <INITIAL>"'"({GRAPHIC}|\")"'" {
151                    yylval.typed_val.type = type_char (pstate);
152                    yylval.typed_val.val = yytext[1];
153                    return CHARLIT;
154                 }
156 <INITIAL>"'[\""{HEXDIG}{2}"\"]'"   {
157                    int v;
158                    yylval.typed_val.type = type_char (pstate);
159                    sscanf (yytext+3, "%2x", &v);
160                    yylval.typed_val.val = v;
161                    return CHARLIT;
162                 }
164 \"({GRAPHIC}|"[\""({HEXDIG}{2}|\")"\"]")*\"   {
165                    yylval.sval = processString (yytext+1, yyleng-2);
166                    return STRING;
167                 }
169 \"              {
170                    error (_("ill-formed or non-terminated string literal"));
171                 }
174 if              {
175                   rewind_to_char ('i');
176                   return 0;
177                 }
179 task            {
180                   rewind_to_char ('t');
181                   return 0;
182                 }
184 thread{WHITE}+{DIG} {
185                   /* This keyword signals the end of the expression and
186                      will be processed separately.  */
187                   rewind_to_char ('t');
188                   return 0;
189                 }
191         /* ADA KEYWORDS */
193 abs             { return ABS; }
194 and             { return _AND_; }
195 else            { return ELSE; }
196 in              { return IN; }
197 mod             { return MOD; }
198 new             { return NEW; }
199 not             { return NOT; }
200 null            { return NULL_PTR; }
201 or              { return OR; }
202 others          { return OTHERS; }
203 rem             { return REM; }
204 then            { return THEN; }
205 xor             { return XOR; }
207         /* BOOLEAN "KEYWORDS" */
209  /* True and False are not keywords in Ada, but rather enumeration constants.
210     However, the boolean type is no longer represented as an enum, so True
211     and False are no longer defined in symbol tables.  We compromise by
212     making them keywords (when bare). */
214 true            { return TRUEKEYWORD; }
215 false           { return FALSEKEYWORD; }
217         /* ATTRIBUTES */
219 {TICK}[a-zA-Z][a-zA-Z]+ { BEGIN INITIAL; return processAttribute (yytext+1); }
221         /* PUNCTUATION */
223 "=>"            { return ARROW; }
224 ".."            { return DOTDOT; }
225 "**"            { return STARSTAR; }
226 ":="            { return ASSIGN; }
227 "/="            { return NOTEQUAL; }
228 "<="            { return LEQ; }
229 ">="            { return GEQ; }
231 <BEFORE_QUAL_QUOTE>"'" { BEGIN INITIAL; return '\''; }
233 [-&*+./:<>=|;\[\]] { return yytext[0]; }
235 ","             { if (paren_depth == 0 && pstate->comma_terminates)
236                     {
237                       rewind_to_char (',');
238                       return 0;
239                     }
240                   else
241                     return ',';
242                 }
244 "("             { paren_depth += 1; return '('; }
245 ")"             { if (paren_depth == 0)
246                     {
247                       rewind_to_char (')');
248                       return 0;
249                     }
250                   else
251                     {
252                       paren_depth -= 1;
253                       return ')';
254                     }
255                 }
257 "."{WHITE}*all  { return DOT_ALL; }
259 "."{WHITE}*{ID} {
260                   yylval.sval = processId (yytext+1, yyleng-1);
261                   return DOT_ID;
262                 }
264 {ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")?  {
265                   int all_posn = find_dot_all (yytext);
267                   if (all_posn == -1 && yytext[yyleng-1] == '\'')
268                     {
269                       BEGIN BEFORE_QUAL_QUOTE;
270                       yyless (yyleng-1);
271                     }
272                   else if (all_posn >= 0)
273                     yyless (all_posn);
274                   yylval.sval = processId (yytext, yyleng);
275                   return NAME;
276                }
279         /* GDB EXPRESSION CONSTRUCTS  */
281 "'"[^']+"'"{WHITE}*:: {
282                   yyless (yyleng - 2);
283                   yylval.sval = processId (yytext, yyleng);
284                   return NAME;
285                 }
287 "::"            { return COLONCOLON; }
289 [{}@]           { return yytext[0]; }
291         /* REGISTERS AND GDB CONVENIENCE VARIABLES */
293 "$"({LETTER}|{DIG}|"$")*  {
294                   yylval.sval.ptr = yytext;
295                   yylval.sval.length = yyleng;
296                   return DOLLAR_VARIABLE;
297                 }
299         /* CATCH-ALL ERROR CASE */
301 .               { error (_("Invalid character '%s' in expression."), yytext); }
304 #include <ctype.h>
305 /* Initialize the lexer for processing new expression. */
307 static void
308 lexer_init (FILE *inp)
310   BEGIN INITIAL;
311   paren_depth = 0;
312   yyrestart (inp);
316 /* Copy S2 to S1, removing all underscores, and downcasing all letters.  */
318 static void
319 canonicalizeNumeral (char *s1, const char *s2)
321   for (; *s2 != '\000'; s2 += 1)
322     {
323       if (*s2 != '_')
324         {
325           *s1 = tolower(*s2);
326           s1 += 1;
327         }
328     }
329   s1[0] = '\000';
332 /* Interprets the prefix of NUM that consists of digits of the given BASE
333    as an integer of that BASE, with the string EXP as an exponent.
334    Puts value in yylval, and returns INT, if the string is valid.  Causes
335    an error if the number is improperly formated.   BASE, if NULL, defaults
336    to "10", and EXP to "1".  The EXP does not contain a leading 'e' or 'E'.
337  */
339 static int
340 processInt (struct parser_state *par_state, const char *base0,
341             const char *num0, const char *exp0)
343   ULONGEST result;
344   long exp;
345   int base;
346   const char *trailer;
348   if (base0 == NULL)
349     base = 10;
350   else
351     {
352       base = strtol (base0, (char **) NULL, 10);
353       if (base < 2 || base > 16)
354         error (_("Invalid base: %d."), base);
355     }
357   if (exp0 == NULL)
358     exp = 0;
359   else
360     exp = strtol(exp0, (char **) NULL, 10);
362   errno = 0;
363   result = strtoulst (num0, &trailer, base);
364   if (errno == ERANGE)
365     error (_("Integer literal out of range"));
366   if (isxdigit(*trailer))
367     error (_("Invalid digit `%c' in based literal"), *trailer);
369   while (exp > 0)
370     {
371       if (result > (ULONG_MAX / base))
372         error (_("Integer literal out of range"));
373       result *= base;
374       exp -= 1;
375     }
377   if ((result >> (gdbarch_int_bit (par_state->gdbarch ())-1)) == 0)
378     yylval.typed_val.type = type_int (par_state);
379   else if ((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) == 0)
380     yylval.typed_val.type = type_long (par_state);
381   else if (((result >> (gdbarch_long_bit (par_state->gdbarch ())-1)) >> 1) == 0)
382     {
383       /* We have a number representable as an unsigned integer quantity.
384          For consistency with the C treatment, we will treat it as an
385          anonymous modular (unsigned) quantity.  Alas, the types are such
386          that we need to store .val as a signed quantity.  Sorry
387          for the mess, but C doesn't officially guarantee that a simple
388          assignment does the trick (no, it doesn't; read the reference manual).
389        */
390       yylval.typed_val.type
391         = builtin_type (par_state->gdbarch ())->builtin_unsigned_long;
392       if (result & LONGEST_SIGN)
393         yylval.typed_val.val =
394           (LONGEST) (result & ~LONGEST_SIGN)
395           - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
396       else
397         yylval.typed_val.val = (LONGEST) result;
398       return INT;
399     }
400   else
401     yylval.typed_val.type = type_long_long (par_state);
403   yylval.typed_val.val = (LONGEST) result;
404   return INT;
407 static int
408 processReal (struct parser_state *par_state, const char *num0)
410   yylval.typed_val_float.type = type_long_double (par_state);
412   bool parsed = parse_float (num0, strlen (num0),
413                              yylval.typed_val_float.type,
414                              yylval.typed_val_float.val);
415   gdb_assert (parsed);
416   return FLOAT;
420 /* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym.  The
421    resulting string is valid until the next call to ada_parse.  If
422    NAME0 contains the substring "___", it is assumed to be already
423    encoded and the resulting name is equal to it.  Similarly, if the name
424    starts with '<', it is copied verbatim.  Otherwise, it differs
425    from NAME0 in that:
426     + Characters between '...' are transfered verbatim to yylval.ssym.
427     + Trailing "'" characters in quoted sequences are removed (a leading quote is
428       preserved to indicate that the name is not to be GNAT-encoded).
429     + Unquoted whitespace is removed.
430     + Unquoted alphabetic characters are mapped to lower case.
431    Result is returned as a struct stoken, but for convenience, the string
432    is also null-terminated.  Result string valid until the next call of
433    ada_parse.
434  */
435 static struct stoken
436 processId (const char *name0, int len)
438   char *name = (char *) obstack_alloc (&temp_parse_space, len + 11);
439   int i0, i;
440   struct stoken result;
442   result.ptr = name;
443   while (len > 0 && isspace (name0[len-1]))
444     len -= 1;
446   if (name0[0] == '<' || strstr (name0, "___") != NULL)
447     {
448       strncpy (name, name0, len);
449       name[len] = '\000';
450       result.length = len;
451       return result;
452     }
454   i = i0 = 0;
455   while (i0 < len)
456     {
457       if (isalnum (name0[i0]))
458         {
459           name[i] = tolower (name0[i0]);
460           i += 1; i0 += 1;
461         }
462       else switch (name0[i0])
463         {
464         default:
465           name[i] = name0[i0];
466           i += 1; i0 += 1;
467           break;
468         case ' ': case '\t':
469           i0 += 1;
470           break;
471         case '\'':
472           do
473             {
474               name[i] = name0[i0];
475               i += 1; i0 += 1;
476             }
477           while (i0 < len && name0[i0] != '\'');
478           i0 += 1;
479           break;
480         }
481     }
482   name[i] = '\000';
484   result.length = i;
485   return result;
488 /* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
489    with special hex character notations replaced with characters. 
490    Result valid until the next call to ada_parse.  */
492 static struct stoken
493 processString (const char *text, int len)
495   const char *p;
496   char *q;
497   const char *lim = text + len;
498   struct stoken result;
500   q = (char *) obstack_alloc (&temp_parse_space, len);
501   result.ptr = q;
502   p = text;
503   while (p < lim)
504     {
505       if (p[0] == '[' && p[1] == '"' && p+2 < lim)
506          {
507            if (p[2] == '"')  /* "...["""]... */
508              {
509                *q = '"';
510                p += 4;
511              }
512            else
513              {
514                int chr;
515                sscanf (p+2, "%2x", &chr);
516                *q = (char) chr;
517                p += 5;
518              }
519          }
520        else
521          *q = *p;
522        q += 1;
523        p += 1;
524      }
525   result.length = q - result.ptr;
526   return result;
529 /* Returns the position within STR of the '.' in a
530    '.{WHITE}*all' component of a dotted name, or -1 if there is none.
531    Note: we actually don't need this routine, since 'all' can never be an
532    Ada identifier.  Thus, looking up foo.all or foo.all.x as a name
533    must fail, and will eventually be interpreted as (foo).all or
534    (foo).all.x.  However, this does avoid an extraneous lookup. */
536 static int
537 find_dot_all (const char *str)
539   int i;
541   for (i = 0; str[i] != '\000'; i++)
542     if (str[i] == '.')
543       {
544         int i0 = i;
546         do
547           i += 1;
548         while (isspace (str[i]));
550         if (strncasecmp (str + i, "all", 3) == 0
551             && !isalnum (str[i + 3]) && str[i + 3] != '_')
552           return i0;
553       }
554   return -1;
557 /* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
558    case.  */
560 static int
561 subseqMatch (const char *subseq, const char *str)
563   if (subseq[0] == '\0')
564     return 1;
565   else if (str[0] == '\0')
566     return 0;
567   else if (tolower (subseq[0]) == tolower (str[0]))
568     return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
569   else
570     return subseqMatch (subseq, str+1);
574 static struct { const char *name; int code; }
575 attributes[] = {
576   { "address", TICK_ADDRESS },
577   { "unchecked_access", TICK_ACCESS },
578   { "unrestricted_access", TICK_ACCESS },
579   { "access", TICK_ACCESS },
580   { "first", TICK_FIRST },
581   { "last", TICK_LAST },
582   { "length", TICK_LENGTH },
583   { "max", TICK_MAX },
584   { "min", TICK_MIN },
585   { "modulus", TICK_MODULUS },
586   { "pos", TICK_POS },
587   { "range", TICK_RANGE },
588   { "size", TICK_SIZE },
589   { "tag", TICK_TAG },
590   { "val", TICK_VAL },
591   { NULL, -1 }
594 /* Return the syntactic code corresponding to the attribute name or
595    abbreviation STR.  */
597 static int
598 processAttribute (const char *str)
600   int i, k;
602   for (i = 0; attributes[i].code != -1; i += 1)
603     if (strcasecmp (str, attributes[i].name) == 0)
604       return attributes[i].code;
606   for (i = 0, k = -1; attributes[i].code != -1; i += 1)
607     if (subseqMatch (str, attributes[i].name))
608       {
609         if (k == -1)
610           k = i;
611         else
612           error (_("ambiguous attribute name: `%s'"), str);
613       }
614   if (k == -1)
615     error (_("unrecognized attribute: `%s'"), str);
617   return attributes[k].code;
620 /* Back up lexptr by yyleng and then to the rightmost occurrence of
621    character CH, case-folded (there must be one).  WARNING: since
622    lexptr points to the next input character that Flex has not yet
623    transferred to its internal buffer, the use of this function
624    depends on the assumption that Flex calls YY_INPUT only when it is
625    logically necessary to do so (thus, there is no reading ahead
626    farther than needed to identify the next token.)  */
628 static void
629 rewind_to_char (int ch)
631   pstate->lexptr -= yyleng;
632   while (toupper (*pstate->lexptr) != toupper (ch))
633     pstate->lexptr -= 1;
634   yyrestart (NULL);
637 /* Dummy definition to suppress warnings about unused static definitions. */
638 typedef void (*dummy_function) ();
639 dummy_function ada_flex_use[] = 
641   (dummy_function) yyunput
644 DIAGNOSTIC_POP