From 20589430f496921664b7bda805403cdc22a139cc Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 3 Dec 2019 12:34:40 +0100 Subject: [PATCH] ENH: driver/parser/scanner for volume expressions --- src/finiteVolume/Make/files | 7 + .../expressions/base/fvExprDriver.C | 8 +- .../expressions/base/fvExprDriver.H | 2 +- .../expressions/base/fvExprDriverTemplates.C | 23 +- .../expressions/volume/createCode | 13 + .../expressions/volume/volumeExpr.C | 44 + .../expressions/volume/volumeExprDriver.C | 226 + .../expressions/volume/volumeExprDriver.H | 510 +++ .../volume/volumeExprDriverFields.C | 283 ++ .../expressions/volume/volumeExprDriverI.H | 137 + .../volume/volumeExprDriverTemplates.C | 331 ++ .../expressions/volume/volumeExprFwd.H | 84 + .../volume/volumeExprLemonParser.h | 119 + .../volume/volumeExprLemonParser.lyy-m4 | 826 ++++ .../volume/volumeExprLemonParserMacros.m4 | 139 + .../expressions/volume/volumeExprParser.H | 106 + .../expressions/volume/volumeExprScanner.H | 162 + .../expressions/volume/volumeExprScanner.cc | 3866 +++++++++++++++++ .../expressions/volume/volumeExprScanner.rl | 694 +++ 19 files changed, 7563 insertions(+), 17 deletions(-) create mode 100755 src/finiteVolume/expressions/volume/createCode create mode 100644 src/finiteVolume/expressions/volume/volumeExpr.C create mode 100644 src/finiteVolume/expressions/volume/volumeExprDriver.C create mode 100644 src/finiteVolume/expressions/volume/volumeExprDriver.H create mode 100644 src/finiteVolume/expressions/volume/volumeExprDriverFields.C create mode 100644 src/finiteVolume/expressions/volume/volumeExprDriverI.H create mode 100644 src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C create mode 100644 src/finiteVolume/expressions/volume/volumeExprFwd.H create mode 100644 src/finiteVolume/expressions/volume/volumeExprLemonParser.h create mode 100644 src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 create mode 100644 src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 create mode 100644 src/finiteVolume/expressions/volume/volumeExprParser.H create mode 100644 src/finiteVolume/expressions/volume/volumeExprScanner.H create mode 100644 src/finiteVolume/expressions/volume/volumeExprScanner.cc create mode 100644 src/finiteVolume/expressions/volume/volumeExprScanner.rl diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files index 5ef761d151..8476427b52 100644 --- a/src/finiteVolume/Make/files +++ b/src/finiteVolume/Make/files @@ -265,6 +265,13 @@ $(patchExpr)/patchExprDriverFields.C $(patchExpr)/patchExprLemonParser.lyy-m4 $(patchExpr)/patchExprScanner.cc +volumeExpr = $(expr)/volume +$(volumeExpr)/volumeExpr.C +$(volumeExpr)/volumeExprDriver.C +$(volumeExpr)/volumeExprDriverFields.C +$(volumeExpr)/volumeExprLemonParser.lyy-m4 +$(volumeExpr)/volumeExprScanner.cc + fvMatrices/fvMatrices.C fvMatrices/fvScalarMatrix/fvScalarMatrix.C diff --git a/src/finiteVolume/expressions/base/fvExprDriver.C b/src/finiteVolume/expressions/base/fvExprDriver.C index 2dbd08757b..1e6055dadd 100644 --- a/src/finiteVolume/expressions/base/fvExprDriver.C +++ b/src/finiteVolume/expressions/base/fvExprDriver.C @@ -96,7 +96,7 @@ Foam::expressions::fvExprDriver::fvExprDriver ( bool cacheReadFields, bool searchInMemory, - bool searchOnDisc, + bool searchFiles, const dictionary& dict ) : @@ -104,7 +104,7 @@ Foam::expressions::fvExprDriver::fvExprDriver ( cacheReadFields, searchInMemory, - searchOnDisc, + searchFiles, dict ), globalScopes_(), @@ -142,7 +142,7 @@ Foam::expressions::fvExprDriver::fvExprDriver ( dict.lookupOrDefault("cacheReadFields", false), dict.lookupOrDefault("searchInMemory", true), - dict.lookupOrDefault("searchOnDisc", false), + dict.lookupOrDefault("searchFiles", false), dict ) { @@ -603,7 +603,7 @@ Foam::word Foam::expressions::fvExprDriver::getFieldClassName } } - if (searchOnDisc()) + if (searchFiles()) { return getHeaderClassName(this->mesh(), name); } diff --git a/src/finiteVolume/expressions/base/fvExprDriver.H b/src/finiteVolume/expressions/base/fvExprDriver.H index 7a941440fc..4104d07964 100644 --- a/src/finiteVolume/expressions/base/fvExprDriver.H +++ b/src/finiteVolume/expressions/base/fvExprDriver.H @@ -382,7 +382,7 @@ public: ( bool cacheReadFields = false, bool searchInMemory = true, - bool searchOnDisc = false, + bool searchFiles = false, const dictionary& dict = dictionary::null ); diff --git a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C index 498c398bfc..70eda6a08d 100644 --- a/src/finiteVolume/expressions/base/fvExprDriverTemplates.C +++ b/src/finiteVolume/expressions/base/fvExprDriverTemplates.C @@ -140,8 +140,8 @@ bool Foam::expressions::fvExprDriver::foundField { Info<< "fvExprDriver::foundField. Name: " << name << " Type: " << Type::typeName - << " search memory:" << searchInMemory() - << " disc:" << searchOnDisc() << endl; + << " registry:" << searchInMemory() + << " disk:" << searchFiles() << endl; } // if (std::is_void::value) ... @@ -155,30 +155,29 @@ bool Foam::expressions::fvExprDriver::foundField { if (debug) { - Info<< "Found " << name << " in memory" << endl; + Info<< "Found registered: " << name << endl; } return true; } if (debug) { - Info<< "No " << name << " of type " << Type::typeName - << " found in memory"; + Info<< "Registered " << name; if (ioptr) { - Info<< " but of type " << ioptr->headerClassName(); + Info<< " type:" << ioptr->headerClassName(); } - Info<< endl; + Info<< ", not type:" << Type::typeName << nl; } } - if (searchOnDisc() && getTypeOfField(name) == Type::typeName) + if (searchFiles() && getTypeOfField(name) == Type::typeName) { if (debug) { - Info<< "Found " << name << " on disc" << endl; + Info<< "Found file: " << name << nl; } return true; } @@ -326,7 +325,7 @@ Foam::tmp Foam::expressions::fvExprDriver::getOrReadFieldImpl { if (debug) { - Info<< "Getting " << name << " from memory" << endl; + Info<< "Retrieve registered: " << name << nl; } const GeomField& origFld = obr.lookupObject(name); @@ -356,7 +355,7 @@ Foam::tmp Foam::expressions::fvExprDriver::getOrReadFieldImpl } } } - else if (searchOnDisc() && getTypeOfField(name) == GeomField::typeName) + else if (searchFiles() && getTypeOfField(name) == GeomField::typeName) { if (debug) { @@ -415,7 +414,7 @@ Foam::tmp Foam::expressions::fvExprDriver::getOrReadFieldImpl { FatalErrorInFunction << "Could not find field " << name - << " in memory or on disc" << endl + << " in registry or on file-system" << nl << exit(FatalError); } diff --git a/src/finiteVolume/expressions/volume/createCode b/src/finiteVolume/expressions/volume/createCode new file mode 100755 index 0000000000..30d5e5902c --- /dev/null +++ b/src/finiteVolume/expressions/volume/createCode @@ -0,0 +1,13 @@ +#!/bin/sh +cd ${0%/*} || exit 1 # Run from this directory +# Manually create ragel scanner and lemon parser header + +prefix=volumeExpr + +"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \ + -prefix="$prefix" \ + -scanner=Scanner.rl \ + -parser=LemonParser.lyy-m4 \ + "$@" + +#------------------------------------------------------------------------------ diff --git a/src/finiteVolume/expressions/volume/volumeExpr.C b/src/finiteVolume/expressions/volume/volumeExpr.C new file mode 100644 index 0000000000..8859f6deb5 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExpr.C @@ -0,0 +1,44 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +#include "volumeExprFwd.H" +#include "defineDebugSwitch.H" + +// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ +defineDebugSwitchWithName(volumeExpr, "volumeExpr", 0); +registerDebugSwitchWithName(volumeExpr, volumeExpr, "volumeExpr"); + +} // End namespace expressions +} // End namespace Foam + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriver.C b/src/finiteVolume/expressions/volume/volumeExprDriver.C new file mode 100644 index 0000000000..8cb2c5002e --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriver.C @@ -0,0 +1,226 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +#include "volumeExprDriver.H" +#include "volumeExprScanner.H" +#include "error.H" +#include "fvPatch.H" +#include "fvMesh.H" +#include "className.H" +#include "addToRunTimeSelectionTable.H" + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ +namespace volumeExpr +{ + +defineTypeNameAndDebug(parseDriver, 0); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + dictionary, + volume +); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + idName, + volume +); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + dictionary, + internalField +); + +addNamedToRunTimeSelectionTable +( + fvExprDriver, + parseDriver, + idName, + internalField +); + +} // End namespace volumeExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * // + +namespace Foam +{ + static label getPatchID(const fvMesh& mesh, const word& patchName) + { + const auto& bMesh = mesh.boundaryMesh(); + + const label patchId = bMesh.findPatchID(patchName); + + if (patchId < 0) + { + FatalErrorInFunction + << "No patch " << patchName << " found in " + << flatOutput(bMesh.names()) << nl + << exit(FatalError); + } + return patchId; + } + + + static inline const polyPatch& findPolyPatch + ( + const fvMesh& mesh, + const word& patchName + ) + { + return mesh.boundaryMesh()[getPatchID(mesh, patchName)]; + } + +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +Foam::expressions::volumeExpr::parseDriver::parseDriver +( + const fvMesh& mesh, + bool cacheReadFields +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(cacheReadFields), + mesh_(mesh), + resultType_(), + isLogical_(false), + fieldGeoType_(NO_DATA), + resultDimension_() +{} + + +Foam::expressions::volumeExpr::parseDriver::parseDriver +( + const fvMesh& mesh, + const dictionary& dict +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(dict), + mesh_(mesh), + resultType_(), + isLogical_(false), + fieldGeoType_(NO_DATA), + resultDimension_() +{} + + +Foam::expressions::volumeExpr::parseDriver::parseDriver +( + const fvMesh& mesh, + const parseDriver& driver +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(driver), + mesh_(mesh), + resultType_(), + isLogical_(false), + fieldGeoType_(NO_DATA), + resultDimension_() +{} + + +Foam::expressions::volumeExpr::parseDriver::parseDriver +( + const word& meshName, + const fvMesh& mesh +) +: + parseDriver(mesh) +{ + //?? Info<< "Warn that meshName is ignored?" << nl; +} + + +Foam::expressions::volumeExpr::parseDriver::parseDriver +( + const dictionary& dict, + const fvMesh& mesh +) +: + parsing::genericRagelLemonDriver(), + expressions::fvExprDriver(dict), + mesh_(mesh), + resultType_(), + isLogical_(false), + fieldGeoType_(NO_DATA), + resultDimension_() +{} + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +bool Foam::expressions::volumeExpr::parseDriver::readDict +( + const dictionary& dict +) +{ + expressions::fvExprDriver::readDict(dict); + dict.readIfPresent("dimensions", resultDimension_); + + return true; +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +unsigned Foam::expressions::volumeExpr::parseDriver::parse +( + const std::string& expr, + size_t pos, + size_t len +) +{ + scanner scan(this->debugScanner()); + + scan.process(expr, pos, len, *this); + + return 0; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriver.H b/src/finiteVolume/expressions/volume/volumeExprDriver.H new file mode 100644 index 0000000000..0ddb6a2104 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriver.H @@ -0,0 +1,510 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Class + Foam::expressions::volumeExpr::parseDriver + +Description + Driver for volume, surface, point field expressions + + Additional Properties + \table + Property | Description | Required | Default + dimensions | Dimensions for the expression result | no | + \endtable + + In addition to the standard mathematical functions, operations and + logical and relational operations, the volume expression support the + following driver-specific functions: + + Functions + \table + Function | Description | Number of arguments | + vol | The cell volumes | 0 | + pos | The cell centres | 0 | + pts | The cell points | 0 | + area | The face area magnitudes | 0 | + fpos | The face centres | 0 | + weightAverage| Volume or area weighted average | 1 | + weightSum | Volume or area weighted sum | 1 | + face | The face areaNormal vectors | 0 | + face | A surface-field face value | 1 | + point | A point-field point value | 1 | + cellToFace | Interpolate cell values onto faces | 1 | + cellToPoint | Interpolate cell values onto points | 1 | + pointToCell | Interpolate point values onto cells | 1 | + reconstruct | Reconstruct cell vector from surface scalar | 1 | + rand | Random field | 0/1 | + \endtable + + Selections + \table + Function| Description | Number of arguments | + cset | Logical vol field corresponding to cellSet | 1 | + fset | Logical surf field corresponding to faceSet | 1 | + pset | Logical point field corresponding to pointSet | 1 | + czone | Logical vol field corresponding to cellZone | 1 | + fzone | Logical surf field corresponding to faceZone | 1 | + pzone | Logical point field corresponding to pointZone| 1 | + \endtable + +SourceFiles + volumeExprDriver.C + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_volumeExprDriver_H +#define expressions_volumeExprDriver_H + +#include "volumeExprFwd.H" +#include "fvExprDriver.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "pointFields.H" +#include "genericRagelLemonDriver.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ +namespace expressions +{ +namespace volumeExpr +{ + +/*---------------------------------------------------------------------------*\ + Class parseDriver Declaration +\*---------------------------------------------------------------------------*/ + +class parseDriver +: + public parsing::genericRagelLemonDriver, + public expressions::fvExprDriver +{ +protected: + + // Protected Data + + //- The referenced mesh + const fvMesh& mesh_; + + //- The results (volume, surface, point) + autoPtr resultField_; + + //- The result type-name. + // Normally volScalarField, surfaceVectorField etc, + // but Scalar is modified for logical as volScalarField etc + word resultType_; + + //- A logical (bool-like) field (but actually a scalar) + bool isLogical_; + + //- A volume/surface/point field + enum FieldAssociation fieldGeoType_; + + //- The result dimensions + dimensionSet resultDimension_; + + + // Protected Member Functions + + //- Deep-copy the internalField as a result. + // Uses the isLogical() and isPointData() values to handle + // additional bookkeeping. + // For isLogical(), renames the resultType_ from '*Scalar*' + // to '*Logical*' (eg, volLogicalField) + template + void setInternalFieldResult(const Field& fld); + + //- Cell selections (as logical) + tmp field_cellSelection + ( + const word& name, + enum topoSetSource::sourceType setType + ) const; + + //- Face selections (as logical) + tmp field_faceSelection + ( + const word& name, + enum topoSetSource::sourceType setType + ) const; + + //- Point selections (as logical) + tmp field_pointSelection + ( + const word& name, + enum topoSetSource::sourceType setType + ) const; + + + // No copy copy construct + parseDriver(const parseDriver&) = delete; + + // No copy assignment + void operator=(const parseDriver&) = delete; + + +public: + + ClassName("volumeExpr::driver"); + + // Constructors + + //- Construct for specified mesh + explicit parseDriver + ( + const fvMesh& mesh, + bool cacheReadFields = false + ); + + //- Construct for specified mesh with given dictionary + parseDriver(const fvMesh& mesh, const dictionary& dict); + + //- Construct for specified mesh with copy of driver context + parseDriver(const fvMesh& mesh, const parseDriver& driver); + + //- Construct with meshName for the given mesh + parseDriver(const word& meshName, const fvMesh& mesh); + + //- Construct with patchName and region specified in dictionary + parseDriver(const dictionary& dict, const fvMesh& mesh); + + //- Clone + virtual autoPtr clone() const + { + return autoPtr + ( + new parseDriver(this->mesh_, *this) + ); + } + + + //- Destructor + virtual ~parseDriver() = default; + + + // Public Member Functions + + //- The mesh we are attached to + virtual const fvMesh& mesh() const + { + return mesh_; + } + + //- The underlying field size for the expression + virtual label size() const + { + return mesh_.nCells(); + } + + //- The underlying point field size for the expression + virtual label pointSize() const + { + return mesh_.nPoints(); + } + + //- Field size associated with different geometric field types + inline label size(const FieldAssociation geoType) const; + + + // Reading + + //- Read variables, tables etc. + // Adds support for "dimensions" + virtual bool readDict(const dictionary& dict); + + + // Evaluation + + //- Perform parsing on (sub) string + using genericRagelLemonDriver::content; + + //- Execute the parser + virtual unsigned parse + ( + const std::string& expr, + size_t pos = 0, + size_t len = std::string::npos + ); + + + // Field Information + + //- The result type-name. + // Normally volScalarField, surfaceVectorField etc, + // but Scalar is modified for logical as volScalarField etc + const word& resultType() const + { + return resultType_; + } + + //- The geometric field association + FieldAssociation fieldAssociation() const + { + return fieldGeoType_; + } + + //- A logical (bool-like) field. Actually stored as a scalar. + bool isLogical() const + { + return isLogical_; + } + + //- A volume field + bool isVolumeData() const + { + return fieldGeoType_ == FieldAssociation::VOLUME_DATA; + } + + //- A surface field + bool isSurfaceData() const + { + return fieldGeoType_ == FieldAssociation::SURFACE_DATA; + } + + //- A point field + bool isPointData() const + { + return fieldGeoType_ == FieldAssociation::POINT_DATA; + } + + //- Test if stored result pointer is the specified type + template + const GeoField* isResultType() const; + + //- Test if stored result pointer is the specified type + //- and matches the specified logical type + template + const GeoField* isResultType(bool logical, bool dieOnNull=false) const; + + + // Set Fields + + //- Set result (vol field) + template + void setResult + ( + GeometricField* ptr, + bool logical = false + ); + + //- Set result (surface field) + template + void setResult + ( + GeometricField* ptr, + bool logical = false + ); + + //- Set result (point field) + template + void setResult + ( + GeometricField* ptr, + bool logical = false + ); + + + // New Fields + + //- Return a new volume field with the mesh size + template + tmp> + newVolField(const Type& val = pTraits::zero) const; + + //- Return a new surface field with the mesh nInternalFaces size + template + tmp> + newSurfaceField(const Type& val = pTraits::zero) const; + + //- Return a new point field with the mesh nPoints size + template + tmp> + newPointField(const Type& val = pTraits::zero) const; + + + //- Retrieve field (vol field) + template + tmp> + getVolField(const word& fldName, bool getOldTime=false); + + //- Retrieve field (surface field) + template + tmp> + getSurfaceField(const word& fldName, bool getOldTime=false); + + //- Retrieve field (surface field) + template + tmp> + getPointField(const word& fldName, bool getOldTime=false); + + + // Field "shape" conversions + + //- Interpolate cell to face values + template + tmp> + cellToFace + ( + const GeometricField& field + ) const; + + //- Interpolate cell to point values + template + tmp> + cellToPoint + ( + const GeometricField& field + ) const; + + //- Interpolate point to cell values + template + tmp> + pointToCell + ( + const GeometricField& field + ) const; + + + // Custom Field Functions + + //- The volume-weighted average of a field + template + Type volAverage + ( + GeometricField& fld + ) const + { + return weightedAverage(fld.mesh().V(), fld.primitiveField()); + } + + //- The volume-weighted sum of a field + template + Type volSum + ( + GeometricField& fld + ) const + { + return weightedSum(fld.mesh().V(), fld.primitiveField()); + } + + //- The area-weighted average of a field + template + Type areaAverage + ( + GeometricField& fld + ) const + { + return weightedAverage + ( + fld.mesh().magSf().primitiveField(), + fld.primitiveField() + ); + } + + //- The area-weighted sum of a field + template + Type areaSum + ( + GeometricField& fld + ) const + { + return weightedSum + ( + fld.mesh().magSf().primitiveField(), + fld.primitiveField() + ); + } + + + //- The cell volumes - (swak = vol) + tmp field_cellVolume() const; + + //- The cell centres - (swak = pos) + tmp field_cellCentre() const; + + //- The face area magnitudes [magSf] - (swak = area) + tmp field_faceArea() const; + + //- The face centres - (swak = fpos) + tmp field_faceCentre() const; + + //- The face areas with their vector direction [Sf] - (swak = face) + tmp field_areaNormal() const; + + //- The mesh point locations - (swak = pts) + tmp field_pointField() const; + + + //- Cell selection (set) + inline tmp field_cellSet(const word& name) const; + + //- Cell selection (zone) + inline tmp field_cellZone(const word& name) const; + + //- Face selection (set) + inline tmp field_faceSet(const word& name) const; + + //- Face selection (zone) + inline tmp field_faceZone(const word& name) const; + + //- Point selection (set) + inline tmp field_pointSet(const word& name) const; + + //- Point selection (zone) + inline tmp field_pointZone(const word& name) const; + + //- A uniform random field + tmp field_rand(label seed=0, bool gaussian=false) const; + + //- A Gaussian random field + tmp field_randGaussian(label seed=0) const + { + return field_rand(seed, true); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace volumeExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "volumeExprDriverI.H" + +#ifdef NoRepository + #include "volumeExprDriverTemplates.C" +#endif + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverFields.C b/src/finiteVolume/expressions/volume/volumeExprDriverFields.C new file mode 100644 index 0000000000..efc3457e09 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverFields.C @@ -0,0 +1,283 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +#include "volumeExprDriver.H" +#include "fvPatch.H" +#include "error.H" + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_cellSelection +( + const word& name, + enum topoSetSource::sourceType setType +) const +{ + auto tresult = volScalarField::New + ( + "selected", + mesh(), + dimensionedScalar(Zero) + ); + + labelList selected; + switch (setType) + { + case topoSetSource::sourceType::CELLZONE_SOURCE: + case topoSetSource::sourceType::CELLSET_SOURCE: + { + selected = getTopoSetLabels(name, setType); + break; + } + + default: + { + FatalErrorInFunction + << "Unexpected sourceType: " << int(setType) << nl + << exit(FatalError); + break; + } + } + + auto& fld = tresult.ref().primitiveFieldRef(); + UIndirectList(fld, selected) = scalar(1); + + return tresult; +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_faceSelection +( + const word& name, + enum topoSetSource::sourceType setType +) const +{ + auto tresult = surfaceScalarField::New + ( + "selected", + mesh(), + dimensionedScalar(Zero) + ); + + labelList selected; + switch (setType) + { + case topoSetSource::sourceType::FACESET_SOURCE: + case topoSetSource::sourceType::FACEZONE_SOURCE: + { + selected = getTopoSetLabels(name, setType); + break; + } + + default: + { + FatalErrorInFunction + << "Unexpected sourceType: " << int(setType) << nl + << exit(FatalError); + break; + } + } + + const auto& bmesh = mesh().boundaryMesh(); + + auto& result = tresult.ref(); + auto& fld = result.primitiveFieldRef(); + auto& bfld = result.boundaryFieldRef(); + + label nErrors = 0; + + for (const label facei : selected) + { + if (facei < mesh().nInternalFaces()) + { + fld[facei] = scalar(1); + } + else + { + const label patchi = bmesh.whichPatch(facei); + + if (patchi < 0) + { + ++nErrors; + } + else + { + bfld[patchi][facei-bmesh[patchi].start()] = scalar(1); + } + } + } + + if (nErrors) + { + WarningInFunction + << "The faceSet/faceZone " << name << " contained " + << nErrors << " faces outside of the addressing range" << nl + << nl; + } + + + return tresult; +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_pointSelection +( + const word& name, + enum topoSetSource::sourceType setType +) const +{ + auto tresult = pointScalarField::New + ( + "selected", + pointMesh::New(mesh()), + dimensionedScalar(Zero) + ); + + labelList selected; + switch (setType) + { + case topoSetSource::sourceType::POINTSET_SOURCE: + case topoSetSource::sourceType::POINTZONE_SOURCE: + { + selected = getTopoSetLabels(name, setType); + break; + } + + default: + { + FatalErrorInFunction + << "Unexpected sourceType: " << int(setType) << nl + << exit(FatalError); + break; + } + } + + auto& fld = tresult.ref().primitiveFieldRef(); + UIndirectList(fld, selected) = scalar(1); + + return tresult; +} + + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_cellVolume() const +{ + return volScalarField::New + ( + "vol", + mesh(), + dimVol, + mesh().V() + ); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_cellCentre() const +{ + return tmp::New(mesh().C()); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_faceArea() const +{ + return surfaceScalarField::New + ( + "face", + mesh(), + dimless, + mesh().magSf() + ); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_faceCentre() const +{ + return surfaceVectorField::New + ( + "fpos", + mesh(), + dimless, + mesh().Cf() + ); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_areaNormal() const +{ + return surfaceVectorField::New + ( + "face", + mesh(), + dimless, + mesh().Sf() + ); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_pointField() const +{ + return pointVectorField::New + ( + "pts", + pointMesh::New(mesh()), + dimless, + mesh().points() + ); +} + + +Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_rand +( + label seed, + bool gaussian +) const +{ + auto tresult = volScalarField::New + ( + "rand", + mesh(), + dimless + ); + auto& fld = tresult.ref().primitiveFieldRef(); + + fill_random(fld, seed, gaussian); + + return tresult; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverI.H b/src/finiteVolume/expressions/volume/volumeExprDriverI.H new file mode 100644 index 0000000000..2863f0ba1e --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverI.H @@ -0,0 +1,137 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline Foam::label Foam::expressions::volumeExpr::parseDriver::size +( + const FieldAssociation geoType +) const +{ + switch (geoType) + { + case FieldAssociation::POINT_DATA : + return mesh_.nPoints(); + break; + case FieldAssociation::SURFACE_DATA : + return mesh_.nInternalFaces(); + break; + case FieldAssociation::VOLUME_DATA : + return mesh_.nCells(); + break; + default: + break; + } + return 0; +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::parseDriver::field_cellSet +( + const word& name +) const +{ + return field_cellSelection + ( + name, + topoSetSource::sourceType::CELLSET_SOURCE + ); +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_cellZone +( + const word& name +) const +{ + return field_cellSelection + ( + name, + topoSetSource::sourceType::CELLZONE_SOURCE + ); +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_faceSet +( + const word& name +) const +{ + return field_faceSelection + ( + name, + topoSetSource::sourceType::FACESET_SOURCE + ); +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_faceZone +( + const word& name +) const +{ + return field_faceSelection + ( + name, + topoSetSource::sourceType::FACEZONE_SOURCE + ); +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_pointSet +( + const word& name +) const +{ + return field_pointSelection + ( + name, + topoSetSource::sourceType::POINTSET_SOURCE + ); +} + + +inline Foam::tmp +Foam::expressions::volumeExpr::parseDriver::field_pointZone +( + const word& name +) const +{ + return field_pointSelection + ( + name, + topoSetSource::sourceType::POINTZONE_SOURCE + ); +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C b/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C new file mode 100644 index 0000000000..3ffdb5b0b1 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprDriverTemplates.C @@ -0,0 +1,331 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +#include "exprOps.H" +#include "FieldOps.H" +#include "surfaceInterpolate.H" +#include "volPointInterpolation.H" +#include "interpolatePointToCell.H" + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template +void Foam::expressions::volumeExpr::parseDriver::setInternalFieldResult +( + const Field& fld +) +{ + if (isLogical_) + { + // Eg, volScalarField -> volLogicalField + resultType_.replace("Scalar", "Logical"); + + Field bools(fld.size()); + FieldOps::assign(bools, fld, expressions::boolOp()); + + this->result().setResult(std::move(bools), this->isPointData()); + } + else + { + // Deep copy + this->result().setResult(fld, this->isPointData()); + } +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +template +void Foam::expressions::volumeExpr::parseDriver::setResult +( + GeometricField* ptr, + bool logical +) +{ + typedef GeometricField fieldType; + + resultField_.clear(); + + // Characteristics + resultType_ = pTraits::typeName; + isLogical_ = logical; + fieldGeoType_ = VOLUME_DATA; + + // Always strip out dimensions? + if (!resultDimension_.dimensionless()) + { + ptr->dimensions().reset(resultDimension_); + } + + setInternalFieldResult(ptr->primitiveField()); + + // Take ownership + resultField_.reset(ptr); +} + + +template +void Foam::expressions::volumeExpr::parseDriver::setResult +( + GeometricField* ptr, + bool logical +) +{ + typedef GeometricField fieldType; + + resultField_.clear(); + + // Characteristics + resultType_ = pTraits::typeName; + isLogical_ = logical; + fieldGeoType_ = SURFACE_DATA; + + // Always strip out dimensions? + if (!resultDimension_.dimensionless()) + { + ptr->dimensions().reset(resultDimension_); + } + + setInternalFieldResult(ptr->primitiveField()); + + // Take ownership + resultField_.reset(ptr); +} + + +template +void Foam::expressions::volumeExpr::parseDriver::setResult +( + GeometricField* ptr, + bool logical +) +{ + typedef GeometricField fieldType; + + resultField_.clear(); + + // Characteristics + resultType_ = pTraits::typeName; + isLogical_ = logical; + fieldGeoType_ = POINT_DATA; + + // Always strip out dimensions? + if (!resultDimension_.dimensionless()) + { + ptr->dimensions().reset(resultDimension_); + } + + setInternalFieldResult(ptr->primitiveField()); + + // Take ownership + resultField_.reset(ptr); +} + + +template +const GeomField* +Foam::expressions::volumeExpr::parseDriver::isResultType() const +{ + return dynamic_cast(resultField_.get()); +} + + +template +const GeomField* +Foam::expressions::volumeExpr::parseDriver::isResultType +( + bool logical, + bool dieOnNull +) const +{ + const regIOobject* ptr = resultField_.get(); + + if (dieOnNull && ptr != nullptr) + { + FatalErrorInFunction + << "No result available. Requested " + << pTraits::typeName << nl + << exit(FatalError); + } + + if (isLogical_ == logical) + { + return dynamic_cast(ptr); + } + + return nullptr; +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::getVolField +( + const word& fldName, + bool getOldTime +) +{ + typedef GeometricField fieldType; + + return this->getOrReadField + ( + fldName, + true, // mandatory + getOldTime + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::getSurfaceField +( + const word& fldName, + bool getOldTime +) +{ + typedef GeometricField fieldType; + + return this->getOrReadField + ( + fldName, + true, // mandatory + getOldTime + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::getPointField +( + const word& fldName, + bool getOldTime +) +{ + typedef GeometricField fieldType; + + return this->getOrReadPointField + ( + fldName, + true, // mandatory + getOldTime + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::newVolField +( + const Type& val +) const +{ + return GeometricField::New + ( + word("constant.") + word(pTraits::typeName), + mesh(), + dimensioned("", dimless, val) + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::newSurfaceField +( + const Type& val +) const +{ + return GeometricField::New + ( + word("constant.") + word(pTraits::typeName), + mesh(), + dimensioned("", dimless, val) + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::newPointField +( + const Type& val +) const +{ + return GeometricField::New + ( + word("constant.") + word(pTraits::typeName), + pointMesh::New(mesh()), + dimensioned("", dimless, val) + ); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::cellToFace +( + const GeometricField& field +) const +{ + return fvc::interpolate(field); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::cellToPoint +( + const GeometricField& field +) const +{ + volPointInterpolation interp(this->mesh()); + return interp.interpolate(field); +} + + +template +Foam::tmp> +Foam::expressions::volumeExpr::parseDriver::pointToCell +( + const GeometricField& field +) const +{ + auto tresult = newVolField(); + auto& result = tresult.ref(); + + forAll(result,celli) + { + result[celli] = interpolatePointToCell(field, celli); + } + + return tresult; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprFwd.H b/src/finiteVolume/expressions/volume/volumeExprFwd.H new file mode 100644 index 0000000000..1a5df406c4 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprFwd.H @@ -0,0 +1,84 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Namespace + Foam::expressions::volumeExpr + +Description + Namespace for volume field expressions parsing and evaluation + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_volumeExprFwd_H +#define expressions_volumeExprFwd_H + +namespace Foam +{ +namespace expressions +{ +namespace volumeExpr +{ +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +// Forward Declarations +class parser; +class scanner; +class parseDriver; +union scanToken; + +//- Static debugging option +extern int debug; + +//- The field association for volume expressions (mutually exclusive) +enum FieldAssociation : unsigned char +{ + NO_DATA = 0, //!< No data + POINT_DATA = 1, //!< Point data + SURFACE_DATA = 2, //!< Surface data + VOLUME_DATA = 3 //!< Volume data +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace volumeExpr + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +//- Typedef for volumeExpr parseDriver +typedef volumeExpr::parseDriver volumeExprDriver; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParser.h b/src/finiteVolume/expressions/volume/volumeExprLemonParser.h new file mode 100644 index 0000000000..2cca6cd808 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParser.h @@ -0,0 +1,119 @@ +#define TOK_QUESTION 1 +#define TOK_COLON 2 +#define TOK_LOR 3 +#define TOK_LAND 4 +#define TOK_BIT_XOR 5 +#define TOK_BIT_AND 6 +#define TOK_EQUAL 7 +#define TOK_NOT_EQUAL 8 +#define TOK_LESS_EQ 9 +#define TOK_GREATER_EQ 10 +#define TOK_LESS 11 +#define TOK_GREATER 12 +#define TOK_PLUS 13 +#define TOK_MINUS 14 +#define TOK_TIMES 15 +#define TOK_DIVIDE 16 +#define TOK_PERCENT 17 +#define TOK_NEGATE 18 +#define TOK_NOT 19 +#define TOK_DOT 20 +#define TOK_NUMBER 21 +#define TOK_ZERO 22 +#define TOK_PI 23 +#define TOK_LPAREN 24 +#define TOK_RPAREN 25 +#define TOK_DEG_TO_RAD 26 +#define TOK_RAD_TO_DEG 27 +#define TOK_TIME 28 +#define TOK_SCALAR_ID 29 +#define TOK_MIN 30 +#define TOK_COMMA 31 +#define TOK_MAX 32 +#define TOK_SUM 33 +#define TOK_AVERAGE 34 +#define TOK_EXP 35 +#define TOK_LOG 36 +#define TOK_LOG10 37 +#define TOK_SQR 38 +#define TOK_SQRT 39 +#define TOK_CBRT 40 +#define TOK_SIN 41 +#define TOK_COS 42 +#define TOK_TAN 43 +#define TOK_ASIN 44 +#define TOK_ACOS 45 +#define TOK_ATAN 46 +#define TOK_SINH 47 +#define TOK_COSH 48 +#define TOK_TANH 49 +#define TOK_POW 50 +#define TOK_ATAN2 51 +#define TOK_POS 52 +#define TOK_NEG 53 +#define TOK_POS0 54 +#define TOK_NEG0 55 +#define TOK_SIGN 56 +#define TOK_FLOOR 57 +#define TOK_CEIL 58 +#define TOK_ROUND 59 +#define TOK_HYPOT 60 +#define TOK_RAND 61 +#define TOK_VECTOR_ID 62 +#define TOK_SPH_TENSOR_ID 63 +#define TOK_SYM_TENSOR_ID 64 +#define TOK_UNIT_TENSOR 65 +#define TOK_TENSOR_ID 66 +#define TOK_LTRUE 67 +#define TOK_LFALSE 68 +#define TOK_BOOL 69 +#define TOK_CSET 70 +#define TOK_IDENTIFIER 71 +#define TOK_CZONE 72 +#define TOK_CELL_VOLUME 73 +#define TOK_WEIGHT_AVERAGE 74 +#define TOK_WEIGHT_SUM 75 +#define TOK_FACE_EXPR 76 +#define TOK_SSCALAR_ID 77 +#define TOK_SVECTOR_ID 78 +#define TOK_SSPH_TENSOR_ID 79 +#define TOK_SSYM_TENSOR_ID 80 +#define TOK_STENSOR_ID 81 +#define TOK_FSET 82 +#define TOK_FZONE 83 +#define TOK_FACE_AREA 84 +#define TOK_FACE_CENTRE 85 +#define TOK_POINT_EXPR 86 +#define TOK_PSCALAR_ID 87 +#define TOK_PVECTOR_ID 88 +#define TOK_PSPH_TENSOR_ID 89 +#define TOK_PSYM_TENSOR_ID 90 +#define TOK_PTENSOR_ID 91 +#define TOK_PSET 92 +#define TOK_PZONE 93 +#define TOK_POINTS 94 +#define TOK_MAG 95 +#define TOK_MAGSQR 96 +#define TOK_VECTOR 97 +#define TOK_TENSOR 98 +#define TOK_SYM_TENSOR 99 +#define TOK_SPH_TENSOR 100 +#define TOK_CMPT_X 101 +#define TOK_CMPT_Y 102 +#define TOK_CMPT_Z 103 +#define TOK_CMPT_XX 104 +#define TOK_CMPT_XY 105 +#define TOK_CMPT_XZ 106 +#define TOK_CMPT_YX 107 +#define TOK_CMPT_YY 108 +#define TOK_CMPT_YZ 109 +#define TOK_CMPT_ZX 110 +#define TOK_CMPT_ZY 111 +#define TOK_CMPT_ZZ 112 +#define TOK_CMPT_II 113 +#define TOK_TRANSPOSE 114 +#define TOK_DIAG 115 +#define TOK_POINT_TO_CELL 116 +#define TOK_RECONSTRUCT 117 +#define TOK_CELL_TO_FACE 118 +#define TOK_CELL_TO_POINT 119 diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 new file mode 100644 index 0000000000..cc7ae238b5 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParser.lyy-m4 @@ -0,0 +1,826 @@ +%include +{ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Description + Lemon grammar for volume expressions. + + https://www.sqlite.org/src/doc/trunk/doc/lemon.html + + See detailed notes in the field expression parser. + +\*---------------------------------------------------------------------------*/ +} // %include + +/* + * include[volumeExprLemonParserMacros.m4] + *include(`volumeExprLemonParserMacros.m4')dnl + !done in a comment since many editors have issues matching m4 quotes! + */ +%include +{ +#include "volumeExprDriver.H" +#include "volumeExprParser.H" +#include "volumeExprScanner.H" +#include "unitConversion.H" +#include "error.H" +#include "volFields.H" +#include "surfaceFields.H" +#include "pointFields.H" +#include "exprDriverOps.H" +#include "GeometricFieldOps.H" +#include "fvcReconstruct.H" + + +// Enable ParseTrace +#undef NDEBUG + +compiler_pragmas() + +// Local Functions + +tmp_management() + +dnl +dnl #if 0 +dnl namespace Foam +dnl { +dnl //- Check field sizes +dnl template +dnl static bool checkSizes(const char* what, T1* arg1, T2* arg2) +dnl { +dnl if (arg1 == nullptr || arg2 == nullptr) +dnl { +dnl FatalError +dnl << "Null pointer in " << what << nl +dnl << Foam::exit(Foam::FatalError); +dnl } +dnl if (arg1->size() != arg2->size()) +dnl { +dnl FatalError +dnl << "Size mismatch in " << what << ' ' +dnl << pTraits::typeName << ", " +dnl << pTraits::typeName << "\n(" +dnl << arg1->size() << " != " << arg2->size() << ')' << nl +dnl << Foam::exit(Foam::FatalError); +dnl } +dnl +dnl return true; +dnl } +dnl } // End namespace Foam +dnl #endif +dnl +} // %include + +// ------------------------------------------------------------------------- // + +%namespace {} + +// Use extra argument for the return value +%extra_context { Foam::expressions::volumeExpr::parseDriver* driver } +%parse_failure { driver->reportFatal("Parse failure, giving up..."); } +%syntax_error { driver->reportFatal("Syntax error"); } + +%token_prefix TOK_ + +// Terminals +%token_type {Foam::expressions::volumeExpr::scanToken*} +// Non-terminals +%type ivalue { Foam::label } +%type svalue { Foam::scalar } +%type ident { Foam::word* } + +// Volume fields +declare_field(lfield, Foam::volScalarField, Foam::scalar, newVolField, getVolField) +declare_field(sfield, Foam::volScalarField, Foam::scalar, newVolField, getVolField) +declare_field(vfield, Foam::volVectorField, Foam::vector, newVolField, getVolField) +declare_field(hfield, Foam::volSphericalTensorField, Foam::sphericalTensor, newVolField, getVolField) +declare_field(yfield, Foam::volSymmTensorField, Foam::symmTensor, newVolField, getVolField) +declare_field(tfield, Foam::volTensorField, Foam::tensor, newVolField, getVolField) + +// Surface fields +declare_field(slfield, Foam::surfaceScalarField, Foam::scalar, newSurfaceField, getSurfaceField) +declare_field(ssfield, Foam::surfaceScalarField, Foam::scalar, newSurfaceField, getSurfaceField) +declare_field(svfield, Foam::surfaceVectorField, Foam::vector, newSurfaceField, getSurfaceField) +declare_field(shfield, Foam::surfaceSphericalTensorField, Foam::sphericalTensor, newSurfaceField, getSurfaceField) +declare_field(syfield, Foam::surfaceSymmTensorField, Foam::symmTensor, newSurfaceField, getSurfaceField) +declare_field(stfield, Foam::surfaceTensorField, Foam::tensor, newSurfaceField, getSurfaceField) + +// Point fields +declare_field(plfield, Foam::pointScalarField, Foam::scalar, newPointField, getPointField) +declare_field(psfield, Foam::pointScalarField, Foam::scalar, newPointField, getPointField) +declare_field(pvfield, Foam::pointVectorField, Foam::vector, newPointField, getPointField) +declare_field(phfield, Foam::pointSphericalTensorField, Foam::sphericalTensor, newPointField, getPointField) +declare_field(pyfield, Foam::pointSymmTensorField, Foam::symmTensor, newPointField, getPointField) +declare_field(ptfield, Foam::pointTensorField, Foam::tensor, newPointField, getPointField) + +// For each rule action with code, destruction must be done by that code block +// Lemon does not generate a destructor for that. +// So do not use Lemon destructors for anything. + +operator_precedence() + +%start_symbol evaluate + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + * Productions (scalar) +\*---------------------------------------------------------------------------*/ + +svalue (lhs) ::= NUMBER (a) . { lhs = (a)->svalue; } // From scanToken +svalue (lhs) ::= ZERO . { lhs = Foam::Zero; } +svalue (lhs) ::= PI LPAREN RPAREN . { lhs = Foam::constant::mathematical::pi; } +svalue (lhs) ::= DEG_TO_RAD LPAREN RPAREN . { lhs = Foam::degToRad(); } +svalue (lhs) ::= RAD_TO_DEG LPAREN RPAREN . { lhs = Foam::radToDeg(); } +svalue (lhs) ::= TIME LPAREN RPAREN . { lhs = driver->timeValue(); } + + +/* * * * * * * * * * * * * * * * Volume Fields * * * * * * * * * * * * * * * *\ +dnl +define([_logic_], [lfield])dnl +define([_scalar_], [sfield])dnl +define([_vector_], [vfield])dnl +define([_sphTensor_], [hfield])dnl +define([_symTensor_], [yfield])dnl +define([_tensor_], [tfield])dnl +dnl +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +/*---------------------------------------------------------------------------*\ + * Productions (volScalarField) +dnl +define([_target_], [sfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_field_from_value(_target_, svalue) +rule_get_field(_target_, SCALAR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_scalar_operations() +rules_scalar_functions() + +// Non-standard but manage via FieldOps::assign +rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp()) +rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp()) +rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp()) + +// Non-standard but manage via FieldOps::assign +rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp()) + + +// Other functions + +_target_ (lhs) ::= RAND LPAREN RPAREN . +{ + lhs = driver->field_rand().ptr(); +} + +_target_ (lhs) ::= RAND LPAREN NUMBER (seed) RPAREN . +{ + // Call with -ve seed to signal use of time index as seed + lhs = driver->field_rand(std::round(-(seed)->svalue)).ptr(); +} + + +/*---------------------------------------------------------------------------*\ + * Productions (volVectorField) +dnl +define([_target_], [vfield])dnl +define([_value_type_], [Foam::vector])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, VECTOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_vector_operations() +rules_vector_functions() + +/*---------------------------------------------------------------------------*\ + * Productions (volSphericalTensorField) +dnl +define([_target_], [hfield])dnl +define([_value_type_], [Foam::sphericalTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SPH_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_sphTensor_operations() +rules_sphTensor_functions() + +/*---------------------------------------------------------------------------*\ + * Productions (volSymmTensorField) +dnl +define([_target_], [yfield])dnl +define([_value_type_], [Foam::symmTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SYM_TENSOR_ID) +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_symTensor_operations() +rules_symTensor_functions() + +/*---------------------------------------------------------------------------*\ + * Productions (volTensorField) +dnl +define([_target_], [tfield])dnl +define([_value_type_], [Foam::tensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } +tfield (lhs) ::= UNIT_TENSOR . { lhs = _new_tfield(Foam::tensor::I); } + +rule_get_field(_target_, TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_tensor_operations() +rules_tensor_functions() + +/*---------------------------------------------------------------------------*\ + * Logic field productions (volScalarField) +dnl +define([_target_], [lfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ } + +_logic_ (lhs) ::= LTRUE . { lhs = _new_lfield(_logic_true_); } +_logic_ (lhs) ::= LFALSE . { lhs = _new_lfield(_logic_false_); } + +rule_cast_logical(_target_, _target_) +rule_cast_logical(_target_, _scalar_, Foam::scalar) + +rules_logical_operations(_logic_, _value_type_) + + +/*---------------------------------------------------------------------------*\ + * General Volume-related productions +\*---------------------------------------------------------------------------*/ + +rules_driver_volume_functions() + + +/* * * * * * * * * * * * * * * * Surface Fields * * * * * * * * * * * * * * *\ +dnl +define([_logic_], [slfield])dnl +define([_scalar_], [ssfield])dnl +define([_vector_], [svfield])dnl +define([_sphTensor_], [shfield])dnl +define([_symTensor_], [syfield])dnl +define([_tensor_], [stfield])dnl +dnl +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +dnl> %ifndef disable_surface_fields + +/*---------------------------------------------------------------------------*\ + * Productions (surfaceScalarField) +dnl +define([_target_], [ssfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_field_from_value(_target_, svalue, FACE_EXPR) +rule_get_field(_target_, SSCALAR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_scalar_operations() +rules_scalar_functions() + +// Non-standard but manage via FieldOps::assign +rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp()) +rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp()) +rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp()) + +// Non-standard but manage via FieldOps::assign +rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp()) + + +/*---------------------------------------------------------------------------*\ + * Productions (surfaceVectorField) +dnl +define([_target_], [svfield])dnl +define([_value_type_], [Foam::vector])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SVECTOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_vector_operations() +rules_vector_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (surfaceSphericalTensorField) +dnl +define([_target_], [shfield])dnl +define([_value_type_], [Foam::sphericalTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SSPH_TENSOR_ID) +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_sphTensor_operations() +rules_sphTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (surfaceSymmTensorField) +dnl +define([_target_], [syfield])dnl +define([_value_type_], [Foam::symmTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, SSYM_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_symTensor_operations() +rules_symTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (surfaceTensorField) +dnl +define([_target_], [stfield])dnl +define([_value_type_], [Foam::tensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, STENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_tensor_operations() +rules_tensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Logic field productions (surfaceScalarField) +dnl +define([_target_], [slfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ } + +_logic_ (lhs) ::= FACE_EXPR LPAREN LTRUE RPAREN . { lhs = _new_slfield(_logic_true_); } +_logic_ (lhs) ::= FACE_EXPR LPAREN LFALSE RPAREN . { lhs = _new_slfield(_logic_false_); } + +rule_cast_logical(_target_, _target_) +rule_cast_logical(_target_, _scalar_, Foam::scalar) + +rules_logical_operations(_logic_, _value_type_) + + +/*---------------------------------------------------------------------------*\ + * General Surface-related productions +\*---------------------------------------------------------------------------*/ + +rules_driver_surface_functions() + +dnl> %endif +// End disable_surface_fields + + +/* * * * * * * * * * * * * * * * Point Fields * * * * * * * * * * * * * * * *\ +dnl +define([_logic_], [plfield])dnl +define([_scalar_], [psfield])dnl +define([_vector_], [pvfield])dnl +define([_sphTensor_], [phfield])dnl +define([_symTensor_], [pyfield])dnl +define([_tensor_], [ptfield])dnl +dnl +dnl Several functions are incomplete for point fields +dnl +pushdef([incomplete_rule_unary_func], []) +pushdef([incomplete_rule_binary_func], []) +\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +dnl> %ifndef disable_point_fields + +/*---------------------------------------------------------------------------*\ + * Productions (pointScalarField) +dnl +define([_target_], [psfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_field_from_value(_target_, svalue, POINT_EXPR) +rule_get_field(_target_, PSCALAR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) + +// Non-standard but manage via FieldOps::assign +rule_unary_assign(_target_, _target_, FLOOR, Foam::floorOp()) +rule_unary_assign(_target_, _target_, CEIL, Foam::ceilOp()) +rule_unary_assign(_target_, _target_, ROUND, Foam::roundOp()) + +// Non-standard but manage via FieldOps::assign +rule_binary_assign(_target_, _target_, _target_, HYPOT, Foam::hypotOp()) + + +/*---------------------------------------------------------------------------*\ + * Some special handling for point fields. + * Some operators are incomplete, or ambiguous. + * Just calculate directly on the primitiveField, which is not as bad as it + * sounds since most of the pointPatchField operators are dummies (no-op) + * anyhow. +dnl +pushdef([rule_binary_op], +[$1 (lhs) ::= $2 (a) $4 $3 (b) . +{ + lhs = _new_$1(); + (*lhs).primitiveFieldRef() = + (make_obj(a).primitiveField() $5 make_obj(b).primitiveField()); +}] +)dnl> +dnl +pushdef([rule_unary_func], +[$1 (lhs) ::= $3 LPAREN $2 (a) RPAREN . +{ + lhs = _new_$1(); + (*lhs).primitiveFieldRef() = $4 (make_obj(a).primitiveField()); +}] +)dnl> +dnl +pushdef([rule_binary_func], +[$1 (lhs) ::= $4 LPAREN $2 (a) COMMA $3 (b) RPAREN . +{ + lhs = _new_$1(); + (*lhs).primitiveFieldRef() = + $5(make_obj(a).primitiveField(), make_obj(b).primitiveField()); +}] +)dnl> +dnl +\*---------------------------------------------------------------------------*/ + +rules_scalar_operations() +rules_scalar_functions() + +dnl/* Restore definitions +popdef([rule_binary_op])dnl +popdef([rule_unary_func])dnl +popdef([rule_binary_func])dnl +popdef([incomplete_rule_unary_func])dnl +popdef([incomplete_rule_binary_func])dnl +dnl*/ + + +/*---------------------------------------------------------------------------*\ + * Productions (pointVectorField) +dnl +define([_target_], [pvfield])dnl +define([_value_type_], [Foam::vector])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, PVECTOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_vector_operations() +rules_vector_functions() + +/*---------------------------------------------------------------------------*\ + * Productions (pointSphericalTensorField) +dnl +define([_target_], [phfield])dnl +define([_value_type_], [Foam::sphericalTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, PSPH_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_sphTensor_operations() +rules_sphTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (pointSymmTensorField) +dnl +define([_target_], [pyfield])dnl +define([_value_type_], [Foam::symmTensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, PSYM_TENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_symTensor_operations() +rules_symTensor_functions() + + +/*---------------------------------------------------------------------------*\ + * Productions (pointTensorField) +dnl +define([_target_], [ptfield])dnl +define([_value_type_], [Foam::tensor])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a); } + +rule_get_field(_target_, PTENSOR_ID) + +rules_standard(_target_, _value_type_, _logic_) +rules_inplace_gUnary(_target_) +rules_tensor_operations() +rules_tensor_functions() + +/*---------------------------------------------------------------------------*\ + * Logic field productions (pointScalarField) +dnl +define([_target_], [plfield])dnl +define([_value_type_], [Foam::scalar])dnl +dnl +\*---------------------------------------------------------------------------*/ + +evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Logical */ } + +_logic_ (lhs) ::= POINT_EXPR LPAREN LTRUE RPAREN . { lhs = _new_plfield(_logic_true_); } +_logic_ (lhs) ::= POINT_EXPR LPAREN LFALSE RPAREN . { lhs = _new_plfield(_logic_false_); } +rules_logical_operations(_logic_, _value_type_) + + +/*---------------------------------------------------------------------------*\ + * General Point-related productions +\*---------------------------------------------------------------------------*/ + +rules_driver_point_functions() + +dnl> %endif +// End disable_point_fields + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +/*---------------------------------------------------------------------------*\ + * Volume field composition +\*---------------------------------------------------------------------------*/ + +rule_mag_logical(sfield, lfield) +rules_mag_functions(sfield, sfield) +rules_mag_functions(sfield, vfield) +rules_mag_functions(sfield, tfield) +rules_mag_functions(sfield, yfield) +rules_mag_functions(sfield, hfield) + +rule_vector_zip(vfield, sfield, VECTOR) +rule_tensor_zip(tfield, sfield, TENSOR) +rule_symTensor_zip(yfield, sfield, SYM_TENSOR) +rule_sphTensor_zip(hfield, sfield, SPH_TENSOR) + +rule_vector_components(sfield, vfield) +rule_tensor_components(sfield, tfield) +rule_symTensor_components(sfield, yfield) +rule_sphTensor_components(sfield, hfield) + +rule_tensor_transpose(tfield) +rule_symTensor_transpose(yfield) +rule_sphTensor_transpose(hfield) + +rule_tensor_unzipDiag(vfield, yfield) +rule_tensor_unzipAll(vfield, tfield) + +rule_pointToCell(sfield, psfield) +rule_pointToCell(vfield, pvfield) +rule_pointToCell(tfield, ptfield) +rule_pointToCell(yfield, pyfield) +rule_pointToCell(hfield, phfield) + +vfield (lhs) ::= RECONSTRUCT LPAREN ssfield (a) RPAREN. +{ + lhs = Foam::fvc::reconstruct(make_obj(a)).ptr(); +} + + +/*---------------------------------------------------------------------------*\ + * Surface field composition +\*---------------------------------------------------------------------------*/ + +rule_mag_logical(ssfield, slfield) +rules_mag_functions(ssfield, ssfield) +rules_mag_functions(ssfield, svfield) +rules_mag_functions(ssfield, stfield) +rules_mag_functions(ssfield, syfield) +rules_mag_functions(ssfield, shfield) + +rule_vector_zip(svfield, ssfield, VECTOR) +rule_tensor_zip(stfield, ssfield, TENSOR) +rule_symTensor_zip(syfield, ssfield, SYM_TENSOR) +rule_sphTensor_zip(shfield, ssfield, SPH_TENSOR) + +rule_vector_components(ssfield, svfield) +rule_tensor_components(ssfield, stfield) +rule_symTensor_components(ssfield, syfield) +rule_sphTensor_components(ssfield, shfield) + +rule_tensor_transpose(stfield) +rule_symTensor_transpose(syfield) +rule_sphTensor_transpose(shfield) + +rule_tensor_unzipDiag(svfield, syfield) +rule_tensor_unzipAll(svfield, stfield) + +rule_cellToFace(ssfield, sfield) +rule_cellToFace(svfield, vfield) +rule_cellToFace(stfield, tfield) +rule_cellToFace(syfield, yfield) +rule_cellToFace(shfield, hfield) + + +/*---------------------------------------------------------------------------*\ + * Point field composition + * - Use primitiveField directly +dnl +pushdef([field_write_access], [($1).primitiveFieldRef()])dnl +pushdef([field_read_access], [($1).primitiveField()])dnl +dnl +\*---------------------------------------------------------------------------*/ + +rule_mag_logical(psfield, plfield) +rules_mag_functions(psfield, psfield) +rules_mag_functions(psfield, pvfield) +rules_mag_functions(psfield, ptfield) +rules_mag_functions(psfield, pyfield) +rules_mag_functions(psfield, phfield) + +rule_vector_zip(pvfield, psfield, VECTOR) +rule_tensor_zip(ptfield, psfield, TENSOR) +rule_symTensor_zip(pyfield, psfield, SYM_TENSOR) +rule_sphTensor_zip(phfield, psfield, SPH_TENSOR) + +rule_vector_components(psfield, pvfield) +rule_tensor_components(psfield, ptfield) +rule_symTensor_components(psfield, pyfield) +rule_sphTensor_components(psfield, phfield) + +rule_tensor_transpose(ptfield) +rule_symTensor_transpose(pyfield) +rule_sphTensor_transpose(phfield) + +rule_tensor_unzipDiag(pvfield, pyfield) +rule_tensor_unzipAll(pvfield, ptfield) + +rule_cellToPoint(psfield, sfield) +rule_cellToPoint(pvfield, vfield) +rule_cellToPoint(ptfield, tfield) +rule_cellToPoint(pyfield, yfield) +rule_cellToPoint(phfield, hfield) + + +dnl/* Restore definitions +popdef([field_write_access])dnl +popdef([field_read_access])dnl +dnl*/ + +// ************************************************************************* // + +dnl/* Standard m4 quoting +changequote([`],['])dnl +dnl*/ + +%code +{ + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +void Foam::expressions::volumeExpr::parser::stop() +{ + if (lemon_) + { + ParseFree(lemon_, ::operator delete); + #ifndef NDEBUG + ParseTrace(nullptr, nullptr); + #endif + lemon_ = nullptr; + } +} + + +void Foam::expressions::volumeExpr::parser::start(parseDriver& driver_) +{ + this->stop(); + lemon_ = ParseAlloc(::operator new, &driver_); + + if (debug || driver_.debugParser()) + { + #ifndef NDEBUG + ParseTrace(stderr, const_cast(prompt_)); + #endif + } +} + + +void Foam::expressions::volumeExpr::parser::parse +( + int tokenId, + scanToken* tokenVal +) +{ + Parse(lemon_, tokenId, tokenVal); +} + + +Foam::word Foam::expressions::volumeExpr::parser::nameOfToken +( + int tokenId +) const +{ + #ifndef NDEBUG + if + ( + tokenId > 0 + && unsigned(tokenId) < (sizeof(yyTokenName) / sizeof(char*)) + ) + { + return yyTokenName[tokenId]; + } + return ""; + #else + return word(); + #endif +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End of %code + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 b/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 new file mode 100644 index 0000000000..a0df5c6314 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprLemonParserMacros.m4 @@ -0,0 +1,139 @@ +divert(-1)dnl +#-----------------------------------*- m4 -*----------------------------------- +# ========= | +# \\ / F ield | OpenFOAM: The Open Source CFD Toolbox +# \\ / O peration | +# \\ / A nd | www.openfoam.com +# \\/ M anipulation | +#------------------------------------------------------------------------------ +# Copyright (C) 2019 OpenCFD Ltd. +#------------------------------------------------------------------------------ +# License +# This file is part of OpenFOAM, licensed under GNU General Public License +# . +# +# Description +# Driver-specific m4/lemon macros for volume expressions. +# +#------------------------------------------------------------------------------ + +include(`m4/lemon/base-setup.m4')dnl +include([m4/lemon/operator-precedence.m4])dnl +dnl +include([m4/lemon/rules-standard.m4])dnl +include([m4/lemon/rules-operations.m4])dnl +include([m4/lemon/rules-functions.m4])dnl +include([m4/lemon/rules-components.m4])dnl +include([m4/lemon/rules-fields-components.m4])dnl +include([m4/lemon/rules-scalar-logic.m4])dnl +dnl +divert(-1)dnl + +#------------------------------------------------------------------------------ +# Driver rules +#------------------------------------------------------------------------------ + +define([rules_driver_volume_functions], +[dnl +rule_driver_select(_logic_, CSET, field_cellSet)dnl +rule_driver_select(_logic_, CZONE, field_cellZone)dnl +dnl +rule_driver_nullary(_scalar_, CELL_VOLUME, field_cellVolume)dnl +rule_driver_nullary(_vector_, POS, field_cellCentre)dnl CELL_CENTRE +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, volAverage)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, volAverage)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, volAverage)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, volAverage)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, volAverage)dnl +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, volSum)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_SUM, volSum)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, volSum)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, volSum)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, volSum)dnl +dnl +]) + +define([rules_driver_surface_functions], +[dnl +rule_driver_select(_logic_, FSET, field_faceSet)dnl +rule_driver_select(_logic_, FZONE, field_faceZone)dnl +dnl +rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl +rule_driver_nullary(_vector_, FACE_CENTRE, field_faceCentre)dnl +rule_driver_nullary(_vector_, FACE_EXPR, field_areaNormal)dnl +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_AVERAGE, areaAverage)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_AVERAGE, areaAverage)dnl +dnl +rule_driver_inplace_unary(_scalar_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_vector_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_sphTensor_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_symTensor_, WEIGHT_SUM, areaSum)dnl +rule_driver_inplace_unary(_tensor_, WEIGHT_SUM, areaSum)dnl +dnl +]) + +define([rules_driver_point_functions], +[dnl +rule_driver_select(_logic_, PSET, field_pointSet)dnl +rule_driver_select(_logic_, PZONE, field_pointZone)dnl +dnl +rule_driver_nullary(_vector_, POINTS, field_pointField)dnl +dnl +dnl NB use non-driver versions for points - ie, unweighted +dnl +rule_inplace_unary(_scalar_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_vector_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_sphTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_symTensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +rule_inplace_unary(_tensor_, WEIGHT_AVERAGE, Foam::gAverage)dnl +dnl +rule_inplace_unary(_scalar_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_vector_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_sphTensor_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_symTensor_, WEIGHT_SUM, Foam::gSum)dnl +rule_inplace_unary(_tensor_, WEIGHT_SUM, Foam::gSum)dnl +dnl +]) + + +#------------------------------------------------------------------------------ +# rule_cellToFace(out, in) +# rule_cellToPoint(out, in) +# rule_pointToCell(out, in) +# +# Description +# Production rules for driver cellToFace, cellToPoint, pointToCell, +# methods +#------------------------------------------------------------------------------ + +define([rule_cellToFace], +[rule_driver_unary($1, $2, CELL_TO_FACE, cellToFace)]) + +define([rule_cellToPoint], +[rule_driver_unary($1, $2, CELL_TO_POINT, cellToPoint)]) + +define([rule_pointToCell], +[rule_driver_unary($1, $2, POINT_TO_CELL, pointToCell)]) + + +#------------------------------------------------------------------------------ +# Standard rules for fields: declaration, new/get, driver functions etc. + +include([m4/lemon/rules-fields.m4])dnl +divert(-1)dnl + + +#------------------------------------------------------------------------------ + +# Additional safety measures + +undefine([substr])dnl # Avoid collision with C/C++ naming + +#------------------------------------------------------------------------------ +divert(0)dnl diff --git a/src/finiteVolume/expressions/volume/volumeExprParser.H b/src/finiteVolume/expressions/volume/volumeExprParser.H new file mode 100644 index 0000000000..7664d10b4e --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprParser.H @@ -0,0 +1,106 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Class + Foam::expressions::volumeExpr::parser + +Description + Lemon parser interface for volume expressions grammar + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_volumeExprParser_H +#define expressions_volumeExprParser_H + +#include "volumeExprFwd.H" + +namespace Foam +{ +namespace expressions +{ +namespace volumeExpr +{ + +/*---------------------------------------------------------------------------*\ + Class parser Declaration +\*---------------------------------------------------------------------------*/ + +class parser +{ + // Private Data + + //- Prompt for parser tracing + static constexpr const char* const prompt_ = "volExpr:"; + + //- The lemon parser (demand-driven) + void* lemon_; + + +public: + + //- Local object debugging + int debug; + + + // Constructors + + //- Construct null + parser() : lemon_(nullptr), debug(volumeExpr::debug) {} + + + //- Destructor, deletes parser backend + ~parser() + { + stop(); + } + + + // Member Functions + + //- Start parsing, with the given driver context + void start(parseDriver& driver_); + + //- Stop parsing, freeing the allocated parser + void stop(); + + //- Push token/value to parser + void parse(int tokenId, scanToken* tokenVal); + + //- Return the text name corresponding to the tokenId + word nameOfToken(int tokenId) const; +}; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace volumeExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.H b/src/finiteVolume/expressions/volume/volumeExprScanner.H new file mode 100644 index 0000000000..b432a602fb --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.H @@ -0,0 +1,162 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Class + Foam::expressions::volumeExpr::scanner + +Description + Ragel lexer/scanner interface for volume expressions. + +Note + Ragel code generated with the ./createCode script. + +\*---------------------------------------------------------------------------*/ + +#ifndef expressions_volumeExprScanner_H +#define expressions_volumeExprScanner_H + +#include "volumeExprFwd.H" +#include "scalar.H" + +namespace Foam +{ +namespace expressions +{ +namespace volumeExpr +{ + +/*---------------------------------------------------------------------------*\ + Class scanToken Declaration +\*---------------------------------------------------------------------------*/ + +union scanToken +{ + Foam::label ivalue; + Foam::scalar svalue; + Foam::word* name; + + //- Null construct, bit-wise zero for union content + scanToken() : ivalue(0) {} +}; + + +/*---------------------------------------------------------------------------*\ + Class scanner Declaration +\*---------------------------------------------------------------------------*/ + +class scanner +{ + // Private Data + + //- Wrapped lemon parser + parser* parser_; + + // Ragel code state, action + int cs, act; + + + // Private Member Functions + + //- Dispatch .method to parser (if known) or Fatal + bool dispatch_method + ( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident + ) const; + + //- Dispatch identifier to parser (if possible) or Fatal + bool dispatch_ident + ( + const parseDriver& driver_, + scanToken& scanTok, + word&& ident + ) const; + + +public: + + //- Local debugging + int debug; + + + // Constructors + + //- Construct null, optionally setting debugging + explicit scanner(bool withDebug = false) + : + parser_(nullptr), + debug(volumeExpr::debug) + { + if (withDebug) + { + debug |= 4; + } + } + + + //- Destructor, deletes parser + ~scanner(); + + + // Member Functions + + //- Evaluate sub-string + bool process + ( + const std::string& str, size_t pos, size_t len, + parseDriver& driver_ + ); + + //- Evaluate sub-string + bool process + ( + const std::string& str, size_t pos, + parseDriver& driver_ + ) + { + return process(str, pos, std::string::npos, driver_); + } + + //- Evaluate string + bool process(const std::string& str, parseDriver& driver_) + { + return process(str, 0, std::string::npos, driver_); + } +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace volumeExpr +} // End namespace expressions +} // End namespace Foam + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.cc b/src/finiteVolume/expressions/volume/volumeExprScanner.cc new file mode 100644 index 0000000000..c83ed2be63 --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.cc @@ -0,0 +1,3866 @@ + +#line 1 "volumeExprScanner.rl" +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Description + Ragel lexer interface for lemon grammar of volume field expressions + +\*---------------------------------------------------------------------------*/ + +#include "volumeExprScanner.H" +#include "volumeExprDriver.H" +#include "volumeExprLemonParser.h" +#include "volumeExprParser.H" +#include "Enum.H" +#include "macros.H" + +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wold-style-cast" + +// Debugging to stderr +#undef DebugInfo +#define DebugInfo if (debug) 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 } + +// Special handling for these known (stashed) look-back types +static const Enum lookBehindTokenEnums +({ + TOKEN_PAIR("cellSet", CSET), + TOKEN_PAIR("faceSet", FSET), + TOKEN_PAIR("pointSet", PSET), + TOKEN_PAIR("cellZone", CZONE), + TOKEN_PAIR("faceZone", FZONE), + TOKEN_PAIR("pointZone", PZONE), +}); + +#define HAS_LOOKBEHIND_TOKENS + + +// Special handling of predefined method types. Eg, .x(), .y(), ... +static const Enum 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 */ +}); + + +// Known field-token types +static const Enum fieldTokenEnums +({ +#ifdef TOK_SCALAR_ID + TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID), + TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID), + TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID), + TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID), + TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID), +#else +#error TOK_SCALAR_ID not defined +#endif +#ifdef TOK_SSCALAR_ID + TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID), + TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID), + TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID), + TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID), + TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID), +#else +#warning TOK_SSCALAR_ID not defined +#endif +#ifdef TOK_PSCALAR_ID + TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID), + TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID), + TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID), + TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID), + TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID), +#else +#warning TOK_PSCALAR_ID not defined +#endif +}); + + +// Simple compile-time function name declarations. +// Useful for handling driver-specific dispatching, or functions that +// are not universally available. +static const Enum funcTokenEnums +({ +#ifdef TOK_FLOOR + TOKEN_PAIR("floor", FLOOR), + TOKEN_PAIR("ceil", CEIL), + TOKEN_PAIR("round", ROUND), +#endif +#ifdef TOK_HYPOT /* Can use hypot? */ + TOKEN_PAIR("hypot", HYPOT), +#endif + + // Already parsed as function: TOKEN_PAIR("pos", CELL_CENTRE), + + TOKEN_PAIR("point", POINT_EXPR), // Point value + TOKEN_PAIR("face", FACE_EXPR), // Face value, Face areaNormal + + TOKEN_PAIR("cellToPoint", CELL_TO_POINT), + TOKEN_PAIR("cellToFace", CELL_TO_FACE), + TOKEN_PAIR("pointToCell", POINT_TO_CELL), + + TOKEN_PAIR("area", FACE_AREA), + TOKEN_PAIR("vol", CELL_VOLUME), + + TOKEN_PAIR("fpos", FACE_CENTRE), + TOKEN_PAIR("pts", POINTS), +}); + +} // 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::volumeExpr::parseDriver& driver_, + const word& ident +) +{ + // Get stashed "look-behind" to decide what type of identifier we expect + const int lookBehind = driver_.resetStashedTokenId(); + + if (lookBehind && lookBehindTokenEnums.found(lookBehind)) + { + bool good = false; + + switch (lookBehind) + { + case TOK_CSET : good = driver_.isCellSet(ident); break; + case TOK_FSET : good = driver_.isFaceSet(ident); break; + case TOK_PSET : good = driver_.isPointSet(ident); break; + case TOK_CZONE : good = driver_.isCellZone(ident); break; + case TOK_FZONE : good = driver_.isFaceZone(ident); break; + case TOK_PZONE : good = driver_.isPointZone(ident); break; + } + + if (good) + { + return TOK_IDENTIFIER; + } + + // Fatal + driver_.reportFatal + ( + "Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident + ); + + return -2; // Extra safety + } + + // Surface variables - distinguish from volume by size + #ifdef TOK_SSCALAR_ID + { + const label len = driver_.mesh().nInternalFaces(); + + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, false, len)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SSCALAR_ID, scalar); + checkFieldToken(TOK_SVECTOR_ID, vector); + checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_STENSOR_ID, tensor); + } + #endif + + // Point variables + #ifdef TOK_PSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, true)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_PSCALAR_ID, scalar); + checkFieldToken(TOK_PVECTOR_ID, vector); + checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_PTENSOR_ID, tensor); + } + #endif + + // Volume variables + #ifdef TOK_SCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, false)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SCALAR_ID, scalar); + checkFieldToken(TOK_VECTOR_ID, vector); + checkFieldToken(TOK_SPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_SYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_TENSOR_ID, tensor); + } + #endif + + #undef checkFieldToken + + // Check registered fields and/or disk-files + { + const word fieldType(driver_.getFieldClassName(ident)); + + int tokType = fieldTokenEnums.get(fieldType, -1); + + if (tokType > 0) + { + return tokType; + } + } + + return -1; +} + +} // End anonymous namespace + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// 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) << ": " << driver_.parsePosition() << nl; \ + parser_->parse(TOKEN_OF(T), nullptr); \ + driver_.parsePosition() = (p-buf); + + + +#line 306 "volumeExprScanner.cc" +static const int volumeExpr_start = 11; +static const int volumeExpr_first_final = 11; +static const int volumeExpr_error = 0; + +static const int volumeExpr_en_main = 11; + + +#line 444 "volumeExprScanner.rl" + + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::volumeExpr::scanner::~scanner() +{ + if (parser_) + { + delete parser_; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::expressions::volumeExpr::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.get(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::volumeExpr::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.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " function:" + << parser_->nameOfToken(tokType) << nl; + + parser_->parse(tokType, nullptr); + return true; + } + + #ifdef HAS_LOOKBEHIND_TOKENS + // Specials such "cset" also reset the look-behind + tokType = lookBehindTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " as look-behind:" + << parser_->nameOfToken(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_->nameOfToken(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.get(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_->nameOfToken(tokType) << " with " + << ident.substr(dot).c_str() << " token:" + << parser_->nameOfToken(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::volumeExpr::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 |= 4; + } + + 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; + + // Ragel token start/end (required naming) + const char* ts; + const char* te; + + // Local buffer data. + // - p, pe, eof are required 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 541 "volumeExprScanner.cc" + { + cs = volumeExpr_start; + ts = 0; + te = 0; + act = 0; + } + +#line 669 "volumeExprScanner.rl" + /* ^^^ FSM initialization here ^^^ */; + + +#line 553 "volumeExprScanner.cc" + { + if ( p == pe ) + goto _test_eof; + switch ( cs ) + { +tr2: +#line 328 "volumeExprScanner.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 328 "volumeExprScanner.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 306 "volumeExprScanner.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 371 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(EQUAL); }} + goto st11; +tr9: +#line 425 "volumeExprScanner.rl" + {{p = ((te))-1;}{ EMIT_TOKEN(TENSOR); }} + goto st11; +tr11: +#line 433 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }} + goto st11; +tr12: +#line 374 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LOR); }} + goto st11; +tr16: +#line 356 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PERCENT); }} + goto st11; +tr19: +#line 357 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LPAREN); }} + goto st11; +tr20: +#line 358 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(RPAREN); }} + goto st11; +tr21: +#line 359 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(TIMES); }} + goto st11; +tr22: +#line 360 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(PLUS); }} + goto st11; +tr23: +#line 362 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COMMA); }} + goto st11; +tr24: +#line 361 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(MINUS); }} + goto st11; +tr26: +#line 364 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(DIVIDE); }} + goto st11; +tr28: +#line 366 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(COLON); }} + goto st11; +tr32: +#line 365 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(QUESTION); }} + goto st11; +tr35: +#line 377 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(BIT_XOR); }} + goto st11; +tr52: +#line 350 "volumeExprScanner.rl" + {te = p;p--;} + goto st11; +tr53: +#line 355 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NOT); }} + goto st11; +tr54: +#line 372 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(NOT_EQUAL); }} + goto st11; +tr55: +#line 375 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(BIT_AND); }} + goto st11; +tr56: +#line 373 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LAND); }} + goto st11; +tr57: +#line 363 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(DOT); }} + goto st11; +tr60: +#line 306 "volumeExprScanner.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; +tr62: +#line 334 "volumeExprScanner.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; +tr63: +#line 367 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LESS); }} + goto st11; +tr64: +#line 368 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(LESS_EQ); }} + goto st11; +tr65: +#line 369 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(GREATER); }} + goto st11; +tr66: +#line 370 "volumeExprScanner.rl" + {te = p+1;{ EMIT_TOKEN(GREATER_EQ); }} + goto st11; +tr67: +#line 328 "volumeExprScanner.rl" + {te = p;p--;{ + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + }} + goto st11; +tr69: +#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(WEIGHT_AVERAGE); } + break; + case 58: + {{p = ((te))-1;} EMIT_TOKEN(WEIGHT_SUM); } + break; + case 59: + {{p = ((te))-1;} EMIT_TOKEN(RAND); } + break; + case 60: + {{p = ((te))-1;} EMIT_TOKEN(BOOL); } + break; + case 61: + {{p = ((te))-1;} EMIT_TOKEN(VECTOR); } + break; + case 63: + {{p = ((te))-1;} EMIT_TOKEN(SYM_TENSOR); } + break; + case 64: + {{p = ((te))-1;} EMIT_TOKEN(SPH_TENSOR); } + break; + case 65: + {{p = ((te))-1;} EMIT_TOKEN(ZERO); } + break; + case 66: + {{p = ((te))-1;} EMIT_TOKEN(LTRUE); } + break; + case 67: + {{p = ((te))-1;} EMIT_TOKEN(LFALSE); } + break; + case 69: + {{p = ((te))-1;} EMIT_TOKEN(TIME); } + break; + case 70: + {{p = ((te))-1;} + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + } + break; + } + } + goto st11; +tr83: +#line 399 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(ATAN); }} + goto st11; +tr98: +#line 395 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(COS); }} + goto st11; +tr115: +#line 388 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(LOG); }} + goto st11; +tr122: +#line 404 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(MAG); }} + goto st11; +tr129: +#line 408 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(NEG); }} + goto st11; +tr135: +#line 407 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(POS); }} + goto st11; +tr154: +#line 394 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SIN); }} + goto st11; +tr170: +#line 391 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(SQR); }} + goto st11; +tr186: +#line 396 "volumeExprScanner.rl" + {te = p;p--;{ EMIT_TOKEN(TAN); }} + goto st11; +tr192: +#line 425 "volumeExprScanner.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 900 "volumeExprScanner.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 st40; + case 99: goto st43; + case 100: goto st48; + case 101: goto st55; + case 102: goto st57; + case 108: goto st61; + case 109: goto st65; + case 110: goto st71; + case 112: goto st74; + case 114: goto st77; + case 115: goto st85; + case 116: goto st113; + case 118: goto st125; + case 119: goto st130; + 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 tr52; +st13: + if ( ++p == pe ) + goto _test_eof13; +case 13: + if ( (*p) == 61 ) + goto tr54; + goto tr53; +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 tr56; + goto tr55; +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 tr58; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto st18; + } else + goto st18; + goto tr57; +tr58: +#line 1 "NONE" + {te = p+1;} + goto st16; +st16: + if ( ++p == pe ) + goto _test_eof16; +case 16: +#line 1028 "volumeExprScanner.cc" + switch( (*p) ) { + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr58; + goto tr60; +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 tr60; +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 tr62; +tr27: +#line 1 "NONE" + {te = p+1;} + goto st19; +st19: + if ( ++p == pe ) + goto _test_eof19; +case 19: +#line 1079 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr58; + case 69: goto st5; + case 101: goto st5; + } + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr27; + goto tr60; +st20: + if ( ++p == pe ) + goto _test_eof20; +case 20: + if ( (*p) == 61 ) + goto tr64; + goto tr63; +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 tr66; + goto tr65; +st22: + if ( ++p == pe ) + goto _test_eof22; +case 22: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr68: +#line 1 "NONE" + {te = p+1;} +#line 328 "volumeExprScanner.rl" + {act = 70;} + goto st23; +tr72: +#line 1 "NONE" + {te = p+1;} +#line 430 "volumeExprScanner.rl" + {act = 65;} + goto st23; +tr78: +#line 1 "NONE" + {te = p+1;} +#line 398 "volumeExprScanner.rl" + {act = 40;} + goto st23; +tr80: +#line 1 "NONE" + {te = p+1;} +#line 397 "volumeExprScanner.rl" + {act = 39;} + goto st23; +tr84: +#line 1 "NONE" + {te = p+1;} +#line 400 "volumeExprScanner.rl" + {act = 42;} + goto st23; +tr89: +#line 1 "NONE" + {te = p+1;} +#line 416 "volumeExprScanner.rl" + {act = 55;} + goto st23; +tr92: +#line 1 "NONE" + {te = p+1;} +#line 423 "volumeExprScanner.rl" + {act = 60;} + goto st23; +tr96: +#line 1 "NONE" + {te = p+1;} +#line 393 "volumeExprScanner.rl" + {act = 35;} + goto st23; +tr99: +#line 1 "NONE" + {te = p+1;} +#line 402 "volumeExprScanner.rl" + {act = 44;} + goto st23; +tr106: +#line 1 "NONE" + {te = p+1;} +#line 385 "volumeExprScanner.rl" + {act = 27;} + goto st23; +tr108: +#line 1 "NONE" + {te = p+1;} +#line 387 "volumeExprScanner.rl" + {act = 29;} + goto st23; +tr112: +#line 1 "NONE" + {te = p+1;} +#line 432 "volumeExprScanner.rl" + {act = 67;} + goto st23; +tr117: +#line 1 "NONE" + {te = p+1;} +#line 389 "volumeExprScanner.rl" + {act = 31;} + goto st23; +tr121: +#line 1 "NONE" + {te = p+1;} +#line 415 "volumeExprScanner.rl" + {act = 54;} + goto st23; +tr125: +#line 1 "NONE" + {te = p+1;} +#line 405 "volumeExprScanner.rl" + {act = 47;} + goto st23; +tr126: +#line 1 "NONE" + {te = p+1;} +#line 414 "volumeExprScanner.rl" + {act = 53;} + goto st23; +tr130: +#line 1 "NONE" + {te = p+1;} +#line 410 "volumeExprScanner.rl" + {act = 51;} + goto st23; +tr131: +#line 1 "NONE" + {te = p+1;} +#line 384 "volumeExprScanner.rl" + {act = 26;} + goto st23; +tr134: +#line 1 "NONE" + {te = p+1;} +#line 390 "volumeExprScanner.rl" + {act = 32;} + goto st23; +tr136: +#line 1 "NONE" + {te = p+1;} +#line 409 "volumeExprScanner.rl" + {act = 50;} + goto st23; +tr144: +#line 1 "NONE" + {te = p+1;} +#line 386 "volumeExprScanner.rl" + {act = 28;} + goto st23; +tr145: +#line 1 "NONE" + {te = p+1;} +#line 420 "volumeExprScanner.rl" + {act = 59;} + goto st23; +tr153: +#line 1 "NONE" + {te = p+1;} +#line 411 "volumeExprScanner.rl" + {act = 52;} + goto st23; +tr155: +#line 1 "NONE" + {te = p+1;} +#line 401 "volumeExprScanner.rl" + {act = 43;} + goto st23; +tr168: +#line 1 "NONE" + {te = p+1;} +#line 427 "volumeExprScanner.rl" + {act = 64;} + goto st23; +tr171: +#line 1 "NONE" + {te = p+1;} +#line 392 "volumeExprScanner.rl" + {act = 34;} + goto st23; +tr172: +#line 1 "NONE" + {te = p+1;} +#line 417 "volumeExprScanner.rl" + {act = 56;} + goto st23; +tr180: +#line 1 "NONE" + {te = p+1;} +#line 426 "volumeExprScanner.rl" + {act = 63;} + goto st23; +tr187: +#line 1 "NONE" + {te = p+1;} +#line 403 "volumeExprScanner.rl" + {act = 45;} + goto st23; +tr195: +#line 1 "NONE" + {te = p+1;} +#line 434 "volumeExprScanner.rl" + {act = 69;} + goto st23; +tr197: +#line 1 "NONE" + {te = p+1;} +#line 431 "volumeExprScanner.rl" + {act = 66;} + goto st23; +tr202: +#line 1 "NONE" + {te = p+1;} +#line 424 "volumeExprScanner.rl" + {act = 61;} + goto st23; +tr215: +#line 1 "NONE" + {te = p+1;} +#line 418 "volumeExprScanner.rl" + {act = 57;} + goto st23; +tr217: +#line 1 "NONE" + {te = p+1;} +#line 419 "volumeExprScanner.rl" + {act = 58;} + goto st23; +st23: + if ( ++p == pe ) + goto _test_eof23; +case 23: +#line 1334 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr69; +st24: + if ( ++p == pe ) + goto _test_eof24; +case 24: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st25; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st25: + if ( ++p == pe ) + goto _test_eof25; +case 25: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st26; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st26: + if ( ++p == pe ) + goto _test_eof26; +case 26: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto tr72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st27: + if ( ++p == pe ) + goto _test_eof27; +case 27: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st28; + case 115: goto st30; + case 116: goto st32; + case 118: goto st35; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st28: + if ( ++p == pe ) + goto _test_eof28; +case 28: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st29; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st29: + if ( ++p == pe ) + goto _test_eof29; +case 29: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto tr78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st30: + if ( ++p == pe ) + goto _test_eof30; +case 30: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st31; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st31: + if ( ++p == pe ) + goto _test_eof31; +case 31: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr80; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st32: + if ( ++p == pe ) + goto _test_eof32; +case 32: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st33; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st33: + if ( ++p == pe ) + goto _test_eof33; +case 33: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st34; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st34: + if ( ++p == pe ) + goto _test_eof34; +case 34: + switch( (*p) ) { + case 46: goto tr68; + case 50: goto tr84; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr83; +st35: + if ( ++p == pe ) + goto _test_eof35; +case 35: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st36; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st36: + if ( ++p == pe ) + goto _test_eof36; +case 36: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st37; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st37: + if ( ++p == pe ) + goto _test_eof37; +case 37: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st38; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st38: + if ( ++p == pe ) + goto _test_eof38; +case 38: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st39; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st39: + if ( ++p == pe ) + goto _test_eof39; +case 39: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr89; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st40: + if ( ++p == pe ) + goto _test_eof40; +case 40: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st41; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st41: + if ( ++p == pe ) + goto _test_eof41; +case 41: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st42; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st42: + if ( ++p == pe ) + goto _test_eof42; +case 42: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto tr92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st43: + if ( ++p == pe ) + goto _test_eof43; +case 43: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 98: goto st44; + case 111: goto st46; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st44: + if ( ++p == pe ) + goto _test_eof44; +case 44: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st45; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st45: + if ( ++p == pe ) + goto _test_eof45; +case 45: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st46: + if ( ++p == pe ) + goto _test_eof46; +case 46: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st47; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st47: + if ( ++p == pe ) + goto _test_eof47; +case 47: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr98; +st48: + if ( ++p == pe ) + goto _test_eof48; +case 48: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st49; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st49: + if ( ++p == pe ) + goto _test_eof49; +case 49: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st50; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st50: + if ( ++p == pe ) + goto _test_eof50; +case 50: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st51; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st51: + if ( ++p == pe ) + goto _test_eof51; +case 51: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st52; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st52: + if ( ++p == pe ) + goto _test_eof52; +case 52: + switch( (*p) ) { + case 46: goto tr68; + case 82: goto st53; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st53: + if ( ++p == pe ) + goto _test_eof53; +case 53: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st54; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st54: + if ( ++p == pe ) + goto _test_eof54; +case 54: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st55: + if ( ++p == pe ) + goto _test_eof55; +case 55: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 120: goto st56; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st56: + if ( ++p == pe ) + goto _test_eof56; +case 56: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 112: goto tr108; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st57: + if ( ++p == pe ) + goto _test_eof57; +case 57: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st58; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st58: + if ( ++p == pe ) + goto _test_eof58; +case 58: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st59; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st59: + if ( ++p == pe ) + goto _test_eof59; +case 59: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st60; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st60: + if ( ++p == pe ) + goto _test_eof60; +case 60: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st61: + if ( ++p == pe ) + goto _test_eof61; +case 61: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st62; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st62: + if ( ++p == pe ) + goto _test_eof62; +case 62: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st63; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st63: + if ( ++p == pe ) + goto _test_eof63; +case 63: + switch( (*p) ) { + case 46: goto tr68; + case 49: goto st64; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr115; +st64: + if ( ++p == pe ) + goto _test_eof64; +case 64: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr117; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st65: + if ( ++p == pe ) + goto _test_eof65; +case 65: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st66; + case 105: goto st70; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st66: + if ( ++p == pe ) + goto _test_eof66; +case 66: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st67; + case 120: goto tr121; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st67: + if ( ++p == pe ) + goto _test_eof67; +case 67: + switch( (*p) ) { + case 46: goto tr68; + case 83: goto st68; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr122; +st68: + if ( ++p == pe ) + goto _test_eof68; +case 68: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 113: goto st69; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st69: + if ( ++p == pe ) + goto _test_eof69; +case 69: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr125; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st70: + if ( ++p == pe ) + goto _test_eof70; +case 70: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st71: + if ( ++p == pe ) + goto _test_eof71; +case 71: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st72; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st72: + if ( ++p == pe ) + goto _test_eof72; +case 72: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st73; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st73: + if ( ++p == pe ) + goto _test_eof73; +case 73: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr130; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr129; +st74: + if ( ++p == pe ) + goto _test_eof74; +case 74: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto tr131; + case 111: goto st75; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st75: + if ( ++p == pe ) + goto _test_eof75; +case 75: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st76; + case 119: goto tr134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st76: + if ( ++p == pe ) + goto _test_eof76; +case 76: + switch( (*p) ) { + case 46: goto tr68; + case 48: goto tr136; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 49 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr135; +st77: + if ( ++p == pe ) + goto _test_eof77; +case 77: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st78; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st78: + if ( ++p == pe ) + goto _test_eof78; +case 78: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto st79; + case 110: goto st84; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st79: + if ( ++p == pe ) + goto _test_eof79; +case 79: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st80; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st80: + if ( ++p == pe ) + goto _test_eof80; +case 80: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st81; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st81: + if ( ++p == pe ) + goto _test_eof81; +case 81: + switch( (*p) ) { + case 46: goto tr68; + case 68: goto st82; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st82: + if ( ++p == pe ) + goto _test_eof82; +case 82: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st83; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st83: + if ( ++p == pe ) + goto _test_eof83; +case 83: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto tr144; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st84: + if ( ++p == pe ) + goto _test_eof84; +case 84: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 100: goto tr145; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st85: + if ( ++p == pe ) + goto _test_eof85; +case 85: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st86; + case 112: goto st89; + case 113: goto st102; + case 117: goto st104; + case 121: goto st105; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st86: + if ( ++p == pe ) + goto _test_eof86; +case 86: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st87; + case 110: goto st88; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st87: + if ( ++p == pe ) + goto _test_eof87; +case 87: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto tr153; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st88: + if ( ++p == pe ) + goto _test_eof88; +case 88: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr155; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr154; +st89: + if ( ++p == pe ) + goto _test_eof89; +case 89: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st90; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st90: + if ( ++p == pe ) + goto _test_eof90; +case 90: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st91; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st91: + if ( ++p == pe ) + goto _test_eof91; +case 91: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st92; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st92: + if ( ++p == pe ) + goto _test_eof92; +case 92: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st93; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st93: + if ( ++p == pe ) + goto _test_eof93; +case 93: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st94; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st94: + if ( ++p == pe ) + goto _test_eof94; +case 94: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st95; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st95: + if ( ++p == pe ) + goto _test_eof95; +case 95: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 108: goto st96; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st96: + if ( ++p == pe ) + goto _test_eof96; +case 96: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st97; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st97: + if ( ++p == pe ) + goto _test_eof97; +case 97: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st98; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st98: + if ( ++p == pe ) + goto _test_eof98; +case 98: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st99; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st99: + if ( ++p == pe ) + goto _test_eof99; +case 99: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st100; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st100: + if ( ++p == pe ) + goto _test_eof100; +case 100: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st101; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st101: + if ( ++p == pe ) + goto _test_eof101; +case 101: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr168; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st102: + if ( ++p == pe ) + goto _test_eof102; +case 102: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st103; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st103: + if ( ++p == pe ) + goto _test_eof103; +case 103: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto tr171; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr170; +st104: + if ( ++p == pe ) + goto _test_eof104; +case 104: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr172; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st105: + if ( ++p == pe ) + goto _test_eof105; +case 105: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st106; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st106: + if ( ++p == pe ) + goto _test_eof106; +case 106: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st107; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st107: + if ( ++p == pe ) + goto _test_eof107; +case 107: + switch( (*p) ) { + case 46: goto tr68; + case 84: goto st108; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st108: + if ( ++p == pe ) + goto _test_eof108; +case 108: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st109; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st109: + if ( ++p == pe ) + goto _test_eof109; +case 109: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st110; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st110: + if ( ++p == pe ) + goto _test_eof110; +case 110: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st111; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st111: + if ( ++p == pe ) + goto _test_eof111; +case 111: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st112; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st112: + if ( ++p == pe ) + goto _test_eof112; +case 112: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr180; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st113: + if ( ++p == pe ) + goto _test_eof113; +case 113: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st114; + case 101: goto st116; + case 105: goto st121; + case 114: goto st123; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st114: + if ( ++p == pe ) + goto _test_eof114; +case 114: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st115; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st115: + if ( ++p == pe ) + goto _test_eof115; +case 115: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto tr187; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr186; +st116: + if ( ++p == pe ) + goto _test_eof116; +case 116: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 110: goto st117; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st117: + if ( ++p == pe ) + goto _test_eof117; +case 117: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 115: goto st118; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st118: + if ( ++p == pe ) + goto _test_eof118; +case 118: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st119; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st119: + if ( ++p == pe ) + goto _test_eof119; +case 119: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr191; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +tr191: +#line 1 "NONE" + {te = p+1;} + goto st120; +st120: + if ( ++p == pe ) + goto _test_eof120; +case 120: +#line 3101 "volumeExprScanner.cc" + switch( (*p) ) { + case 46: goto tr68; + case 58: goto st8; + case 95: goto tr68; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr192; +st8: + if ( ++p == pe ) + goto _test_eof8; +case 8: + if ( (*p) == 58 ) + goto st9; + goto tr9; +st9: + if ( ++p == pe ) + goto _test_eof9; +case 9: + if ( (*p) == 73 ) + goto tr11; + goto tr9; +st121: + if ( ++p == pe ) + goto _test_eof121; +case 121: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto st122; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st122: + if ( ++p == pe ) + goto _test_eof122; +case 122: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr195; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st123: + if ( ++p == pe ) + goto _test_eof123; +case 123: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st124; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st124: + if ( ++p == pe ) + goto _test_eof124; +case 124: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr197; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st125: + if ( ++p == pe ) + goto _test_eof125; +case 125: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st126; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st126: + if ( ++p == pe ) + goto _test_eof126; +case 126: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 99: goto st127; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st127: + if ( ++p == pe ) + goto _test_eof127; +case 127: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st128; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st128: + if ( ++p == pe ) + goto _test_eof128; +case 128: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 111: goto st129; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st129: + if ( ++p == pe ) + goto _test_eof129; +case 129: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto tr202; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st130: + if ( ++p == pe ) + goto _test_eof130; +case 130: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st131; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st131: + if ( ++p == pe ) + goto _test_eof131; +case 131: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 105: goto st132; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st132: + if ( ++p == pe ) + goto _test_eof132; +case 132: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st133; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st133: + if ( ++p == pe ) + goto _test_eof133; +case 133: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 104: goto st134; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st134: + if ( ++p == pe ) + goto _test_eof134; +case 134: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 116: goto st135; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st135: + if ( ++p == pe ) + goto _test_eof135; +case 135: + switch( (*p) ) { + case 46: goto tr68; + case 65: goto st136; + case 83: goto st142; + case 95: goto tr68; + } + if ( (*p) < 66 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st136: + if ( ++p == pe ) + goto _test_eof136; +case 136: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 118: goto st137; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st137: + if ( ++p == pe ) + goto _test_eof137; +case 137: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto st138; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st138: + if ( ++p == pe ) + goto _test_eof138; +case 138: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 114: goto st139; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st139: + if ( ++p == pe ) + goto _test_eof139; +case 139: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 97: goto st140; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 98 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st140: + if ( ++p == pe ) + goto _test_eof140; +case 140: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 103: goto st141; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st141: + if ( ++p == pe ) + goto _test_eof141; +case 141: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 101: goto tr215; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st142: + if ( ++p == pe ) + goto _test_eof142; +case 142: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 117: goto st143; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st143: + if ( ++p == pe ) + goto _test_eof143; +case 143: + switch( (*p) ) { + case 46: goto tr68; + case 95: goto tr68; + case 109: goto tr217; + } + if ( (*p) < 65 ) { + if ( 48 <= (*p) && (*p) <= 57 ) + goto tr68; + } else if ( (*p) > 90 ) { + if ( 97 <= (*p) && (*p) <= 122 ) + goto tr68; + } else + goto tr68; + goto tr67; +st10: + if ( ++p == pe ) + goto _test_eof10; +case 10: + if ( (*p) == 124 ) + goto tr12; + goto st0; + } + _test_eof11: cs = 11; goto _test_eof; + _test_eof12: cs = 12; goto _test_eof; + _test_eof13: cs = 13; goto _test_eof; + _test_eof1: cs = 1; goto _test_eof; + _test_eof2: cs = 2; goto _test_eof; + _test_eof14: cs = 14; goto _test_eof; + _test_eof3: cs = 3; goto _test_eof; + _test_eof4: cs = 4; goto _test_eof; + _test_eof15: cs = 15; goto _test_eof; + _test_eof16: cs = 16; goto _test_eof; + _test_eof5: cs = 5; goto _test_eof; + _test_eof6: cs = 6; goto _test_eof; + _test_eof17: cs = 17; goto _test_eof; + _test_eof18: cs = 18; goto _test_eof; + _test_eof19: cs = 19; goto _test_eof; + _test_eof20: cs = 20; goto _test_eof; + _test_eof7: cs = 7; goto _test_eof; + _test_eof21: cs = 21; goto _test_eof; + _test_eof22: cs = 22; goto _test_eof; + _test_eof23: cs = 23; goto _test_eof; + _test_eof24: cs = 24; goto _test_eof; + _test_eof25: cs = 25; goto _test_eof; + _test_eof26: cs = 26; goto _test_eof; + _test_eof27: cs = 27; goto _test_eof; + _test_eof28: cs = 28; goto _test_eof; + _test_eof29: cs = 29; goto _test_eof; + _test_eof30: cs = 30; goto _test_eof; + _test_eof31: cs = 31; goto _test_eof; + _test_eof32: cs = 32; goto _test_eof; + _test_eof33: cs = 33; goto _test_eof; + _test_eof34: cs = 34; goto _test_eof; + _test_eof35: cs = 35; goto _test_eof; + _test_eof36: cs = 36; goto _test_eof; + _test_eof37: cs = 37; goto _test_eof; + _test_eof38: cs = 38; goto _test_eof; + _test_eof39: cs = 39; goto _test_eof; + _test_eof40: cs = 40; goto _test_eof; + _test_eof41: cs = 41; goto _test_eof; + _test_eof42: cs = 42; goto _test_eof; + _test_eof43: cs = 43; goto _test_eof; + _test_eof44: cs = 44; goto _test_eof; + _test_eof45: cs = 45; goto _test_eof; + _test_eof46: cs = 46; goto _test_eof; + _test_eof47: cs = 47; goto _test_eof; + _test_eof48: cs = 48; goto _test_eof; + _test_eof49: cs = 49; goto _test_eof; + _test_eof50: cs = 50; goto _test_eof; + _test_eof51: cs = 51; goto _test_eof; + _test_eof52: cs = 52; goto _test_eof; + _test_eof53: cs = 53; goto _test_eof; + _test_eof54: cs = 54; goto _test_eof; + _test_eof55: cs = 55; goto _test_eof; + _test_eof56: cs = 56; goto _test_eof; + _test_eof57: cs = 57; goto _test_eof; + _test_eof58: cs = 58; goto _test_eof; + _test_eof59: cs = 59; goto _test_eof; + _test_eof60: cs = 60; goto _test_eof; + _test_eof61: cs = 61; goto _test_eof; + _test_eof62: cs = 62; goto _test_eof; + _test_eof63: cs = 63; goto _test_eof; + _test_eof64: cs = 64; goto _test_eof; + _test_eof65: cs = 65; goto _test_eof; + _test_eof66: cs = 66; goto _test_eof; + _test_eof67: cs = 67; goto _test_eof; + _test_eof68: cs = 68; goto _test_eof; + _test_eof69: cs = 69; goto _test_eof; + _test_eof70: cs = 70; goto _test_eof; + _test_eof71: cs = 71; goto _test_eof; + _test_eof72: cs = 72; goto _test_eof; + _test_eof73: cs = 73; goto _test_eof; + _test_eof74: cs = 74; goto _test_eof; + _test_eof75: cs = 75; goto _test_eof; + _test_eof76: cs = 76; goto _test_eof; + _test_eof77: cs = 77; goto _test_eof; + _test_eof78: cs = 78; goto _test_eof; + _test_eof79: cs = 79; goto _test_eof; + _test_eof80: cs = 80; goto _test_eof; + _test_eof81: cs = 81; goto _test_eof; + _test_eof82: cs = 82; goto _test_eof; + _test_eof83: cs = 83; goto _test_eof; + _test_eof84: cs = 84; goto _test_eof; + _test_eof85: cs = 85; goto _test_eof; + _test_eof86: cs = 86; goto _test_eof; + _test_eof87: cs = 87; goto _test_eof; + _test_eof88: cs = 88; goto _test_eof; + _test_eof89: cs = 89; goto _test_eof; + _test_eof90: cs = 90; goto _test_eof; + _test_eof91: cs = 91; goto _test_eof; + _test_eof92: cs = 92; goto _test_eof; + _test_eof93: cs = 93; goto _test_eof; + _test_eof94: cs = 94; goto _test_eof; + _test_eof95: cs = 95; goto _test_eof; + _test_eof96: cs = 96; goto _test_eof; + _test_eof97: cs = 97; goto _test_eof; + _test_eof98: cs = 98; goto _test_eof; + _test_eof99: cs = 99; goto _test_eof; + _test_eof100: cs = 100; goto _test_eof; + _test_eof101: cs = 101; goto _test_eof; + _test_eof102: cs = 102; goto _test_eof; + _test_eof103: cs = 103; goto _test_eof; + _test_eof104: cs = 104; goto _test_eof; + _test_eof105: cs = 105; goto _test_eof; + _test_eof106: cs = 106; goto _test_eof; + _test_eof107: cs = 107; goto _test_eof; + _test_eof108: cs = 108; goto _test_eof; + _test_eof109: cs = 109; goto _test_eof; + _test_eof110: cs = 110; goto _test_eof; + _test_eof111: cs = 111; goto _test_eof; + _test_eof112: cs = 112; goto _test_eof; + _test_eof113: cs = 113; goto _test_eof; + _test_eof114: cs = 114; goto _test_eof; + _test_eof115: cs = 115; goto _test_eof; + _test_eof116: cs = 116; goto _test_eof; + _test_eof117: cs = 117; goto _test_eof; + _test_eof118: cs = 118; goto _test_eof; + _test_eof119: cs = 119; goto _test_eof; + _test_eof120: cs = 120; goto _test_eof; + _test_eof8: cs = 8; goto _test_eof; + _test_eof9: cs = 9; goto _test_eof; + _test_eof121: cs = 121; goto _test_eof; + _test_eof122: cs = 122; goto _test_eof; + _test_eof123: cs = 123; goto _test_eof; + _test_eof124: cs = 124; goto _test_eof; + _test_eof125: cs = 125; goto _test_eof; + _test_eof126: cs = 126; goto _test_eof; + _test_eof127: cs = 127; goto _test_eof; + _test_eof128: cs = 128; goto _test_eof; + _test_eof129: cs = 129; goto _test_eof; + _test_eof130: cs = 130; goto _test_eof; + _test_eof131: cs = 131; goto _test_eof; + _test_eof132: cs = 132; goto _test_eof; + _test_eof133: cs = 133; goto _test_eof; + _test_eof134: cs = 134; goto _test_eof; + _test_eof135: cs = 135; goto _test_eof; + _test_eof136: cs = 136; goto _test_eof; + _test_eof137: cs = 137; goto _test_eof; + _test_eof138: cs = 138; goto _test_eof; + _test_eof139: cs = 139; goto _test_eof; + _test_eof140: cs = 140; goto _test_eof; + _test_eof141: cs = 141; goto _test_eof; + _test_eof142: cs = 142; goto _test_eof; + _test_eof143: cs = 143; goto _test_eof; + _test_eof10: cs = 10; goto _test_eof; + + _test_eof: {} + if ( p == eof ) + { + switch ( cs ) { + case 12: goto tr52; + case 13: goto tr53; + case 14: goto tr55; + case 15: goto tr57; + case 16: goto tr60; + case 5: goto tr5; + case 6: goto tr5; + case 17: goto tr60; + case 18: goto tr62; + case 19: goto tr60; + case 20: goto tr63; + case 21: goto tr65; + case 22: goto tr67; + case 23: goto tr69; + case 24: goto tr67; + case 25: goto tr67; + case 26: goto tr67; + case 27: goto tr67; + case 28: goto tr67; + case 29: goto tr67; + case 30: goto tr67; + case 31: goto tr67; + case 32: goto tr67; + case 33: goto tr67; + case 34: goto tr83; + case 35: goto tr67; + case 36: goto tr67; + case 37: goto tr67; + case 38: goto tr67; + case 39: goto tr67; + case 40: goto tr67; + case 41: goto tr67; + case 42: goto tr67; + case 43: goto tr67; + case 44: goto tr67; + case 45: goto tr67; + case 46: goto tr67; + case 47: goto tr98; + case 48: goto tr67; + case 49: goto tr67; + case 50: goto tr67; + case 51: goto tr67; + case 52: goto tr67; + case 53: goto tr67; + case 54: goto tr67; + case 55: goto tr67; + case 56: goto tr67; + case 57: goto tr67; + case 58: goto tr67; + case 59: goto tr67; + case 60: goto tr67; + case 61: goto tr67; + case 62: goto tr67; + case 63: goto tr115; + case 64: goto tr67; + case 65: goto tr67; + case 66: goto tr67; + case 67: goto tr122; + case 68: goto tr67; + case 69: goto tr67; + case 70: goto tr67; + case 71: goto tr67; + case 72: goto tr67; + case 73: goto tr129; + case 74: goto tr67; + case 75: goto tr67; + case 76: goto tr135; + case 77: goto tr67; + case 78: goto tr67; + case 79: goto tr67; + case 80: goto tr67; + case 81: goto tr67; + case 82: goto tr67; + case 83: goto tr67; + case 84: goto tr67; + case 85: goto tr67; + case 86: goto tr67; + case 87: goto tr67; + case 88: goto tr154; + case 89: goto tr67; + case 90: goto tr67; + case 91: goto tr67; + case 92: goto tr67; + case 93: goto tr67; + case 94: goto tr67; + case 95: goto tr67; + case 96: goto tr67; + case 97: goto tr67; + case 98: goto tr67; + case 99: goto tr67; + case 100: goto tr67; + case 101: goto tr67; + case 102: goto tr67; + case 103: goto tr170; + case 104: goto tr67; + case 105: goto tr67; + case 106: goto tr67; + case 107: goto tr67; + case 108: goto tr67; + case 109: goto tr67; + case 110: goto tr67; + case 111: goto tr67; + case 112: goto tr67; + case 113: goto tr67; + case 114: goto tr67; + case 115: goto tr186; + case 116: goto tr67; + case 117: goto tr67; + case 118: goto tr67; + case 119: goto tr67; + case 120: goto tr192; + case 8: goto tr9; + case 9: goto tr9; + case 121: goto tr67; + case 122: goto tr67; + case 123: goto tr67; + case 124: goto tr67; + case 125: goto tr67; + case 126: goto tr67; + case 127: goto tr67; + case 128: goto tr67; + case 129: goto tr67; + case 130: goto tr67; + case 131: goto tr67; + case 132: goto tr67; + case 133: goto tr67; + case 134: goto tr67; + case 135: goto tr67; + case 136: goto tr67; + case 137: goto tr67; + case 138: goto tr67; + case 139: goto tr67; + case 140: goto tr67; + case 141: goto tr67; + case 142: goto tr67; + case 143: goto tr67; + } + } + + _out: {} + } + +#line 671 "volumeExprScanner.rl" + /* ^^^ FSM execution here ^^^ */; + + if (0 == cs) + { + driver_.reportFatal("Parse error while scanning", (p-buf)); + } + + if (p != eof) + { + driver_.reportFatal("Parsing failed with remaining content", (p-buf)); + } + + // Terminate parser execution + parser_->parse(0, nullptr); + parser_->stop(); + + // Restore debug value + debug = oldDebug; + + return true; +} + + +// ************************************************************************* // diff --git a/src/finiteVolume/expressions/volume/volumeExprScanner.rl b/src/finiteVolume/expressions/volume/volumeExprScanner.rl new file mode 100644 index 0000000000..0b198b10af --- /dev/null +++ b/src/finiteVolume/expressions/volume/volumeExprScanner.rl @@ -0,0 +1,694 @@ +/*--------------------------------*- C++ -*----------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Description + Ragel lexer interface for lemon grammar of volume field expressions + +\*---------------------------------------------------------------------------*/ + +#include "volumeExprScanner.H" +#include "volumeExprDriver.H" +#include "volumeExprLemonParser.h" +#include "volumeExprParser.H" +#include "Enum.H" +#include "macros.H" + +#pragma GCC diagnostic ignored "-Wimplicit-fallthrough" +#pragma GCC diagnostic ignored "-Wold-style-cast" + +// Debugging to stderr +#undef DebugInfo +#define DebugInfo if (debug) 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 } + +// Special handling for these known (stashed) look-back types +static const Enum lookBehindTokenEnums +({ + TOKEN_PAIR("cellSet", CSET), + TOKEN_PAIR("faceSet", FSET), + TOKEN_PAIR("pointSet", PSET), + TOKEN_PAIR("cellZone", CZONE), + TOKEN_PAIR("faceZone", FZONE), + TOKEN_PAIR("pointZone", PZONE), +}); + +#define HAS_LOOKBEHIND_TOKENS + + +// Special handling of predefined method types. Eg, .x(), .y(), ... +static const Enum 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 */ +}); + + +// Known field-token types +static const Enum fieldTokenEnums +({ +#ifdef TOK_SCALAR_ID + TOKEN_PAIR(volScalarField::typeName.c_str(), SCALAR_ID), + TOKEN_PAIR(volVectorField::typeName.c_str(), VECTOR_ID), + TOKEN_PAIR(volTensorField::typeName.c_str(), TENSOR_ID), + TOKEN_PAIR(volSymmTensorField::typeName.c_str(), SYM_TENSOR_ID), + TOKEN_PAIR(volSphericalTensorField::typeName.c_str(), SPH_TENSOR_ID), +#else +#error TOK_SCALAR_ID not defined +#endif +#ifdef TOK_SSCALAR_ID + TOKEN_PAIR(surfaceScalarField::typeName.c_str(), SSCALAR_ID), + TOKEN_PAIR(surfaceVectorField::typeName.c_str(), SVECTOR_ID), + TOKEN_PAIR(surfaceTensorField::typeName.c_str(), STENSOR_ID), + TOKEN_PAIR(surfaceSymmTensorField::typeName.c_str(), SSYM_TENSOR_ID), + TOKEN_PAIR(surfaceSphericalTensorField::typeName.c_str(), SSPH_TENSOR_ID), +#else +#warning TOK_SSCALAR_ID not defined +#endif +#ifdef TOK_PSCALAR_ID + TOKEN_PAIR(pointScalarField::typeName.c_str(), PSCALAR_ID), + TOKEN_PAIR(pointVectorField::typeName.c_str(), PVECTOR_ID), + TOKEN_PAIR(pointTensorField::typeName.c_str(), PTENSOR_ID), + TOKEN_PAIR(pointSymmTensorField::typeName.c_str(), PSYM_TENSOR_ID), + TOKEN_PAIR(pointSphericalTensorField::typeName.c_str(), PSPH_TENSOR_ID), +#else +#warning TOK_PSCALAR_ID not defined +#endif +}); + + +// Simple compile-time function name declarations. +// Useful for handling driver-specific dispatching, or functions that +// are not universally available. +static const Enum funcTokenEnums +({ +#ifdef TOK_FLOOR + TOKEN_PAIR("floor", FLOOR), + TOKEN_PAIR("ceil", CEIL), + TOKEN_PAIR("round", ROUND), +#endif +#ifdef TOK_HYPOT /* Can use hypot? */ + TOKEN_PAIR("hypot", HYPOT), +#endif + + // Already parsed as function: TOKEN_PAIR("pos", CELL_CENTRE), + + TOKEN_PAIR("point", POINT_EXPR), // Point value + TOKEN_PAIR("face", FACE_EXPR), // Face value, Face areaNormal + + TOKEN_PAIR("cellToPoint", CELL_TO_POINT), + TOKEN_PAIR("cellToFace", CELL_TO_FACE), + TOKEN_PAIR("pointToCell", POINT_TO_CELL), + + TOKEN_PAIR("area", FACE_AREA), + TOKEN_PAIR("vol", CELL_VOLUME), + + TOKEN_PAIR("fpos", FACE_CENTRE), + TOKEN_PAIR("pts", POINTS), +}); + +} // 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::volumeExpr::parseDriver& driver_, + const word& ident +) +{ + // Get stashed "look-behind" to decide what type of identifier we expect + const int lookBehind = driver_.resetStashedTokenId(); + + if (lookBehind && lookBehindTokenEnums.found(lookBehind)) + { + bool good = false; + + switch (lookBehind) + { + case TOK_CSET : good = driver_.isCellSet(ident); break; + case TOK_FSET : good = driver_.isFaceSet(ident); break; + case TOK_PSET : good = driver_.isPointSet(ident); break; + case TOK_CZONE : good = driver_.isCellZone(ident); break; + case TOK_FZONE : good = driver_.isFaceZone(ident); break; + case TOK_PZONE : good = driver_.isPointZone(ident); break; + } + + if (good) + { + return TOK_IDENTIFIER; + } + + // Fatal + driver_.reportFatal + ( + "Error no " + lookBehindTokenEnums.get(lookBehind) + ": " + ident + ); + + return -2; // Extra safety + } + + // Surface variables - distinguish from volume by size + #ifdef TOK_SSCALAR_ID + { + const label len = driver_.mesh().nInternalFaces(); + + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, false, len)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SSCALAR_ID, scalar); + checkFieldToken(TOK_SVECTOR_ID, vector); + checkFieldToken(TOK_SSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_SSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_STENSOR_ID, tensor); + } + #endif + + // Point variables + #ifdef TOK_PSCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, true)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_PSCALAR_ID, scalar); + checkFieldToken(TOK_PVECTOR_ID, vector); + checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_PTENSOR_ID, tensor); + } + #endif + + // Volume variables + #ifdef TOK_SCALAR_ID + { + #undef checkFieldToken + #define checkFieldToken(TokType, Type) \ + if (driver_.isVariable(ident, false)) \ + { \ + return TokType; \ + } + + checkFieldToken(TOK_SCALAR_ID, scalar); + checkFieldToken(TOK_VECTOR_ID, vector); + checkFieldToken(TOK_SPH_TENSOR_ID, sphericalTensor); + checkFieldToken(TOK_SYM_TENSOR_ID, symmTensor); + checkFieldToken(TOK_TENSOR_ID, tensor); + } + #endif + + #undef checkFieldToken + + // Check registered fields and/or disk-files + { + const word fieldType(driver_.getFieldClassName(ident)); + + int tokType = fieldTokenEnums.get(fieldType, -1); + + if (tokType > 0) + { + return tokType; + } + } + + return -1; +} + +} // End anonymous namespace + + +/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ + +// 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) << ": " << driver_.parsePosition() << nl; \ + parser_->parse(TOKEN_OF(T), nullptr); \ + driver_.parsePosition() = (p-buf); + + +%%{ + machine volumeExpr; + write data; + + action emit_number { + 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); + } + + action emit_ident { + driver_.parsePosition() = (ts-buf); + dispatch_ident(driver_, scanTok, word(ts, te-ts, false)); + driver_.parsePosition() = (p-buf); + } + + action emit_method { + // 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); + } + + decimal = ((digit* '.' digit+) | (digit+ '.'?)) ; + number = ((digit+ | decimal) ([Ee][\-+]? digit+)?) ; + ident = ((alpha|'_') . ((alnum|[._])**)) ; + dquoted = '"' [^\"]+ '"' ; + squoted = "'" [^\']+ "'" ; + + + ## The scanner + main := |* + space*; + + number => emit_number; + + ## operators + '!' =>{ EMIT_TOKEN(NOT); }; + '%' =>{ EMIT_TOKEN(PERCENT); }; + '(' =>{ EMIT_TOKEN(LPAREN); }; + ')' =>{ EMIT_TOKEN(RPAREN); }; + '*' =>{ EMIT_TOKEN(TIMES); }; + '+' =>{ EMIT_TOKEN(PLUS); }; + '-' =>{ EMIT_TOKEN(MINUS); }; + ',' =>{ EMIT_TOKEN(COMMA); }; + '.' =>{ EMIT_TOKEN(DOT); }; + '/' =>{ EMIT_TOKEN(DIVIDE); }; + '?' =>{ EMIT_TOKEN(QUESTION); }; + ':' =>{ EMIT_TOKEN(COLON); }; + '<' =>{ EMIT_TOKEN(LESS); }; + '<=' =>{ EMIT_TOKEN(LESS_EQ); }; + '>' =>{ EMIT_TOKEN(GREATER); }; + '>=' =>{ EMIT_TOKEN(GREATER_EQ); }; + '==' =>{ EMIT_TOKEN(EQUAL); }; + '!=' =>{ EMIT_TOKEN(NOT_EQUAL); }; + '&&' =>{ EMIT_TOKEN(LAND); }; + '||' =>{ EMIT_TOKEN(LOR); }; + '&' =>{ EMIT_TOKEN(BIT_AND); }; +## Not needed? '|' =>{ EMIT_TOKEN(BIT_OK); }; + '^' =>{ EMIT_TOKEN(BIT_XOR); }; + + ## Some '.method' - Error if unknown + '.' alpha+ => emit_method; + + + ## Regular functions + "pi" =>{ EMIT_TOKEN(PI); }; + "degToRad" =>{ EMIT_TOKEN(DEG_TO_RAD); }; + "radToDeg" =>{ EMIT_TOKEN(RAD_TO_DEG); }; + "exp" =>{ EMIT_TOKEN(EXP); }; + "log" =>{ EMIT_TOKEN(LOG); }; + "log10" =>{ EMIT_TOKEN(LOG10); }; + "pow" =>{ EMIT_TOKEN(POW); }; + "sqr" =>{ EMIT_TOKEN(SQR); }; + "sqrt" =>{ EMIT_TOKEN(SQRT); }; + "cbrt" =>{ EMIT_TOKEN(CBRT); }; + "sin" =>{ EMIT_TOKEN(SIN); }; + "cos" =>{ EMIT_TOKEN(COS); }; + "tan" =>{ EMIT_TOKEN(TAN); }; + "asin" =>{ EMIT_TOKEN(ASIN); }; + "acos" =>{ EMIT_TOKEN(ACOS); }; + "atan" =>{ EMIT_TOKEN(ATAN); }; + "atan2" =>{ EMIT_TOKEN(ATAN2); }; + "sinh" =>{ EMIT_TOKEN(SINH); }; + "cosh" =>{ EMIT_TOKEN(COSH); }; + "tanh" =>{ EMIT_TOKEN(TANH); }; + "mag" =>{ EMIT_TOKEN(MAG); }; + "magSqr" =>{ EMIT_TOKEN(MAGSQR); }; + + "pos" =>{ EMIT_TOKEN(POS); }; + "neg" =>{ EMIT_TOKEN(NEG); }; + "pos0" =>{ EMIT_TOKEN(POS0); }; + "neg0" =>{ EMIT_TOKEN(NEG0); }; + "sign" =>{ EMIT_TOKEN(SIGN); }; + + ## Reductions, or other special functions + "min" =>{ EMIT_TOKEN(MIN); }; + "max" =>{ EMIT_TOKEN(MAX); }; + "average" =>{ EMIT_TOKEN(AVERAGE); }; + "sum" =>{ EMIT_TOKEN(SUM); }; + "weightAverage" =>{ EMIT_TOKEN(WEIGHT_AVERAGE); }; + "weightSum" =>{ EMIT_TOKEN(WEIGHT_SUM); }; + "rand" =>{ EMIT_TOKEN(RAND); }; + + ## Types + "bool" =>{ EMIT_TOKEN(BOOL); }; + "vector" =>{ EMIT_TOKEN(VECTOR); }; + "tensor" =>{ EMIT_TOKEN(TENSOR); }; + "symmTensor" =>{ EMIT_TOKEN(SYM_TENSOR); }; + "sphericalTensor" =>{ EMIT_TOKEN(SPH_TENSOR); }; + + ## Single value (constants, etc) + "Zero" =>{ EMIT_TOKEN(ZERO); }; + "true" =>{ EMIT_TOKEN(LTRUE); }; + "false" =>{ EMIT_TOKEN(LFALSE); }; + "tensor::I" =>{ EMIT_TOKEN(UNIT_TENSOR); }; + "time" =>{ EMIT_TOKEN(TIME); }; + + ## Identifier (field, etc - error if unknown) + ## Handle 'bare' names and single/double quoted ones + ident => emit_ident; + dquoted => emit_ident; + squoted => emit_ident; + + space*; + *|; +}%% + + +// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * // + +Foam::expressions::volumeExpr::scanner::~scanner() +{ + if (parser_) + { + delete parser_; + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::expressions::volumeExpr::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.get(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::volumeExpr::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.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " function:" + << parser_->nameOfToken(tokType) << nl; + + parser_->parse(tokType, nullptr); + return true; + } + + #ifdef HAS_LOOKBEHIND_TOKENS + // Specials such "cset" also reset the look-behind + tokType = lookBehindTokenEnums.get(ident, -1); + + if (tokType > 0) + { + DebugInfo + << "Emit:" << ident << " as look-behind:" + << parser_->nameOfToken(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_->nameOfToken(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.get(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_->nameOfToken(tokType) << " with " + << ident.substr(dot).c_str() << " token:" + << parser_->nameOfToken(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::volumeExpr::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 |= 4; + } + + 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; + + // Ragel token start/end (required naming) + const char* ts; + const char* te; + + // Local buffer data. + // - p, pe, eof are required 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 + %%{write init;}%% /* ^^^ FSM initialization here ^^^ */; + + %%{write exec;}%% /* ^^^ FSM execution here ^^^ */; + + if (%%{write error;}%% == cs) + { + driver_.reportFatal("Parse error while scanning", (p-buf)); + } + + if (p != eof) + { + driver_.reportFatal("Parsing failed with remaining content", (p-buf)); + } + + // Terminate parser execution + parser_->parse(0, nullptr); + parser_->stop(); + + // Restore debug value + debug = oldDebug; + + return true; +} + + +// ************************************************************************* //