OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-old/] [gdb-7.1/] [gdb/] [ada-lex.l] - Blame information for rev 227

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 227 jeremybenn
/* FLEX lexer for Ada expressions, for GDB.
2
   Copyright (C) 1994, 1997, 1998, 2000, 2001, 2002, 2003, 2007, 2008, 2009,
3
   2010 Free Software Foundation, Inc.
4
 
5
   This file is part of GDB.
6
 
7
   This program is free software; you can redistribute it and/or modify
8
   it under the terms of the GNU General Public License as published by
9
   the Free Software Foundation; either version 3 of the License, or
10
   (at your option) any later version.
11
 
12
   This program is distributed in the hope that it will be useful,
13
   but WITHOUT ANY WARRANTY; without even the implied warranty of
14
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
   GNU General Public License for more details.
16
 
17
   You should have received a copy of the GNU General Public License
18
   along with this program.  If not, see .  */
19
 
20
/*----------------------------------------------------------------------*/
21
 
22
/* The converted version of this file is to be included in ada-exp.y, */
23
/* the Ada parser for gdb.  The function yylex obtains characters from */
24
/* the global pointer lexptr.  It returns a syntactic category for */
25
/* each successive token and places a semantic value into yylval */
26
/* (ada-lval), defined by the parser.   */
27
 
28
DIG     [0-9]
29
NUM10   ({DIG}({DIG}|_)*)
30
HEXDIG  [0-9a-f]
31
NUM16   ({HEXDIG}({HEXDIG}|_)*)
32
OCTDIG  [0-7]
33
LETTER  [a-z_]
34
ID      ({LETTER}({LETTER}|{DIG})*|"<"{LETTER}({LETTER}|{DIG})*">")
35
WHITE   [ \t\n]
36
TICK    ("'"{WHITE}*)
37
GRAPHIC [a-z0-9 #&'()*+,-./:;<>=_|!$%?@\[\]\\^`{}~]
38
OPER    ([-+*/=<>&]|"<="|">="|"**"|"/="|"and"|"or"|"xor"|"not"|"mod"|"rem"|"abs")
39
 
40
EXP     (e[+-]{NUM10})
41
POSEXP  (e"+"?{NUM10})
42
 
43
%{
44
 
45
#define NUMERAL_WIDTH 256
46
#define LONGEST_SIGN ((ULONGEST) 1 << (sizeof(LONGEST) * HOST_CHAR_BIT - 1))
47
 
48
/* Temporary staging for numeric literals.  */
49
static char numbuf[NUMERAL_WIDTH];
50
 static void canonicalizeNumeral (char *s1, const char *);
51
static struct stoken processString (const char*, int);
52
static int processInt (const char *, const char *, const char *);
53
static int processReal (const char *);
54
static struct stoken processId (const char *, int);
55
static int processAttribute (const char *);
56
static int find_dot_all (const char *);
57
 
58
#undef YY_DECL
59
#define YY_DECL static int yylex ( void )
60
 
61
/* Flex generates a static function "input" which is not used.
62
   Defining YY_NO_INPUT comments it out.  */
63
#define YY_NO_INPUT
64
 
65
#undef YY_INPUT
66
#define YY_INPUT(BUF, RESULT, MAX_SIZE) \
67
    if ( *lexptr == '\000' ) \
68
      (RESULT) = YY_NULL; \
69
    else \
70
      { \
71
        *(BUF) = *lexptr; \
72
        (RESULT) = 1; \
73
        lexptr += 1; \
74
      }
75
 
76
static int find_dot_all (const char *);
77
 
78
%}
79
 
80
%option case-insensitive interactive nodefault
81
 
82
%s BEFORE_QUAL_QUOTE
83
 
84
%%
85
 
86
{WHITE}          { }
87
 
88
"--".*           { yyterminate(); }
89
 
90
{NUM10}{POSEXP}  {
91
                   canonicalizeNumeral (numbuf, yytext);
92
                   return processInt (NULL, numbuf, strrchr(numbuf, 'e')+1);
93
                 }
94
 
95
{NUM10}          {
96
                   canonicalizeNumeral (numbuf, yytext);
97
                   return processInt (NULL, numbuf, NULL);
98
                 }
99
 
100
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#"{POSEXP} {
101
                   canonicalizeNumeral (numbuf, yytext);
102
                   return processInt (numbuf,
103
                                      strchr (numbuf, '#') + 1,
104
                                      strrchr(numbuf, '#') + 1);
105
                 }
106
 
107
{NUM10}"#"{HEXDIG}({HEXDIG}|_)*"#" {
108
                   canonicalizeNumeral (numbuf, yytext);
109
                   return processInt (numbuf, strchr (numbuf, '#') + 1, NULL);
110
                 }
111
 
112
"0x"{HEXDIG}+   {
113
                  canonicalizeNumeral (numbuf, yytext+2);
114
                  return processInt ("16#", numbuf, NULL);
115
                }
116
 
117
 
118
{NUM10}"."{NUM10}{EXP} {
119
                   canonicalizeNumeral (numbuf, yytext);
120
                   return processReal (numbuf);
121
                }
122
 
123
{NUM10}"."{NUM10} {
124
                   canonicalizeNumeral (numbuf, yytext);
125
                   return processReal (numbuf);
126
                }
127
 
128
{NUM10}"#"{NUM16}"."{NUM16}"#"{EXP} {
129
                   error (_("Based real literals not implemented yet."));
130
                }
131
 
132
{NUM10}"#"{NUM16}"."{NUM16}"#" {
133
                   error (_("Based real literals not implemented yet."));
134
                }
135
 
136
"'"({GRAPHIC}|\")"'" {
137
                   yylval.typed_val.type = type_char ();
138
                   yylval.typed_val.val = yytext[1];
139
                   return CHARLIT;
140
                }
141
 
142
"'[\""{HEXDIG}{2}"\"]'"   {
143
                   int v;
144
                   yylval.typed_val.type = type_char ();
145
                   sscanf (yytext+3, "%2x", &v);
146
                   yylval.typed_val.val = v;
147
                   return CHARLIT;
148
                }
149
 
150
\"({GRAPHIC}|"[\""({HEXDIG}{2}|\")"\"]")*\"   {
151
                   yylval.sval = processString (yytext+1, yyleng-2);
152
                   return STRING;
153
                }
154
 
155
\"              {
156
                   error (_("ill-formed or non-terminated string literal"));
157
                }
158
 
159
 
160
if              {
161
                  while (*lexptr != 'i' && *lexptr != 'I')
162
                    lexptr -= 1;
163
                  yyrestart(NULL);
164
                  return 0;
165
                }
166
 
167
(task|thread)   {
168
                  /* This keyword signals the end of the expression and
169
                     will be processed separately.  */
170
                  while (*lexptr != 't' && *lexptr != 'T')
171
                    lexptr--;
172
                  yyrestart(NULL);
173
                  return 0;
174
                }
175
 
176
        /* ADA KEYWORDS */
177
 
178
abs             { return ABS; }
179
and             { return _AND_; }
180
else            { return ELSE; }
181
in              { return IN; }
182
mod             { return MOD; }
183
new             { return NEW; }
184
not             { return NOT; }
185
null            { return NULL_PTR; }
186
or              { return OR; }
187
others          { return OTHERS; }
188
rem             { return REM; }
189
then            { return THEN; }
190
xor             { return XOR; }
191
 
192
        /* BOOLEAN "KEYWORDS" */
193
 
194
 /* True and False are not keywords in Ada, but rather enumeration constants.
195
    However, the boolean type is no longer represented as an enum, so True
196
    and False are no longer defined in symbol tables.  We compromise by
197
    making them keywords (when bare). */
198
 
199
true            { return TRUEKEYWORD; }
200
false           { return FALSEKEYWORD; }
201
 
202
        /* ATTRIBUTES */
203
 
204
{TICK}[a-zA-Z][a-zA-Z]+ { return processAttribute (yytext+1); }
205
 
206
        /* PUNCTUATION */
207
 
208
"=>"            { return ARROW; }
209
".."            { return DOTDOT; }
210
"**"            { return STARSTAR; }
211
":="            { return ASSIGN; }
212
"/="            { return NOTEQUAL; }
213
"<="            { return LEQ; }
214
">="            { return GEQ; }
215
 
216
"'" { BEGIN INITIAL; return '\''; }
217
 
218
[-&*+./:<>=|;\[\]] { return yytext[0]; }
219
 
220
","             { if (paren_depth == 0 && comma_terminates)
221
                    {
222
                      lexptr -= 1;
223
                      yyrestart(NULL);
224
                      return 0;
225
                    }
226
                  else
227
                    return ',';
228
                }
229
 
230
"("             { paren_depth += 1; return '('; }
231
")"             { if (paren_depth == 0)
232
                    {
233
                      lexptr -= 1;
234
                      yyrestart(NULL);
235
                      return 0;
236
                    }
237
                  else
238
                    {
239
                      paren_depth -= 1;
240
                      return ')';
241
                    }
242
                }
243
 
244
"."{WHITE}*all  { return DOT_ALL; }
245
 
246
"."{WHITE}*{ID} {
247
                  yylval.sval = processId (yytext+1, yyleng-1);
248
                  return DOT_ID;
249
                }
250
 
251
{ID}({WHITE}*"."{WHITE}*({ID}|\"{OPER}\"))*(" "*"'")?  {
252
                  int all_posn = find_dot_all (yytext);
253
 
254
                  if (all_posn == -1 && yytext[yyleng-1] == '\'')
255
                    {
256
                      BEGIN BEFORE_QUAL_QUOTE;
257
                      yyless (yyleng-1);
258
                    }
259
                  else if (all_posn >= 0)
260
                    yyless (all_posn);
261
                  yylval.sval = processId (yytext, yyleng);
262
                  return NAME;
263
               }
264
 
265
 
266
        /* GDB EXPRESSION CONSTRUCTS  */
267
 
268
"'"[^']+"'"{WHITE}*:: {
269
                  yyless (yyleng - 2);
270
                  yylval.sval = processId (yytext, yyleng);
271
                  return NAME;
272
                }
273
 
274
"::"            { return COLONCOLON; }
275
 
276
[{}@]           { return yytext[0]; }
277
 
278
        /* REGISTERS AND GDB CONVENIENCE VARIABLES */
279
 
280
"$"({LETTER}|{DIG}|"$")*  {
281
                  yylval.sval.ptr = yytext;
282
                  yylval.sval.length = yyleng;
283
                  return SPECIAL_VARIABLE;
284
                }
285
 
286
        /* CATCH-ALL ERROR CASE */
287
 
288
.               { error (_("Invalid character '%s' in expression."), yytext); }
289
%%
290
 
291
#include 
292
#include "gdb_string.h"
293
 
294
/* Initialize the lexer for processing new expression. */
295
 
296
void
297
lexer_init (FILE *inp)
298
{
299
  BEGIN INITIAL;
300
  yyrestart (inp);
301
}
302
 
303
 
304
/* Copy S2 to S1, removing all underscores, and downcasing all letters.  */
305
 
306
static void
307
canonicalizeNumeral (char *s1, const char *s2)
308
{
309
  for (; *s2 != '\000'; s2 += 1)
310
    {
311
      if (*s2 != '_')
312
        {
313
          *s1 = tolower(*s2);
314
          s1 += 1;
315
        }
316
    }
317
  s1[0] = '\000';
318
}
319
 
320
/* Interprets the prefix of NUM that consists of digits of the given BASE
321
   as an integer of that BASE, with the string EXP as an exponent.
322
   Puts value in yylval, and returns INT, if the string is valid.  Causes
323
   an error if the number is improperly formated.   BASE, if NULL, defaults
324
   to "10", and EXP to "1".  The EXP does not contain a leading 'e' or 'E'.
325
 */
326
 
327
static int
328
processInt (const char *base0, const char *num0, const char *exp0)
329
{
330
  ULONGEST result;
331
  long exp;
332
  int base;
333
 
334
  char *trailer;
335
 
336
  if (base0 == NULL)
337
    base = 10;
338
  else
339
    {
340
      base = strtol (base0, (char **) NULL, 10);
341
      if (base < 2 || base > 16)
342
        error (_("Invalid base: %d."), base);
343
    }
344
 
345
  if (exp0 == NULL)
346
    exp = 0;
347
  else
348
    exp = strtol(exp0, (char **) NULL, 10);
349
 
350
  errno = 0;
351
  result = strtoulst (num0, (const char **) &trailer, base);
352
  if (errno == ERANGE)
353
    error (_("Integer literal out of range"));
354
  if (isxdigit(*trailer))
355
    error (_("Invalid digit `%c' in based literal"), *trailer);
356
 
357
  while (exp > 0)
358
    {
359
      if (result > (ULONG_MAX / base))
360
        error (_("Integer literal out of range"));
361
      result *= base;
362
      exp -= 1;
363
    }
364
 
365
  if ((result >> (gdbarch_int_bit (parse_gdbarch)-1)) == 0)
366
    yylval.typed_val.type = type_int ();
367
  else if ((result >> (gdbarch_long_bit (parse_gdbarch)-1)) == 0)
368
    yylval.typed_val.type = type_long ();
369
  else if (((result >> (gdbarch_long_bit (parse_gdbarch)-1)) >> 1) == 0)
370
    {
371
      /* We have a number representable as an unsigned integer quantity.
372
         For consistency with the C treatment, we will treat it as an
373
         anonymous modular (unsigned) quantity.  Alas, the types are such
374
         that we need to store .val as a signed quantity.  Sorry
375
         for the mess, but C doesn't officially guarantee that a simple
376
         assignment does the trick (no, it doesn't; read the reference manual).
377
       */
378
      yylval.typed_val.type
379
        = builtin_type (parse_gdbarch)->builtin_unsigned_long;
380
      if (result & LONGEST_SIGN)
381
        yylval.typed_val.val =
382
          (LONGEST) (result & ~LONGEST_SIGN)
383
          - (LONGEST_SIGN>>1) - (LONGEST_SIGN>>1);
384
      else
385
        yylval.typed_val.val = (LONGEST) result;
386
      return INT;
387
    }
388
  else
389
    yylval.typed_val.type = type_long_long ();
390
 
391
  yylval.typed_val.val = (LONGEST) result;
392
  return INT;
393
}
394
 
395
static int
396
processReal (const char *num0)
397
{
398
  sscanf (num0, "%" DOUBLEST_SCAN_FORMAT, &yylval.typed_val_float.dval);
399
 
400
  yylval.typed_val_float.type = type_float ();
401
  if (sizeof(DOUBLEST) >= gdbarch_double_bit (parse_gdbarch)
402
                            / TARGET_CHAR_BIT)
403
    yylval.typed_val_float.type = type_double ();
404
  if (sizeof(DOUBLEST) >= gdbarch_long_double_bit (parse_gdbarch)
405
                            / TARGET_CHAR_BIT)
406
    yylval.typed_val_float.type = type_long_double ();
407
 
408
  return FLOAT;
409
}
410
 
411
 
412
/* Store a canonicalized version of NAME0[0..LEN-1] in yylval.ssym.  The
413
   resulting string is valid until the next call to ada_parse.  It differs
414
   from NAME0 in that:
415
    + Characters between '...' or <...> are transfered verbatim to
416
      yylval.ssym.
417
    + <, >, and trailing "'" characters in quoted sequences are removed
418
      (a leading quote is preserved to indicate that the name is not to be
419
      GNAT-encoded).
420
    + Unquoted whitespace is removed.
421
    + Unquoted alphabetic characters are mapped to lower case.
422
   Result is returned as a struct stoken, but for convenience, the string
423
   is also null-terminated.  Result string valid until the next call of
424
   ada_parse.
425
 */
426
static struct stoken
427
processId (const char *name0, int len)
428
{
429
  char *name = obstack_alloc (&temp_parse_space, len + 11);
430
  int i0, i;
431
  struct stoken result;
432
 
433
  while (len > 0 && isspace (name0[len-1]))
434
    len -= 1;
435
  i = i0 = 0;
436
  while (i0 < len)
437
    {
438
      if (isalnum (name0[i0]))
439
        {
440
          name[i] = tolower (name0[i0]);
441
          i += 1; i0 += 1;
442
        }
443
      else switch (name0[i0])
444
        {
445
        default:
446
          name[i] = name0[i0];
447
          i += 1; i0 += 1;
448
          break;
449
        case ' ': case '\t':
450
          i0 += 1;
451
          break;
452
        case '\'':
453
          do
454
            {
455
              name[i] = name0[i0];
456
              i += 1; i0 += 1;
457
            }
458
          while (i0 < len && name0[i0] != '\'');
459
          i0 += 1;
460
          break;
461
        case '<':
462
          i0 += 1;
463
          while (i0 < len && name0[i0] != '>')
464
            {
465
              name[i] = name0[i0];
466
              i += 1; i0 += 1;
467
            }
468
          i0 += 1;
469
          break;
470
        }
471
    }
472
  name[i] = '\000';
473
 
474
  result.ptr = name;
475
  result.length = i;
476
  return result;
477
}
478
 
479
/* Return TEXT[0..LEN-1], a string literal without surrounding quotes,
480
   with special hex character notations replaced with characters.
481
   Result valid until the next call to ada_parse.  */
482
 
483
static struct stoken
484
processString (const char *text, int len)
485
{
486
  const char *p;
487
  char *q;
488
  const char *lim = text + len;
489
  struct stoken result;
490
 
491
  q = result.ptr = obstack_alloc (&temp_parse_space, len);
492
  p = text;
493
  while (p < lim)
494
    {
495
      if (p[0] == '[' && p[1] == '"' && p+2 < lim)
496
         {
497
           if (p[2] == '"')  /* "...["""]... */
498
             {
499
               *q = '"';
500
               p += 4;
501
             }
502
           else
503
             {
504
               int chr;
505
               sscanf (p+2, "%2x", &chr);
506
               *q = (char) chr;
507
               p += 5;
508
             }
509
         }
510
       else
511
         *q = *p;
512
       q += 1;
513
       p += 1;
514
     }
515
  result.length = q - result.ptr;
516
  return result;
517
}
518
 
519
/* Returns the position within STR of the '.' in a
520
   '.{WHITE}*all' component of a dotted name, or -1 if there is none.
521
   Note: we actually don't need this routine, since 'all' can never be an
522
   Ada identifier.  Thus, looking up foo.all or foo.all.x as a name
523
   must fail, and will eventually be interpreted as (foo).all or
524
   (foo).all.x.  However, this does avoid an extraneous lookup. */
525
 
526
static int
527
find_dot_all (const char *str)
528
{
529
  int i;
530
  for (i = 0; str[i] != '\000'; i += 1)
531
    {
532
      if (str[i] == '.')
533
        {
534
          int i0 = i;
535
          do
536
            i += 1;
537
          while (isspace (str[i]));
538
          if (strncmp (str+i, "all", 3) == 0
539
              && ! isalnum (str[i+3]) && str[i+3] != '_')
540
            return i0;
541
        }
542
    }
543
  return -1;
544
}
545
 
546
/* Returns non-zero iff string SUBSEQ matches a subsequence of STR, ignoring
547
   case.  */
548
 
549
static int
550
subseqMatch (const char *subseq, const char *str)
551
{
552
  if (subseq[0] == '\0')
553
    return 1;
554
  else if (str[0] == '\0')
555
    return 0;
556
  else if (tolower (subseq[0]) == tolower (str[0]))
557
    return subseqMatch (subseq+1, str+1) || subseqMatch (subseq, str+1);
558
  else
559
    return subseqMatch (subseq, str+1);
560
}
561
 
562
 
563
static struct { const char *name; int code; }
564
attributes[] = {
565
  { "address", TICK_ADDRESS },
566
  { "unchecked_access", TICK_ACCESS },
567
  { "unrestricted_access", TICK_ACCESS },
568
  { "access", TICK_ACCESS },
569
  { "first", TICK_FIRST },
570
  { "last", TICK_LAST },
571
  { "length", TICK_LENGTH },
572
  { "max", TICK_MAX },
573
  { "min", TICK_MIN },
574
  { "modulus", TICK_MODULUS },
575
  { "pos", TICK_POS },
576
  { "range", TICK_RANGE },
577
  { "size", TICK_SIZE },
578
  { "tag", TICK_TAG },
579
  { "val", TICK_VAL },
580
  { NULL, -1 }
581
};
582
 
583
/* Return the syntactic code corresponding to the attribute name or
584
   abbreviation STR.  */
585
 
586
static int
587
processAttribute (const char *str)
588
{
589
  int i, k;
590
 
591
  for (i = 0; attributes[i].code != -1; i += 1)
592
    if (strcasecmp (str, attributes[i].name) == 0)
593
      return attributes[i].code;
594
 
595
  for (i = 0, k = -1; attributes[i].code != -1; i += 1)
596
    if (subseqMatch (str, attributes[i].name))
597
      {
598
        if (k == -1)
599
          k = i;
600
        else
601
          error (_("ambiguous attribute name: `%s'"), str);
602
      }
603
  if (k == -1)
604
    error (_("unrecognized attribute: `%s'"), str);
605
 
606
  return attributes[k].code;
607
}
608
 
609
int
610
yywrap(void)
611
{
612
  return 1;
613
}
614
 
615
/* Dummy definition to suppress warnings about unused static definitions. */
616
typedef void (*dummy_function) ();
617
dummy_function ada_flex_use[] =
618
{
619
  (dummy_function) yyunput
620
};

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.