%top{
  #include <stdint.h>
}

%{
/*
 * Copyright (c) 2010 Mark Liversedge (liversedge@gmail.com)
 *
 * 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 2 of the License, 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, Inc., 51
 * Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */

#include "DataFilter.h"

// need to get rid of this and use a string...
#include <stdio.h>

#ifdef YY_FLEX_SUBMINOR_VERSION
# define YY_FLEX_VERSION               \
  (YY_FLEX_MAJOR_VERSION) * 1000000 \
+ (YY_FLEX_MINOR_VERSION) * 1000    \
+ (YY_FLEX_SUBMINOR_VERSION)
#else
# define YY_FLEX_VERSION               \
  (YY_FLEX_MAJOR_VERSION) * 1000000 \
+ (YY_FLEX_MINOR_VERSION) * 1000
#endif

// tokens
#include "DataFilter_yacc.h"/* generated by the scanner */

int DataFiltercolumn = 1;

#define YY_USER_ACTION DataFilterlloc.first_line = DataFilterlloc.last_line = DataFilterlineno; \
    DataFilterlloc.first_column = DataFiltercolumn; DataFilterlloc.last_column = DataFiltercolumn + DataFilterleng - 1; \
    DataFiltercolumn += DataFilterleng;

%}
%option noyywrap
%option nounput
%option noinput
%option 8bit
%option yylineno
%option prefix="DataFilter"
%option never-interactive
%%

"#"[^\r\n]*                                 ; /* ignore single-line comments */
"%%python"(.|[\n\r\t])*"%%"                 DataFilterlval.op = PYTHON; return PYTHON;
"="                                         DataFilterlval.op = EQ; return EQ;
"<>"                                        DataFilterlval.op = NEQ; return NEQ;
"<"                                         DataFilterlval.op = LT; return LT;
"<="                                        DataFilterlval.op = LTE; return LTE;
">"                                         DataFilterlval.op = GT; return GT;
">="                                        DataFilterlval.op = GTE; return GTE;
"?:"                                        DataFilterlval.op = ELVIS; return ELVIS;
"<-"                                        DataFilterlval.op = ASSIGN; return ASSIGN;

"if"                                        DataFilterlval.op = IF_; return IF_;
"else"                                      DataFilterlval.op = ELSE_; return ELSE_;

"while"                                     DataFilterlval.op = WHILE; return WHILE;

[Mm][Aa][Tt][Cc][Hh][Ee][Ss]                DataFilterlval.op = MATCHES; return MATCHES;
[Bb][Ee][Gg][Ii][Nn][Ss][Ww][Ii][Tt][Hh]    DataFilterlval.op = BEGINSWITH; return BEGINSWITH;
[Ee][Nn][Dd][Ss][Ww][Ii][Tt][Hh]            DataFilterlval.op = ENDSWITH; return ENDSWITH;
[Cc][Oo][Nn][Tt][Aa][Ii][Nn][Ss]            DataFilterlval.op = CONTAINS; return CONTAINS;

                                            /* functions identified by name in the lexer is probably
                                              going to limit us in the future */
[Bb][Ee][Ss][Tt]                            strcpy(DataFilterlval.function, "best"); return BEST;
[Tt][Ii][Zz]                                strcpy(DataFilterlval.function, "tiz"); return TIZ;
[Cc][Oo][Nn][Ff][Ii][Gg]                    strcpy(DataFilterlval.function, "config"); return CONFIG;
[Cc][Oo][Nn][Ss][Tt]                        strcpy(DataFilterlval.function, "const"); return CONST_;

"&&"                                        DataFilterlval.op = AND; return AND;
[Aa][nN][Dd]                                DataFilterlval.op = AND; return AND;
"||"                                        DataFilterlval.op = OR; return OR;
[Oo][Rr]                                    DataFilterlval.op = OR; return OR;

[0-9]+                                      return DF_INTEGER;
[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?           return DF_FLOAT;
\"([^\"]|\\\")*\"                           return DF_STRING;  /* contains non-quotes or escaped-quotes */
"TRIMP(100)_Points"                         return SYMBOL; /* special case */
"Left/Right_Balance"                        return SYMBOL; /* special case */
"Minimum_W'bal"                             return SYMBOL; /* special case */
"Max_W'_Expended"                           return SYMBOL; /* special case */
"Maximum_W'bal_Match"                       return SYMBOL; /* special case */
"W'bal_Matches_>_2KJ"                       return SYMBOL; /* special case */
"W'bal_TAU"                                 return SYMBOL; /* special case */
"W'_Work"                                   return SYMBOL; /* special case */
"W'_Watts"                                  return SYMBOL; /* special case */
"W1_W'bal_Low_Fatigue"                      return SYMBOL; /* special case */
"W2_W'bal_Moderate_Fatigue"                 return SYMBOL; /* special case */
"W3_W'bal_Heavy_Fatigue"                    return SYMBOL; /* special case */
"W4_W'bal_Severe_Fatigue"                   return SYMBOL; /* special case */
"W1_Above_CP_W'bal_Low_Fatigue"             return SYMBOL; /* special case */
"W2_Above_CP_W'bal_Moderate_Fatigue"        return SYMBOL; /* special case */
"W3_Above_CP_W'bal_Heavy_Fatigue"           return SYMBOL; /* special case */
"W4_Above_CP_W'bal_Severe_Fatigue"          return SYMBOL; /* special case */
"W1_W'bal_Work_Low_Fatigue"                 return SYMBOL; /* special case */
"W2_W'bal_Work_Moderate_Fatigue"            return SYMBOL; /* special case */
"W3_W'bal_Work_Heavy_Fatigue"               return SYMBOL; /* special case */
"W4_W'bal_Work_Severe_Fatigue"              return SYMBOL; /* special case */
[Ww]\'                                      return SYMBOL; /* special case */
[Dd]\'                                      return SYMBOL; /* special case */
[Ss][Dd]\'                                  return SYMBOL; /* special case */
[a-zA-Z0-9][a-zA-Z0-9_%™]+                  return SYMBOL; /* symbols can start with 0-9 */
[a-zA-Z_]                                   return SYMBOL; /* one character symbols */
"+"                                         DataFilterlval.op = ADD; return ADD;
"-"                                         DataFilterlval.op = SUBTRACT; return SUBTRACT;
"*"                                         DataFilterlval.op = MULTIPLY; return MULTIPLY;
"/"                                         DataFilterlval.op = DIVIDE; return DIVIDE;
"^"                                         DataFilterlval.op = POW; return POW;


[ \n\t\r]                                   ; /* we just ignore whitespace */

                                            /* any other character, typically :, { or } */
.                                           return DataFiltertext[0];
%%

// Older versions of flex (prior to 2.5.9) do not have the destroy function
// Or We're not using GNU flex then we also won't have a destroy function
#if !defined(FLEX_SCANNER) || (YY_FLEX_VERSION < 2005009)
int DataFilterlex_destroy(void) { return 0; }
#endif

void DataFilter_setString(QString p)
{
    BEGIN(0);
    DataFiltercolumn = 0;
    // internally work with UTF-8 encoding
    // this works for FLEX, since the multi-byte characters only appear WITHIN a "String",
    // but not as part of the grammar - this is important since a char in UTF-8 can have up to 4 bytes
    DataFilter_scan_string(p.toUtf8().data());
}

void DataFilter_clearString()
{
    DataFilterlex_destroy();
}

