Automatic date update in version.in
[binutils-gdb.git] / gprofng / src / QLParser.yy
blobd7f732c737d3bcec1a1b76dcd0b867f06f7c732e
1 /* Copyright (C) 2021 Free Software Foundation, Inc.
2    Contributed by Oracle.
4    This file is part of GNU Binutils.
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, or (at your option)
9    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, write to the Free Software
18    Foundation, 51 Franklin Street - Fifth Floor, Boston,
19    MA 02110-1301, USA.  */
21 // To rebuild QLParser.tab.cc and QLParser.tab.hh, use bison 3.6 or newer:
22 // cd gprofng/src && bison QLParser.yy
24 // For "api.parser.class"
25 %require "3.0"
26 %language "C++"
28 %code top {
29 #include <stdio.h>
30 #include <string.h>
31 #include <string>
33 %code requires {
34 #include "QLParser.h"
35 #include "DbeSession.h"
36 #include "Expression.h"
37 #include "Table.h"
38 #include "i18n.h"
41 %code
43 namespace QL
45   static QL::Parser::symbol_type yylex (QL::Result &result);
47   static Expression *
48   processName (std::string str)
49   {
50     const char *name = str.c_str();
51     int propID = dbeSession->getPropIdByName (name);
52     if (propID != PROP_NONE)
53       return new Expression (Expression::OP_NAME,
54                       new Expression (Expression::OP_NUM, (uint64_t) propID));
56     // If a name is not statically known try user defined objects
57     Expression *expr = dbeSession->findObjDefByName (name);
58     if (expr != NULL)
59       return expr->copy();
61     throw Parser::syntax_error ("Name not found");
62   }
66 %defines
67 %define api.namespace {QL}
68 // in Bison 3.3, use %define api.parser.class {Parser} instead parser_class_name
69 %define parser_class_name {Parser}
70 %define api.token.constructor
71 %define api.value.type variant
72 // Later: api.value.automove
73 %define api.token.prefix {L_}
74 %define parse.assert
75 %param {QL::Result &result}
77 %start S
79 %token LPAR "("
80   RPAR ")"
81   HASPROP
82   FILEIOVFD
84 %token YYEOF 0
85 %token <uint64_t> NUM FNAME JGROUP JPARENT QSTR
86 %token <std::string> NAME
88 %nonassoc IN SOME ORDR
89 %left  COMMA ","
90 %right QWE "?"
91        COLON ":"
92 %left  AND "&&"
93        OR "|"
94        EQV NEQV
95        BITAND BITOR
96        BITXOR "^"
97 %nonassoc EQ "="
98           NE "!="
99           LT "<"
100           GT ">"
101           LE "<="
102           GE ">="
103 %left LS "<<"
104       RS ">>"
105       ADD "+"
106       MINUS "-"
107       MUL "*"
108       DIV "/"
109       REM "%"
110 %right DEG
111        NOT "!"
112        BITNOT "~"
114 %type <Expression *>  exp term
116 // %destructor { delete $$; } <Expression *>;
120 S:      /* empty */             { result.out = new Expression (Expression::OP_NUM, (uint64_t) 1); }
121 |       exp                     { result.out = $1; }
123 exp:      exp DEG exp           { $$ = new Expression (Expression::OP_DEG, $1, $3); } /* dead? */
124         | exp MUL exp           { $$ = new Expression (Expression::OP_MUL, $1, $3); }
125         | exp DIV exp           { $$ = new Expression (Expression::OP_DIV, $1, $3); }
126         | exp REM exp           { $$ = new Expression (Expression::OP_REM, $1, $3); }
127         | exp ADD exp           { $$ = new Expression (Expression::OP_ADD, $1, $3); }
128         | exp MINUS exp         { $$ = new Expression (Expression::OP_MINUS, $1, $3); }
129         | exp LS  exp           { $$ = new Expression (Expression::OP_LS, $1, $3); }
130         | exp RS  exp           { $$ = new Expression (Expression::OP_RS, $1, $3); }
131         | exp LT  exp           { $$ = new Expression (Expression::OP_LT, $1, $3); }
132         | exp LE  exp           { $$ = new Expression (Expression::OP_LE, $1, $3); }
133         | exp GT  exp           { $$ = new Expression (Expression::OP_GT, $1, $3); }
134         | exp GE  exp           { $$ = new Expression (Expression::OP_GE, $1, $3); }
135         | exp EQ  exp           { $$ = new Expression (Expression::OP_EQ, $1, $3); }
136         | exp NE  exp           { $$ = new Expression (Expression::OP_NE, $1, $3); }
137         | exp BITAND exp        { $$ = new Expression (Expression::OP_BITAND, $1, $3); }
138         | exp BITXOR exp        { $$ = new Expression (Expression::OP_BITXOR, $1, $3); }
139         | exp BITOR  exp        { $$ = new Expression (Expression::OP_BITOR, $1, $3); }
140         | exp AND exp           { $$ = new Expression (Expression::OP_AND, $1, $3); }
141         | exp OR  exp           { $$ = new Expression (Expression::OP_OR, $1, $3); }
142         | exp NEQV exp          { $$ = new Expression (Expression::OP_NEQV, $1, $3); } /* dead? */
143         | exp EQV exp           { $$ = new Expression (Expression::OP_EQV, $1, $3); } /* dead? */
144         | exp QWE exp COLON exp
145           {
146              $$ = new Expression (Expression::OP_QWE, $1,
147                                   new Expression (Expression::OP_COLON, $3, $5));
148           }
149         | exp COMMA  exp        { $$ = new Expression (Expression::OP_COMMA, $1, $3); }
150         | exp IN exp            { $$ = new Expression (Expression::OP_IN, $1, $3); }
151         | exp SOME IN exp       { $$ = new Expression (Expression::OP_SOMEIN, $1, $4); }
152         | exp ORDR IN exp       { $$ = new Expression (Expression::OP_ORDRIN, $1, $4); }
153         | term                  { $$ = $1; }
155 term:     MINUS term
156           {
157              $$ = new Expression (Expression::OP_MINUS,
158                                   new Expression (Expression::OP_NUM, (uint64_t) 0), $2);
159           }
160         | NOT    term           { $$ = new Expression (Expression::OP_NOT, $2); }
161         | BITNOT term           { $$ = new Expression (Expression::OP_BITNOT, $2); }
162         | LPAR exp RPAR         { $$ = $2; }
163         | FNAME LPAR QSTR RPAR
164           {
165             $$ = new Expression (Expression::OP_FUNC,
166                                  new Expression (Expression::OP_NUM, $1),
167                                  new Expression (Expression::OP_NUM, $3));
168           }
169         | HASPROP LPAR NAME RPAR
170           {
171             $$ = new Expression (Expression::OP_HASPROP,
172                                  new Expression (Expression::OP_NUM, processName($3)));
173           }
174         | JGROUP LPAR QSTR RPAR
175           {
176             $$ = new Expression (Expression::OP_JAVA,
177                                  new Expression (Expression::OP_NUM, $1),
178                                  new Expression (Expression::OP_NUM, $3));
179           }
180         | JPARENT LPAR QSTR RPAR
181           {
182              $$ = new Expression (Expression::OP_JAVA,
183                                   new Expression (Expression::OP_NUM, $1),
184                                   new Expression (Expression::OP_NUM, $3));
185           }
186         | FILEIOVFD LPAR QSTR RPAR
187           {
188             $$ = new Expression (Expression::OP_FILE,
189                                  new Expression (Expression::OP_NUM, (uint64_t) 0),
190                                  new Expression (Expression::OP_NUM, $3));
191           }
192         | NUM                   { $$ = new Expression (Expression::OP_NUM, $1); }
193         | NAME                  { $$ = processName($1); }
197 namespace QL
199   static Parser::symbol_type
200   unget_ret (std::istream &in, char c, Parser::symbol_type tok)
201   {
202     in.putback (c);
203     return tok;
204   }
206   static Parser::symbol_type
207   yylex (QL::Result &result)
208   {
209     int base = 0;
210     int c;
212     do
213       c = result.in.get ();
214     while (result.in && (c == ' ' || c == '\t'));
215     if (!result.in)
216       return Parser::make_YYEOF ();
218     switch (c)
219       {
220       case '\0':
221       case '\n': return Parser::make_YYEOF ();
222       case '(': return Parser::make_LPAR () ;
223       case ')': return Parser::make_RPAR ();
224       case ',': return Parser::make_COMMA ();
225       case '%': return Parser::make_REM ();
226       case '/': return Parser::make_DIV ();
227       case '*': return Parser::make_MUL ();
228       case '-': return Parser::make_MINUS ();
229       case '+': return Parser::make_ADD ();
230       case '~': return Parser::make_BITNOT ();
231       case '^': return Parser::make_BITXOR ();
232       case '?': return Parser::make_QWE ();
233       case ':': return Parser::make_COLON ();
234       case '|':
235         c = result.in.get ();
236         if (c == '|')
237           return Parser::make_OR ();
238         else
239           return unget_ret (result.in, c, Parser::make_BITOR ());
240       case '&':
241         c = result.in.get ();
242         if (c == '&')
243           return Parser::make_AND ();
244         else
245           return unget_ret (result.in, c, Parser::make_BITAND ());
246       case '!':
247         c = result.in.get ();
248         if (c == '=')
249           return Parser::make_NE ();
250         else
251           return unget_ret (result.in, c, Parser::make_NOT ());
252       case '=':
253         c = result.in.get ();
254         if (c == '=')
255           return Parser::make_EQ ();
256         else
257           throw Parser::syntax_error ("Syntax error after =");
258       case '<':
259         c = result.in.get ();
260         if (c == '=')
261           return Parser::make_LE ();
262         else if (c == '<')
263           return Parser::make_LS ();
264         else
265           return unget_ret (result.in, c, Parser::make_LT ());
266       case '>':
267         c = result.in.get ();
268         if (c == '=')
269           return Parser::make_GE ();
270         else if (c == '>')
271           return Parser::make_RS ();
272         else
273           return unget_ret (result.in, c, Parser::make_GT ());
274       case '"':
275         {
276           int  maxsz = 16;
277           char *str = (char *) malloc (maxsz);
278           char *ptr = str;
280           for (;;)
281             {
282               c = result.in.get ();
283               if (!result.in)
284                 {
285                   free (str);
286                   throw Parser::syntax_error ("Unclosed \"");
287                 }
289               switch (c)
290                 {
291                 case '"':
292                   *ptr = (char)0;
293                   // XXX omazur: need new string type
294                   return Parser::make_QSTR ((uint64_t) str);
295                 case 0:
296                 case '\n':
297                   free (str);
298                   throw Parser::syntax_error ("Multiline strings are not supported");
299                 default:
300                   if (ptr - str >= maxsz)
301                     {
302                       size_t len = ptr - str;
303                       maxsz = maxsz > 8192 ? maxsz + 8192 : maxsz * 2;
304                       char *new_s = (char *) realloc (str, maxsz);
305                       str = new_s;
306                       ptr = str + len;
307                     }
308                   *ptr++ = c;
309                 }
310             }
311         }
312       default:
313         if (c == '0')
314           {
315             base = 8;
316             c = result.in.get ();
317             if ( c == 'x' )
318               {
319                 base = 16;
320                 c = result.in.get ();
321               }
322           }
323         else if (c >= '1' && c <='9')
324           base = 10;
326         if (base)
327           {
328             uint64_t lval = 0;
329             for (;;)
330               {
331                 int digit = -1;
332                 switch (c)
333                   {
334                   case '0': case '1': case '2': case '3':
335                   case '4': case '5': case '6': case '7':
336                     digit = c - '0';
337                     break;
338                   case '8': case '9':
339                     if (base > 8)
340                       digit = c - '0';
341                     break;
342                   case 'a': case 'b': case 'c':
343                   case 'd': case 'e': case 'f':
344                     if (base == 16)
345                       digit = c - 'a' + 10;
346                     break;
347                   case 'A': case 'B': case 'C':
348                   case 'D': case 'E': case 'F':
349                     if (base == 16)
350                       digit = c - 'A' + 10;
351                     break;
352                   }
353                 if  (digit == -1)
354                   {
355                     result.in.putback (c);
356                     break;
357                   }
358                 lval = lval * base + digit;
359                 c = result.in.get ();
360               }
361             return Parser::make_NUM (lval);
362           }
364         if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
365           {
366             char name[32];      // omazur XXX: accept any length
367             name[0] = (char)c;
368             for (size_t i = 1; i < sizeof (name); i++)
369               {
370                 c = result.in.get ();
371                 if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
372                     (c >= '0' && c <= '9') || (c == '_'))
373                   name[i] = c;
374                 else
375                   {
376                     name[i] = (char)0;
377                     result.in.putback (c);
378                     break;
379                   }
380               }
382             if (strcasecmp (name, NTXT ("IN")) == 0)
383               return Parser::make_IN ();
384             else if (strcasecmp (name, NTXT ("SOME")) == 0)
385               return Parser::make_SOME ();
386             else if (strcasecmp (name, NTXT ("ORDERED")) == 0)
387               return Parser::make_ORDR ();
388             else if (strcasecmp (name, NTXT ("TRUE")) == 0)
389               return Parser::make_NUM ((uint64_t) 1);
390             else if (strcasecmp (name, NTXT ("FALSE")) == 0)
391               return Parser::make_NUM ((uint64_t) 0);
392             else if (strcasecmp (name, NTXT ("FNAME")) == 0)
393               return Parser::make_FNAME (Expression::FUNC_FNAME);
394             else if (strcasecmp (name, NTXT ("HAS_PROP")) == 0)
395               return Parser::make_HASPROP ();
396             else if (strcasecmp (name, NTXT ("JGROUP")) == 0)
397               return Parser::make_JGROUP (Expression::JAVA_JGROUP);
398             else if (strcasecmp (name, NTXT ("JPARENT")) == 0 )
399               return Parser::make_JPARENT (Expression::JAVA_JPARENT);
400             else if (strcasecmp (name, NTXT ("DNAME")) == 0)
401               return Parser::make_FNAME (Expression::FUNC_DNAME);
402             else if (strcasecmp (name, NTXT ("FILEIOVFD")) == 0 )
403               return Parser::make_FILEIOVFD ();
405             std::string nm = std::string (name);
406             return Parser::make_NAME (nm);
407           }
409         throw Parser::syntax_error ("Syntax error");
410       }
411   }
412   void
413   Parser::error (const std::string &)
414   {
415     // do nothing for now
416   }