mirror of
https://github.com/autc04/Retro68.git
synced 2024-06-01 15:41:39 +00:00
419 lines
11 KiB
Plaintext
419 lines
11 KiB
Plaintext
/* Copyright (C) 2021 Free Software Foundation, Inc.
|
|
Contributed by Oracle.
|
|
|
|
This file is part of GNU Binutils.
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 3, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, 51 Franklin Street - Fifth Floor, Boston,
|
|
MA 02110-1301, USA. */
|
|
|
|
// To rebuild QLParser.tab.cc and QLParser.tab.hh, use bison 3.6 or newer:
|
|
// cd gprofng/src && bison QLParser.yy
|
|
|
|
// For "api.parser.class"
|
|
%require "3.0"
|
|
%language "C++"
|
|
|
|
%code top {
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <string>
|
|
}
|
|
%code requires {
|
|
#include "QLParser.h"
|
|
#include "DbeSession.h"
|
|
#include "Expression.h"
|
|
#include "Table.h"
|
|
#include "i18n.h"
|
|
}
|
|
|
|
%code
|
|
{
|
|
namespace QL
|
|
{
|
|
static QL::Parser::symbol_type yylex (QL::Result &result);
|
|
|
|
static Expression *
|
|
processName (std::string str)
|
|
{
|
|
const char *name = str.c_str();
|
|
int propID = dbeSession->getPropIdByName (name);
|
|
if (propID != PROP_NONE)
|
|
return new Expression (Expression::OP_NAME,
|
|
new Expression (Expression::OP_NUM, (uint64_t) propID));
|
|
|
|
// If a name is not statically known try user defined objects
|
|
Expression *expr = dbeSession->findObjDefByName (name);
|
|
if (expr != NULL)
|
|
return expr->copy();
|
|
|
|
throw Parser::syntax_error ("Name not found");
|
|
}
|
|
}
|
|
}
|
|
|
|
%defines
|
|
%define api.namespace {QL}
|
|
// in Bison 3.3, use %define api.parser.class {Parser} instead parser_class_name
|
|
%define parser_class_name {Parser}
|
|
%define api.token.constructor
|
|
%define api.value.type variant
|
|
// Later: api.value.automove
|
|
%define api.token.prefix {L_}
|
|
%define parse.assert
|
|
%param {QL::Result &result}
|
|
|
|
%start S
|
|
|
|
%token LPAR "("
|
|
RPAR ")"
|
|
HASPROP
|
|
FILEIOVFD
|
|
|
|
%token YYEOF 0
|
|
%token <uint64_t> NUM FNAME JGROUP JPARENT QSTR
|
|
%token <std::string> NAME
|
|
|
|
%nonassoc IN SOME ORDR
|
|
%left COMMA ","
|
|
%right QWE "?"
|
|
COLON ":"
|
|
%left AND "&&"
|
|
OR "|"
|
|
EQV NEQV
|
|
BITAND BITOR
|
|
BITXOR "^"
|
|
%nonassoc EQ "="
|
|
NE "!="
|
|
LT "<"
|
|
GT ">"
|
|
LE "<="
|
|
GE ">="
|
|
%left LS "<<"
|
|
RS ">>"
|
|
ADD "+"
|
|
MINUS "-"
|
|
MUL "*"
|
|
DIV "/"
|
|
REM "%"
|
|
%right DEG
|
|
NOT "!"
|
|
BITNOT "~"
|
|
|
|
%type <Expression *> exp term
|
|
|
|
// %destructor { delete $$; } <Expression *>;
|
|
|
|
%%
|
|
|
|
S: /* empty */ { result.out = new Expression (Expression::OP_NUM, (uint64_t) 1); }
|
|
| exp { result.out = $1; }
|
|
|
|
exp: exp DEG exp { $$ = new Expression (Expression::OP_DEG, $1, $3); } /* dead? */
|
|
| exp MUL exp { $$ = new Expression (Expression::OP_MUL, $1, $3); }
|
|
| exp DIV exp { $$ = new Expression (Expression::OP_DIV, $1, $3); }
|
|
| exp REM exp { $$ = new Expression (Expression::OP_REM, $1, $3); }
|
|
| exp ADD exp { $$ = new Expression (Expression::OP_ADD, $1, $3); }
|
|
| exp MINUS exp { $$ = new Expression (Expression::OP_MINUS, $1, $3); }
|
|
| exp LS exp { $$ = new Expression (Expression::OP_LS, $1, $3); }
|
|
| exp RS exp { $$ = new Expression (Expression::OP_RS, $1, $3); }
|
|
| exp LT exp { $$ = new Expression (Expression::OP_LT, $1, $3); }
|
|
| exp LE exp { $$ = new Expression (Expression::OP_LE, $1, $3); }
|
|
| exp GT exp { $$ = new Expression (Expression::OP_GT, $1, $3); }
|
|
| exp GE exp { $$ = new Expression (Expression::OP_GE, $1, $3); }
|
|
| exp EQ exp { $$ = new Expression (Expression::OP_EQ, $1, $3); }
|
|
| exp NE exp { $$ = new Expression (Expression::OP_NE, $1, $3); }
|
|
| exp BITAND exp { $$ = new Expression (Expression::OP_BITAND, $1, $3); }
|
|
| exp BITXOR exp { $$ = new Expression (Expression::OP_BITXOR, $1, $3); }
|
|
| exp BITOR exp { $$ = new Expression (Expression::OP_BITOR, $1, $3); }
|
|
| exp AND exp { $$ = new Expression (Expression::OP_AND, $1, $3); }
|
|
| exp OR exp { $$ = new Expression (Expression::OP_OR, $1, $3); }
|
|
| exp NEQV exp { $$ = new Expression (Expression::OP_NEQV, $1, $3); } /* dead? */
|
|
| exp EQV exp { $$ = new Expression (Expression::OP_EQV, $1, $3); } /* dead? */
|
|
| exp QWE exp COLON exp
|
|
{
|
|
$$ = new Expression (Expression::OP_QWE, $1,
|
|
new Expression (Expression::OP_COLON, $3, $5));
|
|
}
|
|
| exp COMMA exp { $$ = new Expression (Expression::OP_COMMA, $1, $3); }
|
|
| exp IN exp { $$ = new Expression (Expression::OP_IN, $1, $3); }
|
|
| exp SOME IN exp { $$ = new Expression (Expression::OP_SOMEIN, $1, $4); }
|
|
| exp ORDR IN exp { $$ = new Expression (Expression::OP_ORDRIN, $1, $4); }
|
|
| term { $$ = $1; }
|
|
|
|
term: MINUS term
|
|
{
|
|
$$ = new Expression (Expression::OP_MINUS,
|
|
new Expression (Expression::OP_NUM, (uint64_t) 0), $2);
|
|
}
|
|
| NOT term { $$ = new Expression (Expression::OP_NOT, $2); }
|
|
| BITNOT term { $$ = new Expression (Expression::OP_BITNOT, $2); }
|
|
| LPAR exp RPAR { $$ = $2; }
|
|
| FNAME LPAR QSTR RPAR
|
|
{
|
|
$$ = new Expression (Expression::OP_FUNC,
|
|
new Expression (Expression::OP_NUM, $1),
|
|
new Expression (Expression::OP_NUM, $3));
|
|
}
|
|
| HASPROP LPAR NAME RPAR
|
|
{
|
|
$$ = new Expression (Expression::OP_HASPROP,
|
|
new Expression (Expression::OP_NUM, processName($3)));
|
|
}
|
|
| JGROUP LPAR QSTR RPAR
|
|
{
|
|
$$ = new Expression (Expression::OP_JAVA,
|
|
new Expression (Expression::OP_NUM, $1),
|
|
new Expression (Expression::OP_NUM, $3));
|
|
}
|
|
| JPARENT LPAR QSTR RPAR
|
|
{
|
|
$$ = new Expression (Expression::OP_JAVA,
|
|
new Expression (Expression::OP_NUM, $1),
|
|
new Expression (Expression::OP_NUM, $3));
|
|
}
|
|
| FILEIOVFD LPAR QSTR RPAR
|
|
{
|
|
$$ = new Expression (Expression::OP_FILE,
|
|
new Expression (Expression::OP_NUM, (uint64_t) 0),
|
|
new Expression (Expression::OP_NUM, $3));
|
|
}
|
|
| NUM { $$ = new Expression (Expression::OP_NUM, $1); }
|
|
| NAME { $$ = processName($1); }
|
|
|
|
%%
|
|
|
|
namespace QL
|
|
{
|
|
static Parser::symbol_type
|
|
unget_ret (std::istream &in, char c, Parser::symbol_type tok)
|
|
{
|
|
in.putback (c);
|
|
return tok;
|
|
}
|
|
|
|
static Parser::symbol_type
|
|
yylex (QL::Result &result)
|
|
{
|
|
int base = 0;
|
|
int c;
|
|
|
|
do
|
|
c = result.in.get ();
|
|
while (result.in && (c == ' ' || c == '\t'));
|
|
if (!result.in)
|
|
return Parser::make_YYEOF ();
|
|
|
|
switch (c)
|
|
{
|
|
case '\0':
|
|
case '\n': return Parser::make_YYEOF ();
|
|
case '(': return Parser::make_LPAR () ;
|
|
case ')': return Parser::make_RPAR ();
|
|
case ',': return Parser::make_COMMA ();
|
|
case '%': return Parser::make_REM ();
|
|
case '/': return Parser::make_DIV ();
|
|
case '*': return Parser::make_MUL ();
|
|
case '-': return Parser::make_MINUS ();
|
|
case '+': return Parser::make_ADD ();
|
|
case '~': return Parser::make_BITNOT ();
|
|
case '^': return Parser::make_BITXOR ();
|
|
case '?': return Parser::make_QWE ();
|
|
case ':': return Parser::make_COLON ();
|
|
case '|':
|
|
c = result.in.get ();
|
|
if (c == '|')
|
|
return Parser::make_OR ();
|
|
else
|
|
return unget_ret (result.in, c, Parser::make_BITOR ());
|
|
case '&':
|
|
c = result.in.get ();
|
|
if (c == '&')
|
|
return Parser::make_AND ();
|
|
else
|
|
return unget_ret (result.in, c, Parser::make_BITAND ());
|
|
case '!':
|
|
c = result.in.get ();
|
|
if (c == '=')
|
|
return Parser::make_NE ();
|
|
else
|
|
return unget_ret (result.in, c, Parser::make_NOT ());
|
|
case '=':
|
|
c = result.in.get ();
|
|
if (c == '=')
|
|
return Parser::make_EQ ();
|
|
else
|
|
throw Parser::syntax_error ("Syntax error after =");
|
|
case '<':
|
|
c = result.in.get ();
|
|
if (c == '=')
|
|
return Parser::make_LE ();
|
|
else if (c == '<')
|
|
return Parser::make_LS ();
|
|
else
|
|
return unget_ret (result.in, c, Parser::make_LT ());
|
|
case '>':
|
|
c = result.in.get ();
|
|
if (c == '=')
|
|
return Parser::make_GE ();
|
|
else if (c == '>')
|
|
return Parser::make_RS ();
|
|
else
|
|
return unget_ret (result.in, c, Parser::make_GT ());
|
|
case '"':
|
|
{
|
|
int maxsz = 16;
|
|
char *str = (char *) malloc (maxsz);
|
|
char *ptr = str;
|
|
|
|
for (;;)
|
|
{
|
|
c = result.in.get ();
|
|
if (!result.in)
|
|
{
|
|
free (str);
|
|
throw Parser::syntax_error ("Unclosed \"");
|
|
}
|
|
|
|
switch (c)
|
|
{
|
|
case '"':
|
|
*ptr = (char)0;
|
|
// XXX omazur: need new string type
|
|
return Parser::make_QSTR ((uint64_t) str);
|
|
case 0:
|
|
case '\n':
|
|
free (str);
|
|
throw Parser::syntax_error ("Multiline strings are not supported");
|
|
default:
|
|
if (ptr - str >= maxsz)
|
|
{
|
|
size_t len = ptr - str;
|
|
maxsz = maxsz > 8192 ? maxsz + 8192 : maxsz * 2;
|
|
char *new_s = (char *) realloc (str, maxsz);
|
|
str = new_s;
|
|
ptr = str + len;
|
|
}
|
|
*ptr++ = c;
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
if (c == '0')
|
|
{
|
|
base = 8;
|
|
c = result.in.get ();
|
|
if ( c == 'x' )
|
|
{
|
|
base = 16;
|
|
c = result.in.get ();
|
|
}
|
|
}
|
|
else if (c >= '1' && c <='9')
|
|
base = 10;
|
|
|
|
if (base)
|
|
{
|
|
uint64_t lval = 0;
|
|
for (;;)
|
|
{
|
|
int digit = -1;
|
|
switch (c)
|
|
{
|
|
case '0': case '1': case '2': case '3':
|
|
case '4': case '5': case '6': case '7':
|
|
digit = c - '0';
|
|
break;
|
|
case '8': case '9':
|
|
if (base > 8)
|
|
digit = c - '0';
|
|
break;
|
|
case 'a': case 'b': case 'c':
|
|
case 'd': case 'e': case 'f':
|
|
if (base == 16)
|
|
digit = c - 'a' + 10;
|
|
break;
|
|
case 'A': case 'B': case 'C':
|
|
case 'D': case 'E': case 'F':
|
|
if (base == 16)
|
|
digit = c - 'A' + 10;
|
|
break;
|
|
}
|
|
if (digit == -1)
|
|
{
|
|
result.in.putback (c);
|
|
break;
|
|
}
|
|
lval = lval * base + digit;
|
|
c = result.in.get ();
|
|
}
|
|
return Parser::make_NUM (lval);
|
|
}
|
|
|
|
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
|
|
{
|
|
char name[32]; // omazur XXX: accept any length
|
|
name[0] = (char)c;
|
|
for (size_t i = 1; i < sizeof (name); i++)
|
|
{
|
|
c = result.in.get ();
|
|
if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
|
|
(c >= '0' && c <= '9') || (c == '_'))
|
|
name[i] = c;
|
|
else
|
|
{
|
|
name[i] = (char)0;
|
|
result.in.putback (c);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (strcasecmp (name, NTXT ("IN")) == 0)
|
|
return Parser::make_IN ();
|
|
else if (strcasecmp (name, NTXT ("SOME")) == 0)
|
|
return Parser::make_SOME ();
|
|
else if (strcasecmp (name, NTXT ("ORDERED")) == 0)
|
|
return Parser::make_ORDR ();
|
|
else if (strcasecmp (name, NTXT ("TRUE")) == 0)
|
|
return Parser::make_NUM ((uint64_t) 1);
|
|
else if (strcasecmp (name, NTXT ("FALSE")) == 0)
|
|
return Parser::make_NUM ((uint64_t) 0);
|
|
else if (strcasecmp (name, NTXT ("FNAME")) == 0)
|
|
return Parser::make_FNAME (Expression::FUNC_FNAME);
|
|
else if (strcasecmp (name, NTXT ("HAS_PROP")) == 0)
|
|
return Parser::make_HASPROP ();
|
|
else if (strcasecmp (name, NTXT ("JGROUP")) == 0)
|
|
return Parser::make_JGROUP (Expression::JAVA_JGROUP);
|
|
else if (strcasecmp (name, NTXT ("JPARENT")) == 0 )
|
|
return Parser::make_JPARENT (Expression::JAVA_JPARENT);
|
|
else if (strcasecmp (name, NTXT ("DNAME")) == 0)
|
|
return Parser::make_FNAME (Expression::FUNC_DNAME);
|
|
else if (strcasecmp (name, NTXT ("FILEIOVFD")) == 0 )
|
|
return Parser::make_FILEIOVFD ();
|
|
|
|
std::string nm = std::string (name);
|
|
return Parser::make_NAME (nm);
|
|
}
|
|
|
|
throw Parser::syntax_error ("Syntax error");
|
|
}
|
|
}
|
|
void
|
|
Parser::error (const std::string &)
|
|
{
|
|
// do nothing for now
|
|
}
|
|
}
|
|
|