Skip to content
Snippets Groups Projects
fieldExprScanner.cc 66 KiB
Newer Older

#line 1 "fieldExprScanner.rl"
/*--------------------------------*- C++ -*----------------------------------*\
  =========                 |
  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
   \\    /   O peration     |
    \\  /    A nd           | www.openfoam.com
     \\/     M anipulation  |
-------------------------------------------------------------------------------
    Copyright (C) 2019-2021 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
    This file is part of OpenFOAM.

    OpenFOAM 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 of the License, or
    (at your option) any later version.

    OpenFOAM 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 OpenFOAM.  If not, see <http://www.gnu.org/licenses/>.

Description
    Ragel lexer interface for lemon grammar for patch expressions

\*---------------------------------------------------------------------------*/

#include "fieldExprScanner.H"
#include "fieldExprDriver.H"
#include "fieldExprLemonParser.h"
#include "fieldExprParser.H"
#include "Enum.H"
#include "macros.H"

#pragma GCC diagnostic ignored "-Wimplicit-fallthrough"
#pragma GCC diagnostic ignored "-Wunused-const-variable"

// Debugging to stderr
#undef  DebugInfo
#define DebugInfo if (debug & 0x2) InfoErr


// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //

namespace Foam
{

//- Paste token prefix
#define TOKEN_OF(T)         TOK_##T

//- An {int, c_str} enum pairing
#define TOKEN_PAIR(Name,T)  { TOKEN_OF(T), Name }

//- An {int, c_str} enum pairing for field types
#define FIELD_PAIR(Fld,T)  { TOKEN_OF(T), Fld::typeName.c_str() }

#undef HAS_LOOKBEHIND_TOKENS

// Special handling of predefined method types. Eg, .x(), .y(), ...
static const Enum<int> fieldMethodEnums
({
    TOKEN_PAIR("x", CMPT_X),
    TOKEN_PAIR("y", CMPT_Y),
    TOKEN_PAIR("z", CMPT_Z),
    TOKEN_PAIR("xx", CMPT_XX),
    TOKEN_PAIR("xy", CMPT_XY),
    TOKEN_PAIR("xz", CMPT_XZ),
    TOKEN_PAIR("yx", CMPT_YX),
    TOKEN_PAIR("yy", CMPT_YY),
    TOKEN_PAIR("yz", CMPT_YZ),
    TOKEN_PAIR("zx", CMPT_ZX),
    TOKEN_PAIR("zy", CMPT_ZY),
    TOKEN_PAIR("zz", CMPT_ZZ),
    TOKEN_PAIR("ii", CMPT_II),
    TOKEN_PAIR("diag", DIAG),   /* tensors only */
    TOKEN_PAIR("T", TRANSPOSE), /* tensors only */
});


// Simple compile-time function name declarations.
// Useful for handling driver-specific dispatching, or functions that
// are not universally available.
static const Enum<int> funcTokenEnums
({
#ifdef TOK_FLOOR
    TOKEN_PAIR("floor", FLOOR),
    TOKEN_PAIR("ceil", CEIL),
    TOKEN_PAIR("round", ROUND),
#endif
#ifdef TOK_HYPOT
    TOKEN_PAIR("hypot", HYPOT),
#endif
});

} // End namespace Foam


// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //

namespace Foam
{

// Classifying token type based on an identifier name is indeed ugly.
//
// 1)
//   Handle special cases (eg, cellSet,...) first that have been tagged
//   as expected content with the stashed "look-behind" token.
//   Handle not-found errors here directly.
//
// 2)
//   Fallback to determining which field-type (volScalarField etc) the name
//   corresponds to.
//   Handle not-found errors by return -1.
//
static int driverTokenType
(
    const expressions::fieldExpr::parseDriver& driver_,
    const word& ident
)
{
    // Field variables
    #ifdef TOK_SCALAR_ID
    {
        #undef checkFieldToken
        #define checkFieldToken(TokType, Type)                                \
        if (driver_.isLocalVariable<Type>(ident, false))                      \
        {                                                                     \
            return TokType;                                                   \
        }

        checkFieldToken(TOK_SCALAR_ID, scalar);
        checkFieldToken(TOK_VECTOR_ID, vector);
        checkFieldToken(TOK_SYM_TENSOR_ID, symmTensor);
        checkFieldToken(TOK_SPH_TENSOR_ID, sphericalTensor);
        checkFieldToken(TOK_TENSOR_ID, tensor);
        // Not tested: checkFieldToken(TOK_BOOL_ID, bool);
    }
    #endif

    return -1;
}

} // End namespace Foam


/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */

// Ragel machine definition
// Ragel variables (p, pe, eof, cs, top, stack, ts, te, act) defined later...
//
// Can use 'variable p xxx;' etc to change these names

#define EMIT_TOKEN(T)                                                         \
    driver_.parsePosition() = (ts-buf);                                       \
    DebugInfo<< STRINGIFY(T) << " at " << driver_.parsePosition() << nl;      \
    parser_->parse(TOKEN_OF(T), nullptr);                                     \
    driver_.parsePosition() = (p-buf);



#line 167 "fieldExprScanner.cc"
static const int fieldExpr_start = 11;
static const int fieldExpr_first_final = 11;
static const int fieldExpr_error = 0;

static const int fieldExpr_en_main = 11;


#line 304 "fieldExprScanner.rl"



// * * * * * * * * * * * * * * * * Destructor  * * * * * * * * * * * * * * * //

Foam::expressions::fieldExpr::scanner::~scanner()
{
    if (parser_)
    {
        delete parser_;
    }
}


// * * * * * * * * * * * * * Private Member Functions  * * * * * * * * * * * //

bool Foam::expressions::fieldExpr::scanner::dispatch_method
(
    const parseDriver& driver_,
    scanToken& scanTok,
    word&& ident
) const
{
    if (ident[0] == '.')
    {
        ident.erase(0, 1);
    }

    DebugInfo
        << "Method:" << ident
        << " at " << driver_.parsePosition() << nl;

    const int methType = fieldMethodEnums.lookup(ident, -1);

    if (methType > 0)
    {
        // Dispatch '.' and "method" separately
        parser_->parse(TOK_DOT, nullptr);
        parser_->parse(methType, nullptr);

        return true;
    }

    driver_.reportFatal("Unknown method: " + ident);
    return false;
}


bool Foam::expressions::fieldExpr::scanner::dispatch_ident
(
    const parseDriver& driver_,
    scanToken& scanTok,
    word&& ident
) const
{
    int tokType = -1;

    const bool quoted =
    (
        (ident.front() == '"' || ident.front() == '\'')
     && (ident.front() == ident.back())
    );

    if (quoted)
    {
        ident.erase(ident.size()-1);
        ident.erase(0, 1);
    }
    else
    {
        // Check for function name
        tokType = funcTokenEnums.lookup(ident, -1);

        if (tokType > 0)
        {
            DebugInfo
                << "Emit:" << ident << " function:"
                << parser_->tokenName(tokType) << nl;

            parser_->parse(tokType, nullptr);
            return true;
        }

        #ifdef HAS_LOOKBEHIND_TOKENS
        // Specials such "cset" also reset the look-behind
        tokType = lookBehindTokenEnums.lookup(ident, -1);

        if (tokType > 0)
        {
            DebugInfo
                << "Emit:" << ident << " as look-behind:"
                << parser_->tokenName(tokType) << nl;

            driver_.resetStashedTokenId(tokType);
            parser_->parse(tokType, nullptr);
            return true;
        }
        #endif
    }


    // Can also peek at stashed "look-behind"
    // const int lookBehind = driver_.stashedTokenId();

    tokType = driverTokenType(driver_, ident);

    if (tokType > 0)
    {
        DebugInfo
            << "Emit:" << ident << " token:"
            << parser_->tokenName(tokType) << nl;

        scanTok.name = new Foam::word(std::move(ident));
        parser_->parse(tokType, &scanTok);

        return true;
    }


    // Not found? Attempt to strip off '.x' endings etc,
    // but not when quoted

    const auto dot = ident.rfind('.');
    const int methType =
    (
        quoted || dot == std::string::npos
      ? -1
      : fieldMethodEnums.lookup(ident.substr(dot+1), -1)
    );

    if
    (
        methType > 0
     && (tokType = driverTokenType(driver_, ident.substr(0, dot))) > 0
    )
    {
        DebugInfo
            << "Emit:" << ident.substr(0, dot).c_str() << " token:"
            << parser_->tokenName(tokType) << " with "
            << ident.substr(dot).c_str() << " token:"
            << parser_->tokenName(methType) << nl;

        // The field (before the ".")
        ident.erase(dot);

        scanTok.name = new Foam::word(std::move(ident));
        parser_->parse(tokType, &scanTok);

        // Dispatch '.' and "method" separately
        parser_->parse(TOK_DOT, nullptr);
        parser_->parse(methType, nullptr);

        return true;
    }

    driver_.reportFatal
    (
        "Object " + ident + " does not exist or wrong type"
    );

    return false;
}


// * * * * * * * * * * * * * * * Member Functions  * * * * * * * * * * * * * //

bool Foam::expressions::fieldExpr::scanner::process
(
    const std::string& str,
    size_t strBeg,
    size_t strLen,
    parseDriver& driver_
)
{
    // Save debug value
    const int oldDebug = debug;

    if (driver_.debugScanner()) { debug |= 0x2; }
    if (driver_.debugParser())  { debug |= 0x4; }

    if (debug & 0x6)
        InfoErr
            << "Begin parse {"
            << str.substr(strBeg, strLen).c_str() << '}' << nl;
    }

    if (!parser_)
    {
        parser_ = new parser();
    }

    driver_.content(str, strBeg, strLen);

    size_t strEnd = str.length();

    if (strBeg > str.length())
    {
        strBeg = str.length();
    }
    else if (strLen != std::string::npos)
    {
        strLen += strBeg;

        if (strLen < str.length())
        {
            strEnd = strLen;
        }
    }


    parser_->start(driver_);

    // Scan token type
    scanToken scanTok;

    // Token start/end (Ragel naming)
    const char* ts;
    const char* te;

    // Local buffer data.
    // - p, pe, eof are Ragel naming
    // - buf is our own naming

    const char* buf = &(str[strBeg]);
    const char* eof = &(str[strEnd]);
    const char* p = buf;
    const char* pe = eof;

    // Initialize FSM variables
    
#line 407 "fieldExprScanner.cc"
	{
	cs = fieldExpr_start;
	ts = 0;
	te = 0;
	act = 0;
	}

#line 534 "fieldExprScanner.rl"
   /* ^^^ FSM initialization here ^^^ */;

    
#line 419 "fieldExprScanner.cc"
	{
	if ( p == pe )
		goto _test_eof;
	switch ( cs )
	{
tr2:
#line 189 "fieldExprScanner.rl"
	{te = p+1;{
        driver_.parsePosition() = (ts-buf);
        dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr4:
#line 189 "fieldExprScanner.rl"
	{te = p+1;{
        driver_.parsePosition() = (ts-buf);
        dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr5:
#line 167 "fieldExprScanner.rl"
	{{p = ((te))-1;}{
        driver_.parsePosition() = (ts-buf);

        DebugInfo
            << "Number:" << std::string(ts, te-ts).c_str()
            << " at " << driver_.parsePosition() << nl;

        if (readScalar(std::string(ts, te-ts), scanTok.svalue))
        {
            parser_->parse(TOKEN_OF(NUMBER), &scanTok);
        }
        else
        {
            driver_.reportFatal
            (
                "Error parsing number: " + std::string(ts, te-ts)
            );
        }

        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr8:
#line 232 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(EQUAL); }}
	goto st11;
tr9:
#line 284 "fieldExprScanner.rl"
	{{p = ((te))-1;}{ EMIT_TOKEN(TENSOR); }}
	goto st11;
tr11:
#line 292 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(IDENTITY_TENSOR); }}
#line 235 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(LOR); }}
	goto st11;
tr16:
#line 217 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(PERCENT); }}
	goto st11;
tr19:
#line 218 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(LPAREN); }}
	goto st11;
tr20:
#line 219 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(RPAREN); }}
	goto st11;
tr21:
#line 220 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(TIMES); }}
	goto st11;
tr22:
#line 221 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(PLUS); }}
	goto st11;
tr23:
#line 223 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(COMMA); }}
	goto st11;
tr24:
#line 222 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(MINUS); }}
	goto st11;
tr26:
#line 225 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(DIVIDE); }}
	goto st11;
tr28:
#line 227 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(COLON); }}
	goto st11;
tr32:
#line 226 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(QUESTION); }}
	goto st11;
tr35:
#line 238 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(BIT_XOR); }}
	goto st11;
tr51:
#line 211 "fieldExprScanner.rl"
#line 216 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(NOT); }}
	goto st11;
tr53:
#line 233 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(NOT_EQUAL); }}
	goto st11;
tr54:
#line 236 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(BIT_AND); }}
	goto st11;
tr55:
#line 234 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(LAND); }}
	goto st11;
tr56:
#line 224 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(DOT); }}
	goto st11;
tr59:
#line 167 "fieldExprScanner.rl"
	{te = p;p--;{
        driver_.parsePosition() = (ts-buf);

        DebugInfo
            << "Number:" << std::string(ts, te-ts).c_str()
            << " at " << driver_.parsePosition() << nl;

        if (readScalar(std::string(ts, te-ts), scanTok.svalue))
        {
            parser_->parse(TOKEN_OF(NUMBER), &scanTok);
        }
        else
        {
            driver_.reportFatal
            (
                "Error parsing number: " + std::string(ts, te-ts)
            );
        }

        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr61:
#line 195 "fieldExprScanner.rl"
	{te = p;p--;{
        // Tokenized ".method" - dispatch '.' and "method" separately
        driver_.parsePosition() = (ts-buf);
        dispatch_method(driver_, scanTok, word(ts+1, te-ts-1, false));
        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr62:
#line 228 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(LESS); }}
	goto st11;
tr63:
#line 229 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(LESS_EQ); }}
	goto st11;
tr64:
#line 230 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(GREATER); }}
	goto st11;
tr65:
#line 231 "fieldExprScanner.rl"
	{te = p+1;{ EMIT_TOKEN(GREATER_EQ); }}
	goto st11;
tr66:
#line 189 "fieldExprScanner.rl"
	{te = p;p--;{
        driver_.parsePosition() = (ts-buf);
        dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
        driver_.parsePosition() = (p-buf);
    }}
	goto st11;
tr68:
#line 1 "NONE"
	{	switch( act ) {
	case 26:
	{{p = ((te))-1;} EMIT_TOKEN(PI); }
	break;
	case 27:
	{{p = ((te))-1;} EMIT_TOKEN(DEG_TO_RAD); }
	break;
	case 28:
	{{p = ((te))-1;} EMIT_TOKEN(RAD_TO_DEG); }
	break;
	case 29:
	{{p = ((te))-1;} EMIT_TOKEN(EXP); }
	break;
	case 31:
	{{p = ((te))-1;} EMIT_TOKEN(LOG10); }
	break;
	case 32:
	{{p = ((te))-1;} EMIT_TOKEN(POW); }
	break;
	case 34:
	{{p = ((te))-1;} EMIT_TOKEN(SQRT); }
	break;
	case 35:
	{{p = ((te))-1;} EMIT_TOKEN(CBRT); }
	break;
	case 39:
	{{p = ((te))-1;} EMIT_TOKEN(ASIN); }
	break;
	case 40:
	{{p = ((te))-1;} EMIT_TOKEN(ACOS); }
	break;
	case 42:
	{{p = ((te))-1;} EMIT_TOKEN(ATAN2); }
	break;
	case 43:
	{{p = ((te))-1;} EMIT_TOKEN(SINH); }
	break;
	case 44:
	{{p = ((te))-1;} EMIT_TOKEN(COSH); }
	break;
	case 45:
	{{p = ((te))-1;} EMIT_TOKEN(TANH); }
	break;
	case 47:
	{{p = ((te))-1;} EMIT_TOKEN(MAGSQR); }
	break;
	case 50:
	{{p = ((te))-1;} EMIT_TOKEN(POS0); }
	break;
	case 51:
	{{p = ((te))-1;} EMIT_TOKEN(NEG0); }
	break;
	case 52:
	{{p = ((te))-1;} EMIT_TOKEN(SIGN); }
	break;
	case 53:
	{{p = ((te))-1;} EMIT_TOKEN(MIN); }
	break;
	case 54:
	{{p = ((te))-1;} EMIT_TOKEN(MAX); }
	break;
	case 55:
	{{p = ((te))-1;} EMIT_TOKEN(AVERAGE); }
	break;
	case 56:
	{{p = ((te))-1;} EMIT_TOKEN(SUM); }
	break;
	case 57:
	{{p = ((te))-1;} EMIT_TOKEN(RAND); }
	break;
	case 58:
	{{p = ((te))-1;} EMIT_TOKEN(BOOL); }
	break;
	case 59:
	{{p = ((te))-1;} EMIT_TOKEN(VECTOR); }
	break;
	case 61:
	{{p = ((te))-1;} EMIT_TOKEN(SYM_TENSOR); }
	break;
	case 62:
	{{p = ((te))-1;} EMIT_TOKEN(SPH_TENSOR); }
	break;
	case 63:
	{{p = ((te))-1;} EMIT_TOKEN(ZERO); }
	break;
	case 64:
	{{p = ((te))-1;} EMIT_TOKEN(LTRUE); }
	break;
	case 65:
	{{p = ((te))-1;} EMIT_TOKEN(LFALSE); }
	break;
	case 67:
	{{p = ((te))-1;} EMIT_TOKEN(ARG); }
	break;
	case 68:
	{{p = ((te))-1;}
        driver_.parsePosition() = (ts-buf);
        dispatch_ident(driver_, scanTok, word(ts, te-ts, false));
        driver_.parsePosition() = (p-buf);
    }
	break;
	}
	}
	goto st11;
#line 260 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(ATAN); }}
	goto st11;
#line 256 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(COS); }}
	goto st11;
#line 249 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(LOG); }}
	goto st11;
#line 265 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(MAG); }}
	goto st11;
#line 269 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(NEG); }}
	goto st11;
#line 268 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(POS); }}
	goto st11;
#line 255 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(SIN); }}
	goto st11;
#line 252 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(SQR); }}
	goto st11;
#line 257 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(TAN); }}
	goto st11;
#line 284 "fieldExprScanner.rl"
	{te = p;p--;{ EMIT_TOKEN(TENSOR); }}
	goto st11;
st11:
#line 1 "NONE"
	{ts = 0;}
	if ( ++p == pe )
		goto _test_eof11;
case 11:
#line 1 "NONE"
	{ts = p;}
#line 760 "fieldExprScanner.cc"
	switch( (*p) ) {
		case 32: goto st12;
		case 33: goto st13;
		case 34: goto st1;
		case 37: goto tr16;
		case 38: goto st14;
		case 39: goto st3;
		case 40: goto tr19;
		case 41: goto tr20;
		case 42: goto tr21;
		case 43: goto tr22;
		case 44: goto tr23;
		case 45: goto tr24;
		case 46: goto st15;
		case 47: goto tr26;
		case 58: goto tr28;
		case 60: goto st20;
		case 61: goto st7;
		case 62: goto st21;
		case 63: goto tr32;
		case 90: goto st24;
		case 94: goto tr35;
		case 95: goto st22;
		case 97: goto st27;
		case 98: goto st41;
		case 99: goto st44;
		case 100: goto st49;
		case 101: goto st56;
		case 102: goto st58;
		case 108: goto st62;
		case 109: goto st66;
		case 110: goto st72;
		case 112: goto st75;
		case 114: goto st78;
		case 115: goto st86;
		case 116: goto st114;
		case 118: goto st124;
		case 124: goto st10;
	}
	if ( (*p) < 48 ) {
		if ( 9 <= (*p) && (*p) <= 13 )
			goto st12;
	} else if ( (*p) > 57 ) {
		if ( (*p) > 89 ) {
			if ( 103 <= (*p) && (*p) <= 122 )
				goto st22;
		} else if ( (*p) >= 65 )
			goto st22;
	} else
		goto tr27;
	goto st0;
st0:
cs = 0;
	goto _out;
st12:
	if ( ++p == pe )
		goto _test_eof12;
case 12:
	if ( (*p) == 32 )
		goto st12;
	if ( 9 <= (*p) && (*p) <= 13 )
		goto st12;
	goto tr51;
st13:
	if ( ++p == pe )
		goto _test_eof13;
case 13:
	if ( (*p) == 61 )
		goto tr53;
	goto tr52;
st1:
	if ( ++p == pe )
		goto _test_eof1;
case 1:
	if ( (*p) == 34 )
		goto st0;
	goto st2;
st2:
	if ( ++p == pe )
		goto _test_eof2;
case 2:
	if ( (*p) == 34 )
		goto tr2;
	goto st2;
st14:
	if ( ++p == pe )
		goto _test_eof14;
case 14:
	if ( (*p) == 38 )
		goto tr55;
	goto tr54;
st3:
	if ( ++p == pe )
		goto _test_eof3;
case 3:
	if ( (*p) == 39 )
		goto st0;
	goto st4;
st4:
	if ( ++p == pe )
		goto _test_eof4;
case 4:
	if ( (*p) == 39 )
		goto tr4;
	goto st4;
st15:
	if ( ++p == pe )
		goto _test_eof15;
case 15:
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr57;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto st18;
	} else
		goto st18;
	goto tr56;
tr57:
#line 1 "NONE"
	{te = p+1;}
	goto st16;
st16:
	if ( ++p == pe )
		goto _test_eof16;
case 16:
#line 887 "fieldExprScanner.cc"
	switch( (*p) ) {
		case 69: goto st5;
		case 101: goto st5;
	}
	if ( 48 <= (*p) && (*p) <= 57 )
		goto tr57;
	goto tr59;
st5:
	if ( ++p == pe )
		goto _test_eof5;
case 5:
	switch( (*p) ) {
		case 43: goto st6;
		case 45: goto st6;
	}
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st17;
	goto tr5;
st6:
	if ( ++p == pe )
		goto _test_eof6;
case 6:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st17;
	goto tr5;
st17:
	if ( ++p == pe )
		goto _test_eof17;
case 17:
	if ( 48 <= (*p) && (*p) <= 57 )
		goto st17;
	goto tr59;
st18:
	if ( ++p == pe )
		goto _test_eof18;
case 18:
	if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto st18;
	} else if ( (*p) >= 65 )
		goto st18;
	goto tr61;
tr27:
#line 1 "NONE"
	{te = p+1;}
	goto st19;
st19:
	if ( ++p == pe )
		goto _test_eof19;
case 19:
#line 938 "fieldExprScanner.cc"
	switch( (*p) ) {
		case 46: goto tr57;
		case 69: goto st5;
		case 101: goto st5;
	}
	if ( 48 <= (*p) && (*p) <= 57 )
		goto tr27;
	goto tr59;
st20:
	if ( ++p == pe )
		goto _test_eof20;
case 20:
	if ( (*p) == 61 )
		goto tr63;
	goto tr62;
st7:
	if ( ++p == pe )
		goto _test_eof7;
case 7:
	if ( (*p) == 61 )
		goto tr8;
	goto st0;
st21:
	if ( ++p == pe )
		goto _test_eof21;
case 21:
	if ( (*p) == 61 )
		goto tr65;
	goto tr64;
st22:
	if ( ++p == pe )
		goto _test_eof22;
case 22:
	switch( (*p) ) {
		case 46: goto tr67;
		case 95: goto tr67;
	}
	if ( (*p) < 65 ) {
		if ( 48 <= (*p) && (*p) <= 57 )
			goto tr67;
	} else if ( (*p) > 90 ) {
		if ( 97 <= (*p) && (*p) <= 122 )
			goto tr67;
	} else
		goto tr67;
	goto tr66;
tr67:
#line 1 "NONE"
	{te = p+1;}
#line 189 "fieldExprScanner.rl"
	goto st23;
tr71:
#line 1 "NONE"
	{te = p+1;}
#line 289 "fieldExprScanner.rl"
#line 1 "NONE"
	{te = p+1;}
#line 259 "fieldExprScanner.rl"