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: */