diff --git a/applications/tools/foamCalc/Make/files b/applications/tools/foamCalc/Make/files
new file mode 100644
index 0000000000..a2d961e851
--- /dev/null
+++ b/applications/tools/foamCalc/Make/files
@@ -0,0 +1,3 @@
+foamCalc.C
+
+EXE = $(FOAM_APPBIN)/foamCalc
diff --git a/applications/tools/foamCalc/Make/options b/applications/tools/foamCalc/Make/options
new file mode 100644
index 0000000000..18e6fe47af
--- /dev/null
+++ b/applications/tools/foamCalc/Make/options
@@ -0,0 +1,2 @@
+/* EXE_INC = */
+/* EXE_LIBS = */
diff --git a/applications/tools/foamCalc/foamCalc.C b/applications/tools/foamCalc/foamCalc.C
new file mode 100644
index 0000000000..f16886188f
--- /dev/null
+++ b/applications/tools/foamCalc/foamCalc.C
@@ -0,0 +1,164 @@
+/*---------------------------------------------------------------------------*\
+ ========= |
+ \\ / 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 .
+
+Application
+ foamCalc
+
+Group
+ grpTools
+
+Description
+ A simple expression calculator using OpenFOAM string evaluation.
+ Multiple arguments will be concatenated together.
+
+Usage
+ \b foamCalc [OPTION]
+
+ Options:
+ - \par -precision int
+ Output with specified precision
+
+ - \par -rules
+ Print parser rules and exit
+
+ - \par -tokens
+ Print token names and exit
+
+\*---------------------------------------------------------------------------*/
+
+#include "argList.H"
+#include "IOstreams.H"
+#include "exprString.H"
+#include "stringOps.H"
+#include "fieldExprParser.H"
+
+using namespace Foam;
+
+template
+void printInformation
+(
+ Ostream& os,
+ const word& name,
+ const bool printNames,
+ const bool printRules
+)
+{
+ if (printNames)
+ {
+ os << nl << "# Tokens for " << name << nl;
+ Parser::printTokenNames(os);
+ }
+
+ if (printRules)
+ {
+ os << nl << "# Rules for " << name << nl;
+ Parser::printRules(os);
+ }
+}
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+ argList::noBanner();
+ argList::noParallel();
+ argList::setAdvanced("case"); // Hide -case : has no meaning here
+
+ argList::addNote
+ (
+ "A simple expression calculator using OpenFOAM string evaluation.\n"
+ "Multiple arguments will be concatenated together."
+ );
+
+ argList::addBoolOption("rules", "Print parser rules and exit");
+ argList::addBoolOption("tokens", "Print token names and exit");
+ argList::addOption("precision", "int", "Output with specified precision");
+
+ // Flag arguments as optional so that -rules and -tokens works
+ argList::noMandatoryArgs();
+ argList::addArgument
+ (
+ "expression",
+ "The expression to evaluate"
+ );
+
+ argList args(argc, argv);
+
+ const bool printRules = args.found("rules");
+ const bool printNames = args.found("tokens");
+
+ if (printNames || printRules)
+ {
+ printInformation
+ (
+ Info,
+ "field",
+ printNames,
+ printRules
+ );
+
+ return 0;
+ }
+
+ {
+ const int prec = args.lookupOrDefault("precision", 0u);
+ if (prec > 0)
+ {
+ IOstream::defaultPrecision(prec);
+ Sout.precision(prec);
+ }
+ }
+
+ std::string expr;
+
+ for (int argi=1; argi < args.size(); ++argi)
+ {
+ if (argi > 1) expr += ' ';
+ expr += args[argi];
+ }
+
+ // Don't bother stripping C/C++, but do allow empty variables
+ stringOps::inplaceExpand(expr, true);
+ stringOps::inplaceTrim(expr);
+
+ if (expr.empty())
+ {
+ InfoErr
+ << "Error: no expression specified." << nl
+ << "See '" << args.executable() << " -help' for usage" << nl
+ << nl;
+
+ return 1;
+ }
+
+ Info<< stringOps::evaluate(expr).c_str() << nl;
+
+ return 0;
+}
+
+
+// ************************************************************************* //