diff --git a/src/finiteVolume/Make/files b/src/finiteVolume/Make/files
index 20497d102d..5ef761d151 100644
--- a/src/finiteVolume/Make/files
+++ b/src/finiteVolume/Make/files
@@ -258,6 +258,13 @@ $(expr)/base/fvExprDriverFields.C
$(expr)/base/fvExprDriverIO.C
$(expr)/base/fvExprDriverNew.C
+patchExpr = $(expr)/patch
+$(patchExpr)/patchExpr.C
+$(patchExpr)/patchExprDriver.C
+$(patchExpr)/patchExprDriverFields.C
+$(patchExpr)/patchExprLemonParser.lyy-m4
+$(patchExpr)/patchExprScanner.cc
+
fvMatrices/fvMatrices.C
fvMatrices/fvScalarMatrix/fvScalarMatrix.C
diff --git a/src/finiteVolume/expressions/patch/createCode b/src/finiteVolume/expressions/patch/createCode
new file mode 100755
index 0000000000..3aab7655b8
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/createCode
@@ -0,0 +1,13 @@
+#!/bin/sh
+cd ${0%/*} || exit 1 # Run from this directory
+# Manually create ragel scanner and lemon parser header
+
+prefix=patchExpr
+
+"${WM_PROJECT_DIR:?}/wmake/scripts/makeParser" \
+ -prefix="$prefix" \
+ -scanner=Scanner.rl \
+ -parser=LemonParser.lyy-m4 \
+ "$@"
+
+#------------------------------------------------------------------------------
diff --git a/src/finiteVolume/expressions/patch/patchExpr.C b/src/finiteVolume/expressions/patch/patchExpr.C
new file mode 100644
index 0000000000..e5a4c54ccc
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExpr.C
@@ -0,0 +1,45 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 "patchExprFwd.H"
+#include "defineDebugSwitch.H"
+
+// * * * * * * * * * * * * * * * * Globals * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace expressions
+{
+
+defineDebugSwitchWithName(patchExpr, "patchExpr", 0);
+registerDebugSwitchWithName(patchExpr, patchExpr, "patchExpr");
+
+} // End namespace expressions
+} // End namespace Foam
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprDriver.C b/src/finiteVolume/expressions/patch/patchExprDriver.C
new file mode 100644
index 0000000000..5f22efe3e0
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprDriver.C
@@ -0,0 +1,188 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 "patchExprDriver.H"
+#include "patchExprScanner.H"
+#include "error.H"
+#include "fvPatch.H"
+#include "fvMesh.H"
+#include "className.H"
+#include "addToRunTimeSelectionTable.H"
+
+// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace expressions
+{
+namespace patchExpr
+{
+
+defineTypeNameAndDebug(parseDriver, 0);
+
+addNamedToRunTimeSelectionTable
+(
+ fvExprDriver,
+ parseDriver,
+ dictionary,
+ patch
+);
+
+addNamedToRunTimeSelectionTable
+(
+ fvExprDriver,
+ parseDriver,
+ idName,
+ patch
+);
+
+} // End namespace patchExpr
+} // 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 fvPatch& findFvPatch
+ (
+ const fvMesh& mesh,
+ const word& patchName
+ )
+ {
+ return mesh.boundary()[getPatchID(mesh, patchName)];
+ }
+
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
+
+const Foam::fvPatch& Foam::expressions::patchExpr::parseDriver::getFvPatch
+(
+ const fvMesh& fvm,
+ const dictionary& dict
+)
+{
+ return findFvPatch
+ (
+ regionMesh(dict, fvm, true),
+ dict.get("patch")
+ );
+}
+
+
+// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
+
+Foam::expressions::patchExpr::parseDriver::parseDriver(const fvPatch& p)
+:
+ parsing::genericRagelLemonDriver(),
+ expressions::fvExprDriver(),
+ patch_(p)
+{}
+
+
+Foam::expressions::patchExpr::parseDriver::parseDriver
+(
+ const fvPatch& p,
+ const dictionary& dict
+)
+:
+ parsing::genericRagelLemonDriver(),
+ expressions::fvExprDriver(dict),
+ patch_(p)
+{}
+
+
+Foam::expressions::patchExpr::parseDriver::parseDriver
+(
+ const fvPatch& p,
+ const parseDriver& driver_
+)
+:
+ parsing::genericRagelLemonDriver(),
+ expressions::fvExprDriver(driver_),
+ patch_(p)
+{}
+
+
+Foam::expressions::patchExpr::parseDriver::parseDriver
+(
+ const word& patchName,
+ const fvMesh& mesh
+)
+:
+ parseDriver(findFvPatch(mesh, patchName))
+{}
+
+
+Foam::expressions::patchExpr::parseDriver::parseDriver
+(
+ const dictionary& dict,
+ const fvMesh& mesh
+)
+:
+ parseDriver(getFvPatch(mesh, dict), dict)
+{}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+unsigned Foam::expressions::patchExpr::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/patch/patchExprDriver.H b/src/finiteVolume/expressions/patch/patchExprDriver.H
new file mode 100644
index 0000000000..294c902cf4
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprDriver.H
@@ -0,0 +1,305 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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::patchExpr::parseDriver
+
+Description
+ Driver for patch expressions
+
+ 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 face centres | 0 |
+ pts | The face points | 0 |
+ area | The face area magnitudes | 0 |
+ weightAverage| Area weighted average | 1 |
+ weightSum | Area weighted sum | 1 |
+ face | The face areaNormal vectors | 0 |
+ point | A point-field point value | 1 |
+ faceToPoint | Interpolate face values onto points | 1 |
+ pointToFace | Interpolate point values onto faces | 1 |
+ rand | Random field | 0/1 |
+ \endtable
+
+SourceFiles
+ patchExprDriver.C
+ patchExprDriverFields.C
+ patchExprDriverTemplates.C
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef expressions_patchExprDriver_H
+#define expressions_patchExprDriver_H
+
+#include "patchExprFwd.H"
+#include "fvExprDriver.H"
+#include "Enum.H"
+#include "volFields.H"
+#include "surfaceFields.H"
+#include "pointFields.H"
+#include "genericRagelLemonDriver.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+namespace expressions
+{
+namespace patchExpr
+{
+
+/*---------------------------------------------------------------------------*\
+ Class parseDriver Declaration
+\*---------------------------------------------------------------------------*/
+
+class parseDriver
+:
+ public parsing::genericRagelLemonDriver,
+ public expressions::fvExprDriver
+{
+ // Private Member Functions
+
+ static const fvPatch& getFvPatch
+ (
+ const fvMesh& fvm,
+ const dictionary& dict
+ );
+
+
+protected:
+
+ // Protected Data
+
+ //- The referenced patch
+ const fvPatch& patch_;
+
+
+ // Protected Member Functions
+
+ // No copy copy construct
+ parseDriver(const parseDriver&) = delete;
+
+ // No copy assignment
+ void operator=(const parseDriver&) = delete;
+
+
+public:
+
+ ClassName("patchExpr::driver");
+
+ // Constructors
+
+ //- Construct for specified patch
+ explicit parseDriver(const fvPatch& p);
+
+ //- Construct for specified patch with given dictionary
+ parseDriver(const fvPatch& p, const dictionary& dict);
+
+ //- Construct for specified patch with copy of driver context
+ parseDriver(const fvPatch& p, const parseDriver& driver_);
+
+ //- Construct with patchName for the given mesh
+ parseDriver(const word& patchName, const fvMesh& mesh);
+
+ //- Construct with "patch" (mandatory) and "region" (optional)
+ //- specified in dictionary
+ parseDriver(const dictionary& dict, const fvMesh& mesh);
+
+ //- Clone
+ virtual autoPtr clone() const
+ {
+ return autoPtr
+ (
+ new parseDriver(this->patch_, *this)
+ );
+ }
+
+
+ //- Destructor
+ virtual ~parseDriver() = default;
+
+
+ // Public Member Functions
+
+ //- The mesh we are attached to
+ virtual const fvMesh& mesh() const
+ {
+ return patch_.boundaryMesh().mesh();
+ }
+
+ //- The underlying field size for the expression
+ virtual label size() const
+ {
+ return patch_.patch().size();
+ }
+
+ //- The underlying point field size for the expression
+ virtual label pointSize() const
+ {
+ return patch_.patch().nPoints();
+ }
+
+ //- Field size associated with different geometric field types
+ inline label size(const FieldAssociation geoType) const;
+
+
+ // 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
+
+ // Fields
+
+ //- Set result
+ template
+ void setResult(Field* ptr, bool pointVal = false)
+ {
+ result().setResult(ptr, pointVal);
+ }
+
+
+ //- Retrieve variable as field if possible.
+ // Test tmp for validity to determine success of the operation.
+ template
+ tmp> getVariableIfAvailable(const word& fldName) const;
+
+ //- Retrieve field (vol field)
+ template
+ tmp>
+ getVolField(const word& fldName);
+
+ //- Retrieve field (surface field)
+ template
+ tmp>
+ getSurfaceField(const word& fldName);
+
+ //- Retrieve field (point field)
+ template
+ tmp>
+ getPointField(const word& fldName);
+
+ //- Return named field
+ template
+ tmp> getField(const word& fldName);
+
+
+ // Field "shape" conversions
+
+ //- Interpolate face to point
+ template
+ tmp> faceToPoint(const Field& field) const;
+
+ //- Interpolate point to face values
+ template
+ tmp> pointToFace(const Field& field) const;
+
+
+ // Custom Field Functions
+
+ //- The area-weighted average of a field
+ template
+ Type areaAverage(const Field& fld) const
+ {
+ return weightedAverage(patch_.magSf(), fld);
+ }
+
+ //- The area-weighted sum of a field
+ template
+ Type areaSum(const Field& fld) const
+ {
+ return weightedSum(patch_.magSf(), fld);
+ }
+
+ //- The face area magnitudes [magSf] - (swak = area)
+ tmp field_faceArea() const;
+
+ //- The face centres - (swak = pos)
+ tmp field_faceCentre() const;
+
+ //- The face areas with their vector direction [Sf] - (swak = face)
+ tmp field_areaNormal() const;
+
+ //- The patch point locations - (swak = pts)
+ tmp field_pointField() 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);
+ }
+};
+
+
+// Template specializations
+
+//- Retrieve field (surface field: bool)
+template<>
+tmp> parseDriver::getSurfaceField(const word& fldName);
+
+//- Retrieve field (point field: bool)
+template<>
+tmp> parseDriver::getPointField(const word& fldName);
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace patchExpr
+} // End namespace expressions
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#include "patchExprDriverI.H"
+
+#ifdef NoRepository
+ #include "patchExprDriverTemplates.C"
+#endif
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprDriverFields.C b/src/finiteVolume/expressions/patch/patchExprDriverFields.C
new file mode 100644
index 0000000000..690a4c2376
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprDriverFields.C
@@ -0,0 +1,100 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 "patchExprDriver.H"
+#include "fvPatch.H"
+#include "error.H"
+
+// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
+
+template<>
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getSurfaceField
+(
+ const word& name
+)
+{
+ return getVariable(name, this->size());
+}
+
+
+template<>
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getPointField
+(
+ const word& name
+)
+{
+ return getVariable(name, this->pointSize());
+}
+
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+Foam::tmp
+Foam::expressions::patchExpr::parseDriver::field_faceArea() const
+{
+ return patch_.magSf();
+}
+
+
+Foam::tmp
+Foam::expressions::patchExpr::parseDriver::field_faceCentre() const
+{
+ return patch_.Cf();
+}
+
+
+Foam::tmp
+Foam::expressions::patchExpr::parseDriver::field_areaNormal() const
+{
+ return patch_.Sf();
+}
+
+
+Foam::tmp
+Foam::expressions::patchExpr::parseDriver::field_pointField() const
+{
+ return patch_.patch().localPoints();
+}
+
+
+Foam::tmp
+Foam::expressions::patchExpr::parseDriver::field_rand
+(
+ label seed,
+ bool gaussian
+) const
+{
+ auto tresult = tmp::New(this->size());
+ fill_random(tresult.ref(), seed, gaussian);
+
+ return tresult;
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprDriverI.H b/src/finiteVolume/expressions/patch/patchExprDriverI.H
new file mode 100644
index 0000000000..b4ae95c4ea
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprDriverI.H
@@ -0,0 +1,50 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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::patchExpr::parseDriver::size
+(
+ const FieldAssociation geoType
+) const
+{
+ switch (geoType)
+ {
+ case FieldAssociation::POINT_DATA :
+ return patch_.patch().nPoints();
+ break;
+ case FieldAssociation::SURFACE_DATA :
+ return patch_.patch().size();
+ break;
+ default:
+ break;
+ }
+ return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C
new file mode 100644
index 0000000000..7fafffbc50
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprDriverTemplates.C
@@ -0,0 +1,228 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 "primitivePatchInterpolation.H"
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getVariableIfAvailable
+(
+ const word& name
+) const
+{
+ bool isPointVal = false;
+ bool isUniformVal = false;
+
+ tmp> tfield;
+
+ if (hasVariable(name) && variable(name).isType())
+ {
+ const expressions::exprResult& var = variable(name);
+
+ isPointVal = var.isPointValue();
+ isUniformVal = var.isUniform();
+
+ tfield = var.cref().clone();
+ }
+ else if (isGlobalVariable(name, false))
+ {
+ const expressions::exprResult& var = lookupGlobal(name);
+
+ isUniformVal = var.isUniform();
+
+ tfield = var.cref().clone();
+ }
+
+ if (tfield.valid())
+ {
+ const label fldLen = tfield().size();
+ const label len = (isPointVal ? this->pointSize() : this->size());
+
+ if (returnReduce((fldLen == len), andOp()))
+ {
+ return tfield;
+ }
+
+ if (!isUniformVal)
+ {
+ WarningInFunction
+ << "Variable " << name
+ << " does not fit the size and is not a uniform value." << nl
+ << "Using average value" << endl;
+ }
+
+ return tmp>::New(this->size(), gAverage(tfield));
+ }
+
+ return tfield;
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getVolField(const word& name)
+{
+ return getField(name);
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getSurfaceField(const word& name)
+{
+ return getField(name);
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getPointField(const word& name)
+{
+ return getField(name);
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::getField(const word& name)
+{
+ tmp> tfield = getVariableIfAvailable(name);
+
+ if (tfield.valid())
+ {
+ return tfield;
+ }
+
+
+ typedef GeometricField vfieldType;
+ typedef GeometricField sfieldType;
+ typedef GeometricField pfieldType;
+
+ const objectRegistry& obr = this->mesh().thisDb();
+
+ const vfieldType* vfield = obr.findObject(name);
+ const sfieldType* sfield = obr.findObject(name);
+ const pfieldType* pfield = obr.findObject(name);
+
+ // Local, temporary storage
+ tmp t_vfield;
+ tmp t_sfield;
+ tmp t_pfield;
+
+ if (searchFiles() && !vfield && !sfield && !pfield)
+ {
+ const word fldType = this->getTypeOfField(name);
+
+ if (fldType == vfieldType::typeName)
+ {
+ t_vfield = this->readAndRegister(name, mesh());
+ vfield = t_vfield.get();
+ }
+ else if (fldType == sfieldType::typeName)
+ {
+ t_sfield = this->readAndRegister(name, mesh());
+ sfield = t_sfield.get();
+ }
+ else if (fldType == pfieldType::typeName)
+ {
+ t_pfield = this->readAndRegister
+ (
+ name,
+ pointMesh::New(mesh())
+ );
+ pfield = t_pfield.get();
+ }
+ }
+
+ const label patchIndex = patch_.index();
+
+ if (vfield)
+ {
+ return tmp>::New
+ (
+ vfield->boundaryField()[patchIndex]
+ );
+ }
+
+ if (sfield)
+ {
+ return tmp>::New
+ (
+ sfield->boundaryField()[patchIndex]
+ );
+ }
+
+ if (pfield)
+ {
+ return pfield->boundaryField()[patchIndex].patchInternalField();
+ }
+
+
+ FatalErrorInFunction
+ << "No field '" << name << "' of type "
+ << pTraits::typeName << nl << nl
+ << vfieldType::typeName << " Fields: "
+ << flatOutput(obr.sortedNames()) << nl
+ << sfieldType::typeName << " Fields: "
+ << flatOutput(obr.sortedNames()) << nl
+ << pfieldType::typeName << " Fields: "
+ << flatOutput(obr.sortedNames()) << nl
+ << exit(FatalError);
+
+ return tmp>::New();
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::faceToPoint
+(
+ const Field& field
+) const
+{
+ primitivePatchInterpolation interp(patch_.patch());
+
+ return interp.pointToFaceInterpolate(field);
+}
+
+
+template
+Foam::tmp>
+Foam::expressions::patchExpr::parseDriver::pointToFace
+(
+ const Field& field
+) const
+{
+ primitivePatchInterpolation interp(patch_.patch());
+
+ return interp.faceToPointInterpolate(field);
+}
+
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprFwd.H b/src/finiteVolume/expressions/patch/patchExprFwd.H
new file mode 100644
index 0000000000..5682b896fb
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprFwd.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::patchExpr
+
+Description
+ Namespace for patch expressions parsing and evaluation
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef expressions_patchExprFwd_H
+#define expressions_patchExprFwd_H
+
+namespace Foam
+{
+namespace expressions
+{
+namespace patchExpr
+{
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+// Forward Declarations
+class parser;
+class scanner;
+class parseDriver;
+union scanToken;
+
+//- Static debugging option
+extern int debug;
+
+
+//- The field association for patch expressions (mutually exclusive)
+enum FieldAssociation : unsigned char
+{
+ NO_DATA = 0, //!< No data
+ POINT_DATA = 1, //!< Point data
+ SURFACE_DATA = 2 //!< Surface data
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace patchExpr
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+//- Typedef for patchExpr parseDriver
+typedef patchExpr::parseDriver patchExprDriver;
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+} // End namespace expressions
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParser.h b/src/finiteVolume/expressions/patch/patchExprLemonParser.h
new file mode 100644
index 0000000000..8a84326c4d
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprLemonParser.h
@@ -0,0 +1,110 @@
+#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_SSCALAR_ID 30
+#define TOK_MIN 31
+#define TOK_COMMA 32
+#define TOK_MAX 33
+#define TOK_SUM 34
+#define TOK_AVERAGE 35
+#define TOK_EXP 36
+#define TOK_LOG 37
+#define TOK_LOG10 38
+#define TOK_SQR 39
+#define TOK_SQRT 40
+#define TOK_CBRT 41
+#define TOK_SIN 42
+#define TOK_COS 43
+#define TOK_TAN 44
+#define TOK_ASIN 45
+#define TOK_ACOS 46
+#define TOK_ATAN 47
+#define TOK_SINH 48
+#define TOK_COSH 49
+#define TOK_TANH 50
+#define TOK_POW 51
+#define TOK_ATAN2 52
+#define TOK_POS 53
+#define TOK_NEG 54
+#define TOK_POS0 55
+#define TOK_NEG0 56
+#define TOK_SIGN 57
+#define TOK_FLOOR 58
+#define TOK_CEIL 59
+#define TOK_ROUND 60
+#define TOK_HYPOT 61
+#define TOK_RAND 62
+#define TOK_VECTOR_ID 63
+#define TOK_SVECTOR_ID 64
+#define TOK_SPH_TENSOR_ID 65
+#define TOK_SSPH_TENSOR_ID 66
+#define TOK_SYM_TENSOR_ID 67
+#define TOK_SSYM_TENSOR_ID 68
+#define TOK_UNIT_TENSOR 69
+#define TOK_TENSOR_ID 70
+#define TOK_STENSOR_ID 71
+#define TOK_LTRUE 72
+#define TOK_LFALSE 73
+#define TOK_BOOL 74
+#define TOK_SBOOL_ID 75
+#define TOK_FACE_AREA 76
+#define TOK_FACE_EXPR 77
+#define TOK_WEIGHT_AVERAGE 78
+#define TOK_WEIGHT_SUM 79
+#define TOK_POINT_EXPR 80
+#define TOK_PSCALAR_ID 81
+#define TOK_PVECTOR_ID 82
+#define TOK_PSPH_TENSOR_ID 83
+#define TOK_PSYM_TENSOR_ID 84
+#define TOK_PTENSOR_ID 85
+#define TOK_PBOOL_ID 86
+#define TOK_POINTS 87
+#define TOK_MAG 88
+#define TOK_MAGSQR 89
+#define TOK_VECTOR 90
+#define TOK_TENSOR 91
+#define TOK_SYM_TENSOR 92
+#define TOK_SPH_TENSOR 93
+#define TOK_CMPT_X 94
+#define TOK_CMPT_Y 95
+#define TOK_CMPT_Z 96
+#define TOK_CMPT_XX 97
+#define TOK_CMPT_XY 98
+#define TOK_CMPT_XZ 99
+#define TOK_CMPT_YX 100
+#define TOK_CMPT_YY 101
+#define TOK_CMPT_YZ 102
+#define TOK_CMPT_ZX 103
+#define TOK_CMPT_ZY 104
+#define TOK_CMPT_ZZ 105
+#define TOK_CMPT_II 106
+#define TOK_TRANSPOSE 107
+#define TOK_DIAG 108
+#define TOK_POINT_TO_FACE 109
+#define TOK_FACE_TO_POINT 110
diff --git a/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4 b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4
new file mode 100644
index 0000000000..477cc7ea46
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprLemonParser.lyy-m4
@@ -0,0 +1,565 @@
+%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 patch expressions.
+
+ https://www.sqlite.org/src/doc/trunk/doc/lemon.html
+
+ See detailed notes in the field expression parser.
+
+\*---------------------------------------------------------------------------*/
+} // %include
+
+/*
+ * include[patchExprLemonParserMacros.m4]
+ *include(`patchExprLemonParserMacros.m4')dnl
+ !done in a comment since many editors have issues matching m4 quotes!
+ */
+%include
+{
+#include "patchExprDriver.H"
+#include "patchExprParser.H"
+#include "patchExprScanner.H"
+#include "unitConversion.H"
+#include "error.H"
+#include "volFields.H"
+#include "exprOps.H"
+#include "exprDriverOps.H"
+#include "GeometricFieldOps.H"
+
+// Enable ParseTrace
+#undef NDEBUG
+
+compiler_pragmas()
+
+// Local Functions
+
+tmp_management()
+
+} // %include
+
+// ------------------------------------------------------------------------- //
+
+%namespace {}
+
+// Use extra argument for the return value
+%extra_context { Foam::expressions::patchExpr::parseDriver* driver }
+%parse_failure { driver->reportFatal("Parse failure, giving up..."); }
+%syntax_error { driver->reportFatal("Syntax error"); }
+
+%token_prefix TOK_
+
+// Terminals
+%token_type {Foam::expressions::patchExpr::scanToken*}
+// Non-terminals
+%type ivalue { Foam::label }
+%type svalue { Foam::scalar }
+%type ident { Foam::word* }
+
+// Face fields
+declare_field(lfield, Foam::boolField, bool, newField, getSurfaceField)
+declare_field(sfield, Foam::scalarField, Foam::scalar, newField, getField)
+declare_field(vfield, Foam::vectorField, Foam::vector, newField, getField)
+declare_field(hfield, Foam::sphericalTensorField, Foam::sphericalTensor, newField, getField)
+declare_field(yfield, Foam::symmTensorField, Foam::symmTensor, newField, getField)
+declare_field(tfield, Foam::tensorField, Foam::tensor, newField, getField)
+
+// Point fields
+declare_field(plfield, Foam::boolField, bool, newPointField, getPointField)
+declare_field(psfield, Foam::scalarField, Foam::scalar, newPointField, getPointField)
+declare_field(pvfield, Foam::vectorField, Foam::vector, newPointField, getPointField)
+declare_field(phfield, Foam::sphericalTensorField, Foam::sphericalTensor, newPointField, getPointField)
+declare_field(pyfield, Foam::symmTensorField, Foam::symmTensor, newPointField, getPointField)
+declare_field(ptfield, Foam::tensorField, 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(); }
+
+
+/* * * * * * * * * * * * * * * * * Face 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 (scalarField)
+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)
+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 works directly for scalarField
+rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
+
+
+// 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 (vectorField)
+dnl
+define([_target_], [vfield])dnl
+define([_value_type_], [Foam::vector])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a); }
+
+rule_get_field(_target_, VECTOR_ID)
+rule_get_field(_target_, SVECTOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_vector_operations()
+rules_vector_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (sphericalTensorField)
+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)
+rule_get_field(_target_, SSPH_TENSOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_sphTensor_operations()
+rules_sphTensor_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (symmTensorField)
+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)
+rule_get_field(_target_, SSYM_TENSOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_symTensor_operations()
+rules_symTensor_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (tensorField)
+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)
+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 (boolField)
+dnl
+define([_target_], [lfield])dnl
+define([_value_type_], [bool])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a); }
+_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)
+
+dnl/* Handling of named logic fields not really tested (disable in scanner) */
+rule_get_field(_target_, SBOOL_ID)
+rules_logical_operations(_logic_, _value_type_)
+
+
+/*---------------------------------------------------------------------------*\
+ * General Surface-related productions
+\*---------------------------------------------------------------------------*/
+
+rules_driver_surface_functions()
+
+
+/* * * * * * * * * * * * * * * * 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
+\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (point scalarField)
+dnl
+define([_target_], [psfield])dnl
+define([_value_type_], [Foam::scalar])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+
+rule_field_from_value(_target_, svalue, POINT_EXPR)
+rule_get_field(_target_, PSCALAR_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 works directly for scalarField
+rule_binary_func(_target_, _target_, _target_, HYPOT, Foam::hypot)
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (point vectorField)
+dnl
+define([_target_], [pvfield])dnl
+define([_value_type_], [Foam::vector])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+
+rule_get_field(_target_, PVECTOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_vector_operations()
+rules_vector_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (point sphericalTensorField)
+dnl
+define([_target_], [phfield])dnl
+define([_value_type_], [Foam::sphericalTensor])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+
+rule_get_field(_target_, PSPH_TENSOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_sphTensor_operations()
+rules_sphTensor_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (point symmTensorField)
+dnl
+define([_target_], [pyfield])dnl
+define([_value_type_], [Foam::symmTensor])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+
+rule_get_field(_target_, PSYM_TENSOR_ID)
+
+rules_standard(_target_, _value_type_, _logic_)
+rules_inplace_gUnary(_target_)
+rules_symTensor_operations()
+rules_symTensor_functions()
+
+
+/*---------------------------------------------------------------------------*\
+ * Productions (point tensorField)
+dnl
+define([_target_], [ptfield])dnl
+define([_value_type_], [Foam::tensor])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+
+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 (point boolField)
+dnl
+define([_target_], [plfield])dnl
+define([_value_type_], [bool])dnl
+dnl
+\*---------------------------------------------------------------------------*/
+
+evaluate ::= _target_ (a) . { driver->setResult(a, true); /* Point */ }
+_logic_ (lhs) ::= POINT_EXPR LPAREN LTRUE RPAREN . { lhs = _new_plfield(_logic_true_); }
+_logic_ (lhs) ::= POINT_EXPR LPAREN LFALSE RPAREN . { lhs = _new_plfield(_logic_false_); }
+
+rule_cast_logical(_target_, _target_)
+rule_cast_logical(_target_, _scalar_, Foam::scalar)
+
+dnl/* Handling of named logic fields not really tested (disable in scanner) */
+rule_get_field(_target_, PBOOL_ID)
+rules_logical_operations(_logic_, _value_type_)
+
+
+/*---------------------------------------------------------------------------*\
+ * General Point-related productions
+\*---------------------------------------------------------------------------*/
+
+rules_driver_point_functions()
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+/*---------------------------------------------------------------------------*\
+ * Face 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_pointToFace(sfield, psfield)
+rule_pointToFace(vfield, pvfield)
+rule_pointToFace(tfield, ptfield)
+rule_pointToFace(yfield, pyfield)
+rule_pointToFace(hfield, phfield)
+
+
+/*---------------------------------------------------------------------------*\
+ * Point field composition
+\*---------------------------------------------------------------------------*/
+
+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_faceToPoint(psfield, sfield)
+rule_faceToPoint(pvfield, vfield)
+rule_faceToPoint(ptfield, tfield)
+rule_faceToPoint(pyfield, yfield)
+rule_faceToPoint(phfield, hfield)
+
+
+// ************************************************************************* //
+
+dnl/* Standard m4 quoting
+changequote([`],['])dnl
+dnl*/
+
+%code
+{
+
+// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
+
+void Foam::expressions::patchExpr::parser::stop()
+{
+ if (lemon_)
+ {
+ ParseFree(lemon_, ::operator delete);
+ #ifndef NDEBUG
+ ParseTrace(nullptr, nullptr);
+ #endif
+ lemon_ = nullptr;
+ }
+}
+
+
+void Foam::expressions::patchExpr::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::patchExpr::parser::parse
+(
+ int tokenId,
+ scanToken* tokenVal
+)
+{
+ Parse(lemon_, tokenId, tokenVal);
+}
+
+
+Foam::word Foam::expressions::patchExpr::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/patch/patchExprLemonParserMacros.m4 b/src/finiteVolume/expressions/patch/patchExprLemonParserMacros.m4
new file mode 100644
index 0000000000..aa183dfeb6
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprLemonParserMacros.m4
@@ -0,0 +1,109 @@
+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 patch 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
+
+use_bool_logic()dnl # Use boolField directly
+
+#-------------------------------------------------------------------------------
+# Driver rules
+#-------------------------------------------------------------------------------
+
+define([rules_driver_surface_functions],
+[dnl
+rule_driver_nullary(_scalar_, FACE_AREA, field_faceArea)dnl
+rule_driver_nullary(_vector_, POS, field_faceCentre)dnl FACE_CENTRE
+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_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_faceToPoint(out, in)
+# rule_pointToFace(out, in)
+#
+# Description
+# Production rules for driver faceToPoint, pointToFace,
+# methods
+#------------------------------------------------------------------------------
+
+define([rule_faceToPoint],
+[rule_driver_unary($1, $2, FACE_TO_POINT, faceToPoint)])
+
+define([rule_pointToFace],
+[rule_driver_unary($1, $2, POINT_TO_FACE, pointToFace)])
+
+
+#------------------------------------------------------------------------------
+# 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/patch/patchExprParser.H b/src/finiteVolume/expressions/patch/patchExprParser.H
new file mode 100644
index 0000000000..a59fcdcca6
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprParser.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::patchExpr::parser
+
+Description
+ Lemon parser interface for patch expressions grammar
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef expressions_patchExprParser_H
+#define expressions_patchExprParser_H
+
+#include "patchExprFwd.H"
+
+namespace Foam
+{
+namespace expressions
+{
+namespace patchExpr
+{
+
+/*---------------------------------------------------------------------------*\
+ Class parser Declaration
+\*---------------------------------------------------------------------------*/
+
+class parser
+{
+ // Private Data
+
+ //- Prompt for parser tracing
+ static constexpr const char* const prompt_ = "patchExpr:";
+
+ //- The lemon parser (demand-driven)
+ void* lemon_;
+
+
+public:
+
+ //- Local object debugging
+ int debug;
+
+
+ // Constructors
+
+ //- Construct null
+ parser() : lemon_(nullptr), debug(patchExpr::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 patchExpr
+} // End namespace expressions
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprScanner.H b/src/finiteVolume/expressions/patch/patchExprScanner.H
new file mode 100644
index 0000000000..3003b749bf
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprScanner.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::patchExpr::scanner
+
+Description
+ Ragel lexer/scanner interface for patch expressions.
+
+Note
+ Ragel code generated with the ./createCode script.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef expressions_patchExprScanner_H
+#define expressions_patchExprScanner_H
+
+#include "patchExprFwd.H"
+#include "scalar.H"
+
+namespace Foam
+{
+namespace expressions
+{
+namespace patchExpr
+{
+
+/*---------------------------------------------------------------------------*\
+ 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(patchExpr::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 patchExpr
+} // End namespace expressions
+} // End namespace Foam
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/finiteVolume/expressions/patch/patchExprScanner.cc b/src/finiteVolume/expressions/patch/patchExprScanner.cc
new file mode 100644
index 0000000000..98fe2225e1
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprScanner.cc
@@ -0,0 +1,3836 @@
+
+#line 1 "patchExprScanner.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 for patch expressions
+
+\*---------------------------------------------------------------------------*/
+
+#include "patchExprScanner.H"
+#include "patchExprDriver.H"
+#include "patchExprLemonParser.h"
+#include "patchExprParser.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 }
+
+#undef 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
+#error 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", FACE_CENTRE),
+
+ TOKEN_PAIR("point", POINT_EXPR), // Point value
+ TOKEN_PAIR("face", FACE_EXPR), // Face areaNormal
+
+ TOKEN_PAIR("faceToPoint", FACE_TO_POINT),
+ TOKEN_PAIR("pointToFace", POINT_TO_FACE),
+
+ TOKEN_PAIR("area", FACE_AREA),
+ 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::patchExpr::parseDriver& driver_,
+ const word& ident
+)
+{
+#if 0
+ // 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
+ }
+#endif
+
+ // Face variables
+ #ifdef TOK_SSCALAR_ID
+ {
+ #undef checkFieldToken
+ #define checkFieldToken(TokType, Type) \
+ if (driver_.isVariable(ident, false)) \
+ { \
+ 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);
+
+ // Not tested: checkFieldToken(TOK_SBOOL_ID, bool);
+ }
+ #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_PTENSOR_ID, tensor);
+ checkFieldToken(TOK_PTENSOR_ID, tensor);
+ checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor);
+ checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor);
+
+ // Not tested: checkFieldToken(TOK_PBOOL_ID, bool);
+ }
+ #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 276 "patchExprScanner.cc"
+static const int patchExpr_start = 11;
+static const int patchExpr_first_final = 11;
+static const int patchExpr_error = 0;
+
+static const int patchExpr_en_main = 11;
+
+
+#line 414 "patchExprScanner.rl"
+
+
+
+// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
+
+Foam::expressions::patchExpr::scanner::~scanner()
+{
+ if (parser_)
+ {
+ delete parser_;
+ }
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+bool Foam::expressions::patchExpr::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::patchExpr::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::patchExpr::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 511 "patchExprScanner.cc"
+ {
+ cs = patchExpr_start;
+ ts = 0;
+ te = 0;
+ act = 0;
+ }
+
+#line 639 "patchExprScanner.rl"
+ /* ^^^ FSM initialization here ^^^ */;
+
+
+#line 523 "patchExprScanner.cc"
+ {
+ if ( p == pe )
+ goto _test_eof;
+ switch ( cs )
+ {
+tr2:
+#line 298 "patchExprScanner.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 298 "patchExprScanner.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 276 "patchExprScanner.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 341 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(EQUAL); }}
+ goto st11;
+tr9:
+#line 395 "patchExprScanner.rl"
+ {{p = ((te))-1;}{ EMIT_TOKEN(TENSOR); }}
+ goto st11;
+tr11:
+#line 403 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(UNIT_TENSOR); }}
+ goto st11;
+tr12:
+#line 344 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(LOR); }}
+ goto st11;
+tr16:
+#line 326 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(PERCENT); }}
+ goto st11;
+tr19:
+#line 327 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(LPAREN); }}
+ goto st11;
+tr20:
+#line 328 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(RPAREN); }}
+ goto st11;
+tr21:
+#line 329 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(TIMES); }}
+ goto st11;
+tr22:
+#line 330 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(PLUS); }}
+ goto st11;
+tr23:
+#line 332 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(COMMA); }}
+ goto st11;
+tr24:
+#line 331 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(MINUS); }}
+ goto st11;
+tr26:
+#line 334 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(DIVIDE); }}
+ goto st11;
+tr28:
+#line 336 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(COLON); }}
+ goto st11;
+tr32:
+#line 335 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(QUESTION); }}
+ goto st11;
+tr35:
+#line 347 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(BIT_XOR); }}
+ goto st11;
+tr52:
+#line 320 "patchExprScanner.rl"
+ {te = p;p--;}
+ goto st11;
+tr53:
+#line 325 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(NOT); }}
+ goto st11;
+tr54:
+#line 342 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(NOT_EQUAL); }}
+ goto st11;
+tr55:
+#line 345 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(BIT_AND); }}
+ goto st11;
+tr56:
+#line 343 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(LAND); }}
+ goto st11;
+tr57:
+#line 333 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(DOT); }}
+ goto st11;
+tr60:
+#line 276 "patchExprScanner.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 304 "patchExprScanner.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 337 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(LESS); }}
+ goto st11;
+tr64:
+#line 338 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(LESS_EQ); }}
+ goto st11;
+tr65:
+#line 339 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(GREATER); }}
+ goto st11;
+tr66:
+#line 340 "patchExprScanner.rl"
+ {te = p+1;{ EMIT_TOKEN(GREATER_EQ); }}
+ goto st11;
+tr67:
+#line 298 "patchExprScanner.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 369 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(ATAN); }}
+ goto st11;
+tr98:
+#line 365 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(COS); }}
+ goto st11;
+tr115:
+#line 358 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(LOG); }}
+ goto st11;
+tr122:
+#line 374 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(MAG); }}
+ goto st11;
+tr129:
+#line 378 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(NEG); }}
+ goto st11;
+tr135:
+#line 377 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(POS); }}
+ goto st11;
+tr154:
+#line 364 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(SIN); }}
+ goto st11;
+tr170:
+#line 361 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(SQR); }}
+ goto st11;
+tr186:
+#line 366 "patchExprScanner.rl"
+ {te = p;p--;{ EMIT_TOKEN(TAN); }}
+ goto st11;
+tr192:
+#line 395 "patchExprScanner.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 870 "patchExprScanner.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 998 "patchExprScanner.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 1049 "patchExprScanner.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 298 "patchExprScanner.rl"
+ {act = 70;}
+ goto st23;
+tr72:
+#line 1 "NONE"
+ {te = p+1;}
+#line 400 "patchExprScanner.rl"
+ {act = 65;}
+ goto st23;
+tr78:
+#line 1 "NONE"
+ {te = p+1;}
+#line 368 "patchExprScanner.rl"
+ {act = 40;}
+ goto st23;
+tr80:
+#line 1 "NONE"
+ {te = p+1;}
+#line 367 "patchExprScanner.rl"
+ {act = 39;}
+ goto st23;
+tr84:
+#line 1 "NONE"
+ {te = p+1;}
+#line 370 "patchExprScanner.rl"
+ {act = 42;}
+ goto st23;
+tr89:
+#line 1 "NONE"
+ {te = p+1;}
+#line 386 "patchExprScanner.rl"
+ {act = 55;}
+ goto st23;
+tr92:
+#line 1 "NONE"
+ {te = p+1;}
+#line 393 "patchExprScanner.rl"
+ {act = 60;}
+ goto st23;
+tr96:
+#line 1 "NONE"
+ {te = p+1;}
+#line 363 "patchExprScanner.rl"
+ {act = 35;}
+ goto st23;
+tr99:
+#line 1 "NONE"
+ {te = p+1;}
+#line 372 "patchExprScanner.rl"
+ {act = 44;}
+ goto st23;
+tr106:
+#line 1 "NONE"
+ {te = p+1;}
+#line 355 "patchExprScanner.rl"
+ {act = 27;}
+ goto st23;
+tr108:
+#line 1 "NONE"
+ {te = p+1;}
+#line 357 "patchExprScanner.rl"
+ {act = 29;}
+ goto st23;
+tr112:
+#line 1 "NONE"
+ {te = p+1;}
+#line 402 "patchExprScanner.rl"
+ {act = 67;}
+ goto st23;
+tr117:
+#line 1 "NONE"
+ {te = p+1;}
+#line 359 "patchExprScanner.rl"
+ {act = 31;}
+ goto st23;
+tr121:
+#line 1 "NONE"
+ {te = p+1;}
+#line 385 "patchExprScanner.rl"
+ {act = 54;}
+ goto st23;
+tr125:
+#line 1 "NONE"
+ {te = p+1;}
+#line 375 "patchExprScanner.rl"
+ {act = 47;}
+ goto st23;
+tr126:
+#line 1 "NONE"
+ {te = p+1;}
+#line 384 "patchExprScanner.rl"
+ {act = 53;}
+ goto st23;
+tr130:
+#line 1 "NONE"
+ {te = p+1;}
+#line 380 "patchExprScanner.rl"
+ {act = 51;}
+ goto st23;
+tr131:
+#line 1 "NONE"
+ {te = p+1;}
+#line 354 "patchExprScanner.rl"
+ {act = 26;}
+ goto st23;
+tr134:
+#line 1 "NONE"
+ {te = p+1;}
+#line 360 "patchExprScanner.rl"
+ {act = 32;}
+ goto st23;
+tr136:
+#line 1 "NONE"
+ {te = p+1;}
+#line 379 "patchExprScanner.rl"
+ {act = 50;}
+ goto st23;
+tr144:
+#line 1 "NONE"
+ {te = p+1;}
+#line 356 "patchExprScanner.rl"
+ {act = 28;}
+ goto st23;
+tr145:
+#line 1 "NONE"
+ {te = p+1;}
+#line 390 "patchExprScanner.rl"
+ {act = 59;}
+ goto st23;
+tr153:
+#line 1 "NONE"
+ {te = p+1;}
+#line 381 "patchExprScanner.rl"
+ {act = 52;}
+ goto st23;
+tr155:
+#line 1 "NONE"
+ {te = p+1;}
+#line 371 "patchExprScanner.rl"
+ {act = 43;}
+ goto st23;
+tr168:
+#line 1 "NONE"
+ {te = p+1;}
+#line 397 "patchExprScanner.rl"
+ {act = 64;}
+ goto st23;
+tr171:
+#line 1 "NONE"
+ {te = p+1;}
+#line 362 "patchExprScanner.rl"
+ {act = 34;}
+ goto st23;
+tr172:
+#line 1 "NONE"
+ {te = p+1;}
+#line 387 "patchExprScanner.rl"
+ {act = 56;}
+ goto st23;
+tr180:
+#line 1 "NONE"
+ {te = p+1;}
+#line 396 "patchExprScanner.rl"
+ {act = 63;}
+ goto st23;
+tr187:
+#line 1 "NONE"
+ {te = p+1;}
+#line 373 "patchExprScanner.rl"
+ {act = 45;}
+ goto st23;
+tr195:
+#line 1 "NONE"
+ {te = p+1;}
+#line 404 "patchExprScanner.rl"
+ {act = 69;}
+ goto st23;
+tr197:
+#line 1 "NONE"
+ {te = p+1;}
+#line 401 "patchExprScanner.rl"
+ {act = 66;}
+ goto st23;
+tr202:
+#line 1 "NONE"
+ {te = p+1;}
+#line 394 "patchExprScanner.rl"
+ {act = 61;}
+ goto st23;
+tr215:
+#line 1 "NONE"
+ {te = p+1;}
+#line 388 "patchExprScanner.rl"
+ {act = 57;}
+ goto st23;
+tr217:
+#line 1 "NONE"
+ {te = p+1;}
+#line 389 "patchExprScanner.rl"
+ {act = 58;}
+ goto st23;
+st23:
+ if ( ++p == pe )
+ goto _test_eof23;
+case 23:
+#line 1304 "patchExprScanner.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 3071 "patchExprScanner.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 641 "patchExprScanner.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/patch/patchExprScanner.rl b/src/finiteVolume/expressions/patch/patchExprScanner.rl
new file mode 100644
index 0000000000..e26c621c3f
--- /dev/null
+++ b/src/finiteVolume/expressions/patch/patchExprScanner.rl
@@ -0,0 +1,664 @@
+/*--------------------------------*- 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 for patch expressions
+
+\*---------------------------------------------------------------------------*/
+
+#include "patchExprScanner.H"
+#include "patchExprDriver.H"
+#include "patchExprLemonParser.h"
+#include "patchExprParser.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 }
+
+#undef 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
+#error 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", FACE_CENTRE),
+
+ TOKEN_PAIR("point", POINT_EXPR), // Point value
+ TOKEN_PAIR("face", FACE_EXPR), // Face areaNormal
+
+ TOKEN_PAIR("faceToPoint", FACE_TO_POINT),
+ TOKEN_PAIR("pointToFace", POINT_TO_FACE),
+
+ TOKEN_PAIR("area", FACE_AREA),
+ 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::patchExpr::parseDriver& driver_,
+ const word& ident
+)
+{
+#if 0
+ // 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
+ }
+#endif
+
+ // Face variables
+ #ifdef TOK_SSCALAR_ID
+ {
+ #undef checkFieldToken
+ #define checkFieldToken(TokType, Type) \
+ if (driver_.isVariable(ident, false)) \
+ { \
+ 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);
+
+ // Not tested: checkFieldToken(TOK_SBOOL_ID, bool);
+ }
+ #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_PTENSOR_ID, tensor);
+ checkFieldToken(TOK_PTENSOR_ID, tensor);
+ checkFieldToken(TOK_PSYM_TENSOR_ID, symmTensor);
+ checkFieldToken(TOK_PSPH_TENSOR_ID, sphericalTensor);
+
+ // Not tested: checkFieldToken(TOK_PBOOL_ID, bool);
+ }
+ #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 patchExpr;
+ 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::patchExpr::scanner::~scanner()
+{
+ if (parser_)
+ {
+ delete parser_;
+ }
+}
+
+
+// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
+
+bool Foam::expressions::patchExpr::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::patchExpr::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::patchExpr::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;
+}
+
+
+// ************************************************************************* //