Back to home page

Enduro/X

 
 

    


0001 /**
0002  * @brief recognize tokens for UBF evaluator
0003  *
0004  * @file expr.l
0005  */
0006 /* -----------------------------------------------------------------------------
0007  * Enduro/X Middleware Platform for Distributed Transaction Processing
0008  * Copyright (C) 2009-2016, ATR Baltic, Ltd. All Rights Reserved.
0009  * Copyright (C) 2017-2023, Mavimax, Ltd. All Rights Reserved.
0010  * This software is released under one of the following licenses:
0011  * AGPL (with Java and Go exceptions) or Mavimax's license for commercial use.
0012  * See LICENSE file for full text.
0013  * -----------------------------------------------------------------------------
0014  * AGPL license:
0015  *
0016  * This program is free software; you can redistribute it and/or modify it under
0017  * the terms of the GNU Affero General Public License, version 3 as published
0018  * by the Free Software Foundation;
0019  *
0020  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0021  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0022  * PARTICULAR PURPOSE. See the GNU Affero General Public License, version 3
0023  * for more details.
0024  *
0025  * You should have received a copy of the GNU Affero General Public License along 
0026  * with this program; if not, write to the Free Software Foundation, Inc.,
0027  * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0028  *
0029  * -----------------------------------------------------------------------------
0030  * A commercial use license is available from Mavimax, Ltd
0031  * contact@mavimax.com
0032  * -----------------------------------------------------------------------------
0033  */
0034 
0035 %option noyywrap nodefault yylineno
0036 /* Context for reading field */
0037 %x FUNCNM
0038 
0039 %{
0040 #include "expr.h"
0041 #include "expr.tab.h"
0042 #include <ndebug.h>
0043 #include <stdlib.h>
0044 #include <string.h>
0045 #include <nstdutil.h>
0046 
0047  /* Handle locations */
0048  int yycolumn = 1;
0049  #define YY_USER_ACTION yylloc.first_column = yycolumn; yylloc.last_column = yycolumn+yyleng-1; \
0050                                                 yycolumn +=yyleng;
0051 %}
0052 
0053 /* float exponent */
0054 EXP     ([Ee][-+]?[0-9]+)
0055 FLD     ([_a-zA-Z][_a-zA-Z0-9]*)
0056 FUNC ([_a-zA-Z][_a-zA-Z0-9]*)\(
0057 
0058 /* Recursive field syntax FIELD[OCC].FIELD2.FIELD3[OCC], etc.. 
0059  * Needs a parsers to build field sequence
0060  */
0061 FLDREF    ([_a-zA-Z][_a-zA-Z0-9]*(\[[0-9\?]+\]){0,1}((\.[_a-zA-Z][_a-zA-Z0-9]*(\[[0-9\?]+\]){0,1})+)*)
0062 
0063 %%
0064  /* single character ops */
0065 "("                     { return OP; }
0066 ")"                     { return CP; }
0067 
0068  /* Logical OR */
0069 "||"                    { return OR; }
0070  /* Logical AND */
0071 "&&"                    { return AND; }
0072  /* Logical XOR */
0073 "^"                     { return XOR; }
0074   /* Equality Operations */
0075 "=="                    { yylval.fn = EQOP_EQUAL;               return EQOP; }
0076 "!="                    { yylval.fn = EQOP_NOT_EQUAL;   return EQOP; }
0077 "%%"                    { yylval.fn = EQOP_REGEX_EQUAL;         return EQOP_REG; }
0078 "!%"                    { yylval.fn = EQOP_REGEX_NOT_EQUAL; return EQOP_REG; }
0079  /* Rel ops */
0080 "<"                     { yylval.fn = RELOP_LESS;               return RELOP; }
0081 "<="                    { yylval.fn = RELOP_LESS_EQUAL; return RELOP; }
0082 ">"                     { yylval.fn = RELOP_GREATER;    return RELOP; }
0083 ">="                    { yylval.fn = RELOP_GREATER_EQUAL;      return RELOP; }
0084  /* Add ops */
0085 "+"                     { yylval.fn = ADDOP_PLUS;  return ADDOP; }
0086 "-"                     { yylval.fn = ADDOP_MINUS; return ADDOP; }
0087  /* Those bellow we are not going to work as ADDOP! */
0088 "~"                     { yylval.fn = UNARY_CMPL;  return UNARYOP; }
0089 "!"                     { yylval.fn = UNARY_INV;   return UNARYOP; }
0090  /* Mult ops */
0091 "*"                     { yylval.fn = MULOP_DOT;   return MULTOP; }
0092 "/"                     { yylval.fn = MULOP_DIV;   return MULTOP; }
0093 "\%"                    { yylval.fn = MULOP_MOD;   return MULTOP; }
0094 '[^']*'                 {
0095                             {
0096                                 int len = strlen(yytext);
0097                                 if (len>MAX_TEXT)
0098                                 {
0099                                     yyerror("String constant too long!"); 
0100                                     yyterminate();
0101                                 }
0102                                 else
0103                                 {
0104                                     /* stripping off leading ' */
0105                                     strncpy(yylval.strval, yytext+1, len-1);
0106                                     yylval.strval[len-2] = '\0';
0107                                 }
0108                                 return STRING;
0109                             }
0110                         }
0111  /* Numbers - float*/
0112 [0-9]+                  {
0113                             yylval.l = atol(yytext);
0114                             return ULONG;
0115                         }
0116 [0-9]+"."[0-9]*{EXP}? |
0117 "."?[0-9]+{EXP}?        {
0118                             /* TODO: fix sperator according to locale */
0119                             yylval.d = ndrx_atof(yytext); 
0120 
0121                             UBF_LOG(log_debug, "FLOAT: (%s): %lf %lf %lf %lf",
0122                                     yytext, yylval.d, atof(yytext), atof("1.3"), atof("1,3"));
0123                             return UFLOAT;
0124                         }
0125  /* Custom function */
0126 {FUNC}        {
0127                     {
0128                         int len = strlen(yytext);
0129                         
0130                         /* -1 for (, +1 for EOS */
0131                         if (len>MAX_FUNC_NAME)
0132                         {
0133                             yyerror("Function name too long (max: %d)!", (MAX_FUNC_NAME-1)); 
0134                             yyterminate();
0135                         }
0136                         else
0137                         {    
0138                             yylval.funccall = ndrx_fpmalloc(sizeof(ndrx_symbfunc_t), 0);
0139                             
0140                             if (NULL==yylval.funccall)
0141                             {
0142                                 yyerror("Failed to malloc funccall: %s", strerror(errno));
0143                                 yyterminate();
0144                             }
0145                             
0146                             yylval.funccall->arg1[0]=EXEOS;
0147                             
0148                             /* strip off () at the end of func */
0149                             
0150                             ndrx_strncpy_eos(yylval.funccall->funcname, yytext, len-1,
0151                                     sizeof(yylval.funccall->funcname));
0152                             
0153                             UBF_LOG(log_debug, "got function call [%s]", 
0154                                     yylval.funccall->funcname);
0155                             
0156                         }
0157                     }
0158                     BEGIN FUNCNM;
0159                 }
0160 
0161 <FUNCNM>\)      {
0162                     /* pure func. */
0163                     BEGIN INITIAL;
0164                     return FUNCREF;
0165                 }
0166 
0167 <FUNCNM>\'[^']*\'\) {
0168         
0169                     int len = strlen(yytext);
0170 
0171                     /* -3 chars + 1 EOS */
0172                     if (len-2>MAX_TEXT)
0173                     {
0174                         yyerror("Function arg1 too long (max: %d)!", MAX_TEXT-1); 
0175                         yyterminate();
0176                     }
0177                     else
0178                     {
0179                         UBF_LOG(log_debug, "Arg value raw [%s]", yytext);
0180                         ndrx_strncpy_eos(yylval.funccall->arg1, yytext+1, 
0181                             strlen(yytext)-3, sizeof(yylval.funccall->arg1));
0182                         BEGIN INITIAL;
0183                         return FUNCREF;
0184                     }
0185                 }
0186  /* Fix out bad occurrence */
0187 <FUNCNM>.|\n            {
0188                             ndrx_fpfree(yylval.funccall);
0189                             yyerror("Incomplete function call", yytext);
0190                             yyterminate();
0191                         }
0192 
0193  /* Field names */
0194 {FLDREF}                {
0195                             if (EXSUCCEED!=ndrx_ubf_rfldid_parse(yytext, &yylval.fld))
0196                             {
0197                                 yyerror("Failed to parse field id [%s]", yytext);
0198                                 yyterminate();
0199                             }
0200                             return FLDREF;
0201                         }
0202 [ \t]   /* ignore white space */ 
0203 
0204 "\n"                    {
0205                             return EOL;
0206                         }
0207 .                       {
0208                             yyerror("Unknown character [%c]", *yytext); 
0209                             yyterminate();
0210                         }
0211 %%
0212 
0213 /* yylex_destroy() is missing on older bison versions */
0214 #if !defined(YY_FLEX_MAJOR_VERSION) || YY_FLEX_MAJOR_VERSION < 2             \
0215 || (YY_FLEX_MAJOR_VERSION == 2                                               \
0216         && (!defined(YY_FLEX_MINOR_VERSION) || YY_FLEX_MINOR_VERSION < 5     \
0217                 || (YY_FLEX_MINOR_VERSION == 5                               \
0218                       && (!defined(YY_FLEX_SUBMINOR_VERSION)                 \
0219                               || YY_FLEX_SUBMINOR_VERSION < 9))))
0220 
0221 #define yylex_destroy() yy_delete_buffer(YY_CURRENT_BUFFER)
0222 
0223 #endif
0224 
0225 
0226 /* common function to free up parser */
0227 void _free_parser(void)
0228 {
0229     yylex_destroy();
0230 }
0231 
0232 /* vim: set ts=4 sw=4 et smartindent: */