diff --git a/applications/test/dictionary/Make/files b/applications/test/dictionary/Make/files
index 759804fcfa6cf2737cd9599f8aeba508687cf353..148f5fb1c94c8ff332eed2edec36e2771eb65e02 100644
--- a/applications/test/dictionary/Make/files
+++ b/applications/test/dictionary/Make/files
@@ -1,4 +1,7 @@
-calcEntry/calcEntry.C
 dictionaryTest.C
 
+calcEntry/calcEntry.C
+calcEntry/calcEntryParser.cpp
+calcEntry/calcEntryScanner.cpp
+
 EXE = $(FOAM_USER_APPBIN)/dictionaryTest
diff --git a/applications/test/dictionary/calcEntry/CocoParserErrors.H b/applications/test/dictionary/calcEntry/CocoParserErrors.H
new file mode 100644
index 0000000000000000000000000000000000000000..e4c819e302448b508c62b22a1176fda353acc03d
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/CocoParserErrors.H
@@ -0,0 +1,145 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2009-2009 OpenCFD Ltd.
+     \\/     M anipulation  |
+-------------------------------------------------------------------------------
+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 2 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, write to the Free Software Foundation,
+    Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Class
+    Foam::CocoParserErrors
+
+Description
+    Templated class to shadow the error handling for Coco/R parsers
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef CocoParserErrors_H
+#define CocoParserErrors_H
+
+#include "error.H"
+#include "wchar.H"
+
+// avoid confusion about which Warning is meant
+#undef  WarningIn
+#define WarningIn(fn) Foam::Warning(fn, __FILE__, __LINE__)
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                      Class CocoParserErrors Declaration
+\*---------------------------------------------------------------------------*/
+
+template<class BaseClass>
+class CocoParserErrors
+:
+    public BaseClass
+{
+    // Private data
+
+        //- The name issued in warnings and errors
+        word   name_;
+
+public:
+
+    // Constructors
+
+        //- Construct with given name
+        CocoParserErrors(const word& name)
+        :
+            BaseClass(),
+            name_(name)
+        {}
+
+
+    //- Destructor
+    virtual ~CocoParserErrors()
+    {}
+
+
+    // Member functions
+
+        //- Return the name issued for warnings
+        virtual const word& name() const
+        {
+            return name_;
+        }
+
+        //- Return the name issued for warnings
+        virtual word& name()
+        {
+            return name_;
+        }
+
+
+    // Error Handling
+
+        //- Handle a general warning 'msg'
+        virtual void Warning(const wchar_t* msg)
+        {
+            WarningIn(name_)
+                << msg << endl;
+        }
+
+        //- Handle a general warning 'msg'
+        virtual void Warning(int line, int col, const wchar_t* msg)
+        {
+            WarningIn(name_)
+                <<"line " << line << " col " << col << ": "
+                << msg << endl;
+        }
+
+        //- Handle general error 'msg' (eg, a semantic error)
+        virtual void Error(int line, int col, const wchar_t* msg)
+        {
+            FatalErrorIn(name_)
+                << "line " << line << " col " << col <<": " << msg << endl
+                << exit(FatalError);
+        }
+
+        //- Handle general error 'msg' (eg, a semantic error)
+        virtual void Error(const wchar_t* msg)
+        {
+            FatalErrorIn(name_)
+                << msg << endl
+                << exit(FatalError);
+        }
+
+        //- Handle a general exception 'msg'
+        virtual void Exception(const wchar_t* msg)
+        {
+            this->Error(msg);
+        }
+
+};
+
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/applications/test/dictionary/calcEntry/SimpleCalc.atg b/applications/test/dictionary/calcEntry/SimpleCalc.atg
new file mode 100644
index 0000000000000000000000000000000000000000..cdc84cd0c9009a47a6425f6cf5a11ea225e74517
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/SimpleCalc.atg
@@ -0,0 +1,225 @@
+/*-------------------------------------------------------------------------
+ compile with:
+ Coco \
+    -frames $WM_THIRD_PARTY_DIR/coco-r \
+    -prefix calcEntry \
+    -namespace Foam::functionEntries::calcEntryInternal \
+    SimpleCalc.atg
+-------------------------------------------------------------------------*/
+
+#include "dictionary.H"
+#include "scalar.H"
+#include "error.H"
+#include "wchar.H"
+
+
+COMPILER SimpleCalc
+    // Simple four function calculator for OpenFOAM dictionaries
+
+    //! with debug
+    static const int debug = 0;
+
+    //! The parent dictionary
+    mutable dictionary* dict_;
+
+    //! The calculation result
+    scalar val;
+
+    //! token -> scalar
+    scalar getScalar() const
+    {
+        return coco_string_toDouble(t->val);
+    }
+
+    //! token -> string
+    std::string getString() const
+    {
+        char* str = coco_string_create_char(t->val);
+        std::string s(str);
+        coco_string_delete(str);
+        return s;
+    }
+
+
+    //! attach a dictionary
+    void dict(const dictionary& dict) const
+    {
+        dict_ = const_cast<dictionary*>(&dict);
+    }
+
+
+    //! lookup dictionary entry
+    scalar getDictLookup() const
+    {
+        scalar dictValue = 0;
+
+        if (!dict_)
+        {
+            FatalErrorIn
+            (
+                "SimpleCalc::getDictEntry() const"
+            )   << "No dictionary attached!"
+                << exit(FatalError);
+
+            return 0;
+        }
+
+        char* chars = coco_string_create_char
+        (
+            t->val,
+            1,
+            (coco_string_length(t->val) - 1)
+        );
+        word keyword(chars);
+        coco_string_delete(chars);
+
+        if (debug)
+        {
+            Info<<"lookup: " << keyword << nl;
+        }
+
+        entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
+        if (entryPtr && !entryPtr->isDict())
+        {
+            entryPtr->stream() >> dictValue;
+        }
+        else
+        {
+            FatalErrorIn
+            (
+                "SimpleCalc::getDictEntry() const"
+            )   << "keyword " << keyword << " is undefined in dictionary "
+                << exit(FatalError);
+        }
+
+
+        return dictValue;
+    }
+
+    scalar Result() const
+    {
+        return val;
+    }
+
+
+// * * * * * * * * * * * * * * *  CHARACTERS * * * * * * * * * * * * * * * * //
+
+CHARACTERS
+    letter    = 'A'..'Z' + 'a'..'z'.
+    qualifier = '_' + ':'.
+    dollar    = '$'.
+    digit     = "0123456789".
+    sign      = '+' + '-'.
+    cr        = '\r'.
+    lf        = '\n'.
+    tab       = '\t'.
+    stringCh  = ANY - '"' - '\\' - cr - lf.
+    printable = '\u0020' .. '\u007e'.
+
+
+// * * * * * * * * * * * * * * * *  TOKENS * * * * * * * * * * * * * * * * * //
+
+TOKENS
+
+// identifier
+ident  =
+    letter { letter | digit | qualifier }.
+
+// string
+string =
+    '"' { stringCh | '\\' printable } '"'.
+
+// dictionary lookup identifier
+// starts with '$' and otherwise limited to a normal indentifier
+variable  =
+    dollar letter { letter | digit | qualifier }.
+
+// floating point and integer numbers
+number  =
+    [sign] ('.' digit { digit } ) | ( digit { digit } [ '.' { digit } ])
+    [ ('E' | 'e') [sign] digit { digit } ].
+
+
+// * * * * * * * * * * *  PRAGMAS / COMMENTS / IGNORE  * * * * * * * * * * * //
+
+COMMENTS FROM "/*" TO "*/" NESTED
+COMMENTS FROM "//" TO lf
+
+// ignore unprintables
+IGNORE  ANY - printable
+
+
+// * * * * * * * * * * * * * * *  PRODUCTIONS  * * * * * * * * * * * * * * * //
+
+PRODUCTIONS
+
+SimpleCalc                      (. val = 0;
+                                   if (debug){Info<<"start val"<< nl;}
+                                 .)
+=
+  ( '{' Expr<val> '}' | Expr<val> )
+  EOF
+.
+
+
+/*---------------------------------------------------------------------------*/
+
+Expr<scalar& val>               (. scalar val2 = 0;
+                                   if (debug) {Info<<"Expr:"<< val<< nl;}
+                                 .)
+=
+  Term<val>
+  {
+      "+" Term<val2>            (. if (debug) {Info<<"+Term:"<<val2 <<nl;}
+                                   val += val2;
+                                   if (debug) {Info<<"="<< val << nl;}
+                                 .)
+    | "-" Term<val2>            (. if (debug) {Info<<"-Term:"<<val2 <<nl;}
+                                   val -= val2;
+                                   if (debug) {Info<<"="<< val << nl;}
+                                 .)
+  }
+.
+
+
+/*---------------------------------------------------------------------------*/
+
+Term<scalar& val>               (. scalar val2 = 0;
+                                   if (debug) {Info<<"Term:"<< val<< nl;}
+                                 .)
+=
+  Factor<val>
+  {
+     "*" Factor<val2>           (. if (debug) {Info<<"*Factor:"<<val2 << nl;}
+                                   val *= val2;
+                                   if (debug) {Info<<"="<< val << nl; }
+                                 .)
+  |  "/" Factor<val2>           (. if (debug) {Info<<"/Factor:"<<val2 << nl;}
+                                   val /= val2;
+                                   if (debug) {Info<<"="<< val << nl; }
+                                 .)
+  }
+.
+
+
+/*---------------------------------------------------------------------------*/
+Factor<scalar& val>
+=
+    variable                    (. val = getDictLookup();
+                                   if (debug) {Info<<"lookup:"<<val<<nl;}
+                                 .)
+  | number                      (. val = getScalar();
+                                   if (debug) {Info<<"got num:"<<val<<nl;}
+                                 .)
+  | '-' '(' Expr<val> ')'       (. val = -val;
+                                   if (debug) {Info<<"inv:"<<val<<nl;}
+                                 .)
+  | '(' Expr<val> ')'           (. if (debug){Info<<"got Expr:"<<val<<nl;} .)
+.
+
+
+/*---------------------------------------------------------------------------*/
+
+END SimpleCalc.
+
+// ************************************************************************* //
diff --git a/applications/test/dictionary/calcEntry/build.sh b/applications/test/dictionary/calcEntry/build.sh
new file mode 100755
index 0000000000000000000000000000000000000000..4bbaf0eeaf25462e491e09641e6a297427e1698a
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/build.sh
@@ -0,0 +1,11 @@
+#/bin/sh
+cd ${0%/*} || exit 1    # run from this directory
+
+# this will have to do until we make a makefile rule
+
+Coco \
+    -frames $WM_THIRD_PARTY_DIR/coco-r \
+    -prefix calcEntry \
+    -namespace Foam::functionEntries::calcEntryInternal \
+    SimpleCalc.atg
+
diff --git a/applications/test/dictionary/calcEntry/calcEntry.C b/applications/test/dictionary/calcEntry/calcEntry.C
index 76738dd9097bca706d99910afbb8d920537a6534..ccfc68b7027ea5e6f79251784fbc122a18984019 100644
--- a/applications/test/dictionary/calcEntry/calcEntry.C
+++ b/applications/test/dictionary/calcEntry/calcEntry.C
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2009-2009 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -30,6 +30,10 @@ License
 #include "OStringStream.H"
 #include "addToMemberFunctionSelectionTable.H"
 
+#include "ISstream.H"
+#include "CocoParserErrors.H"
+#include "calcEntryParser.h"
+
 // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
 
 namespace Foam
@@ -56,14 +60,121 @@ bool Foam::functionEntries::calcEntry::execute
 (
     const dictionary& parentDict,
     primitiveEntry& entry,
-    Istream& is
+    Istream& istr
 )
 {
-    dictionary args(parentDict, is);
-    OStringStream resultStream;
-    resultStream
-        << (args.lookup("x")[0].number() + args.lookup("y")[0].number());
-    entry.read(parentDict, IStringStream(resultStream.str())());
+    static const int maxLen = 1024;
+    static const int errLen = 80; // truncate error message for readability
+    static char buf[maxLen];
+
+    ISstream& is = dynamicCast<ISstream>(istr);
+
+    // get the { ... } argument without the enclosing brace brackets
+    //
+    // THIS NEEDS REWORKING (LATER) ...
+
+    char c = 0;
+
+    if (!is.read(c).good() || c != token::BEGIN_BLOCK)
+    {
+        is.setBad();
+        FatalIOErrorIn("functionEntries::calcEntry::execute()", is)
+            << "Expected a '" << token::BEGIN_BLOCK
+            << "', found '" << c << "'" << exit(FatalIOError);
+
+        return false;
+    }
+
+    register int nChar = 0;
+    buf[nChar++] = token::BEGIN_BLOCK;
+    int listDepth = 1;       // already saw the first '{'
+
+    while (is.get(c).good())
+    {
+        buf[nChar++] = c;
+        if (nChar == maxLen)
+        {
+            buf[errLen] = '\0';
+
+            FatalIOErrorIn("functionEntries::calcEntry::execute()", is)
+                << "argument \"" << buf << "...\"\n"
+                << "    is too long (max. " << maxLen << " characters)"
+                << exit(FatalIOError);
+
+            return false;
+        }
+
+        // handle nested blocks, even if we don't know what they'd
+        // be useful for
+        if (c == token::BEGIN_BLOCK)
+        {
+            ++listDepth;
+        }
+        else if (c == token::END_BLOCK)
+        {
+            if (--listDepth == 0)
+            {
+                // done reading - overwrite the final '}'
+                // --nChar;
+                break;
+            }
+        }
+    }
+
+    buf[nChar] = '\0';
+
+
+    // emit some info
+    Info<< "grabbed " << nChar << " characters:" << nl
+        << "----------\n"
+        << buf << nl
+        << "----------\n"
+        << nl;
+
+
+    // define parser error handler
+    CocoParserErrors<calcEntryInternal::Errors>
+        myErrorHandler("calcEntry::Parser--");
+
+    calcEntryInternal::Scanner scanner(buf, nChar);
+    calcEntryInternal::Parser  parser(&scanner, &myErrorHandler);
+
+    // Attach dictionary context
+    parser.dict(parentDict);
+
+    parser.Parse();
+
+//    Info<<"got: " << parser.Result() << endl;
+
+    tokenList tokens(2);
+    tokens[0] = parser.Result();
+    tokens[1] = token::END_STATEMENT;
+
+//     Info<<"tokens[0] = " << tokens[0].info() <<nl;
+//     Info<<"tokens[1] = " << tokens[1].info() <<nl;
+//
+//     {
+//     const tokenList& toks = entry;
+//
+//     forAll(toks, tokI)
+//     {
+//         Info<< tokI <<":= " << toks[tokI].info() << endl;
+//     }
+//     }
+
+    ITstream its("ParserResult", tokens);
+    entry.read(parentDict, its);
+//    Info<< "size: " << entry.size() << endl;
+//    entry = newente;
+//    entry.print(Info);
+
+///     const tokenList& toks = entry;
+///
+///     forAll(toks, tokI)
+///     {
+///         Info<< tokI <<":= " << toks[tokI].info() << endl;
+///     }
+///
     return true;
 }
 
diff --git a/applications/test/dictionary/calcEntry/calcEntry.H b/applications/test/dictionary/calcEntry/calcEntry.H
index 119f15564375fa3bb2c31ab1b1c79014745328a9..4f579bd4f29614015c308f0ca64f20e25daf3bf3 100644
--- a/applications/test/dictionary/calcEntry/calcEntry.H
+++ b/applications/test/dictionary/calcEntry/calcEntry.H
@@ -2,7 +2,7 @@
   =========                 |
   \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
    \\    /   O peration     |
-    \\  /    A nd           | Copyright (C) 1991-2009 OpenCFD Ltd.
+    \\  /    A nd           | Copyright (C) 2009-2009 OpenCFD Ltd.
      \\/     M anipulation  |
 -------------------------------------------------------------------------------
 License
@@ -26,6 +26,8 @@ Class
     Foam::functionEntries::calcEntry
 
 Description
+    This dictionary function entry may or may not do anything particularly
+    useful - depending upon what is currently being used to test.
 
 SourceFiles
     calcEntry.C
@@ -45,7 +47,7 @@ namespace functionEntries
 {
 
 /*---------------------------------------------------------------------------*\
-                           Class calcEntry Declaration
+                          Class calcEntry Declaration
 \*---------------------------------------------------------------------------*/
 
 class calcEntry
@@ -64,7 +66,7 @@ class calcEntry
 public:
 
     //- Runtime type information
-    ClassName("calc");
+    ClassName("test");
 
 
     // Member Functions
diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.cpp b/applications/test/dictionary/calcEntry/calcEntryParser.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..412a00c52f5f97cdaa2ed5b2b3b4d8e0d00a8448
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/calcEntryParser.cpp
@@ -0,0 +1,324 @@
+
+
+#include <wchar.h>
+#include "calcEntryParser.h"
+
+
+namespace Foam {
+namespace functionEntries {
+namespace calcEntryInternal {
+
+
+// ----------------------------------------------------------------------------
+// Parser Implementation
+// ----------------------------------------------------------------------------
+
+void Parser::SynErr(int n) {
+	if (errDist >= minErrDist) errors->SynErr(la->line, la->col, n);
+	errDist = 0;
+}
+
+
+void Parser::SemErr(const wchar_t* msg) {
+	if (errDist >= minErrDist) errors->Error(t->line, t->col, msg);
+	errDist = 0;
+}
+
+
+void Parser::Get() {
+	for (;;) {
+		t = la;
+		la = scanner->Scan();
+		if (la->kind <= maxT) {
+			++errDist;
+			break;
+		}
+
+		if (dummyToken != t) {
+			dummyToken->kind = t->kind;
+			dummyToken->pos = t->pos;
+			dummyToken->col = t->col;
+			dummyToken->line = t->line;
+			dummyToken->next = NULL;
+			coco_string_delete(dummyToken->val);
+			dummyToken->val = coco_string_create(t->val);
+			t = dummyToken;
+		}
+		la = t;
+	}
+}
+
+
+void Parser::Expect(int n) {
+	if (la->kind == n) {
+		Get();
+	}
+	else {
+		SynErr(n);
+	}
+}
+
+
+void Parser::ExpectWeak(int n, int follow) {
+	if (la->kind == n) {
+		Get();
+	}
+	else {
+		SynErr(n);
+		while (!StartOf(follow)) {
+			Get();
+		}
+	}
+}
+
+
+bool Parser::WeakSeparator(int n, int syFol, int repFol) {
+	if (la->kind == n) {
+		Get();
+		return true;
+	}
+	else if (StartOf(repFol)) {
+		return false;
+	}
+	else {
+		SynErr(n);
+		while (!(StartOf(syFol) || StartOf(repFol) || StartOf(0))) {
+			Get();
+		}
+		return StartOf(syFol);
+	}
+}
+
+
+void Parser::SimpleCalc() {
+		val = 0;
+		if (debug){Info<<"start val"<< nl;}
+		
+		if (la->kind == 5) {
+			Get();
+			Expr(val);
+			Expect(6);
+		} else if (StartOf(1)) {
+			Expr(val);
+		} else SynErr(14);
+		Expect(0);
+}
+
+void Parser::Expr(scalar& val) {
+		scalar val2 = 0;
+		if (debug) {Info<<"Expr:"<< val<< nl;}
+		
+		Term(val);
+		while (la->kind == 7 || la->kind == 8) {
+			if (la->kind == 7) {
+				Get();
+				Term(val2);
+				if (debug) {Info<<"+Term:"<<val2 <<nl;}
+				val += val2;
+				if (debug) {Info<<"="<< val << nl;}
+				
+			} else {
+				Get();
+				Term(val2);
+				if (debug) {Info<<"-Term:"<<val2 <<nl;}
+				val -= val2;
+				if (debug) {Info<<"="<< val << nl;}
+				
+			}
+		}
+}
+
+void Parser::Term(scalar& val) {
+		scalar val2 = 0;
+		if (debug) {Info<<"Term:"<< val<< nl;}
+		
+		Factor(val);
+		while (la->kind == 9 || la->kind == 10) {
+			if (la->kind == 9) {
+				Get();
+				Factor(val2);
+				if (debug) {Info<<"*Factor:"<<val2 << nl;}
+				val *= val2;
+				if (debug) {Info<<"="<< val << nl; }
+				
+			} else {
+				Get();
+				Factor(val2);
+				if (debug) {Info<<"/Factor:"<<val2 << nl;}
+				val /= val2;
+				if (debug) {Info<<"="<< val << nl; }
+				
+			}
+		}
+}
+
+void Parser::Factor(scalar& val) {
+		if (la->kind == 3) {
+			Get();
+			val = getDictLookup();
+			if (debug) {Info<<"lookup:"<<val<<nl;}
+			
+		} else if (la->kind == 4) {
+			Get();
+			val = getScalar();
+			if (debug) {Info<<"got num:"<<val<<nl;}
+			
+		} else if (la->kind == 8) {
+			Get();
+			Expect(11);
+			Expr(val);
+			Expect(12);
+			val = -val;
+			if (debug) {Info<<"inv:"<<val<<nl;}
+			
+		} else if (la->kind == 11) {
+			Get();
+			Expr(val);
+			Expect(12);
+			if (debug){Info<<"got Expr:"<<val<<nl;} 
+		} else SynErr(15);
+}
+
+
+
+void Parser::Parse() {
+	t = NULL;
+	if (dummyToken) {    // safety: someone might call Parse() twice
+		delete dummyToken;
+	}
+	la = dummyToken = new Token();
+	la->val = coco_string_create(L"Dummy Token");
+	Get();
+	SimpleCalc();
+
+	Expect(0);
+}
+
+
+Parser::Parser(Scanner* scan, Errors* err)
+:
+	dummyToken(NULL),
+	deleteErrorsDestruct_(!err),
+	minErrDist(2),
+	errDist(minErrDist),
+	scanner(scan),
+	errors(err),
+	t(NULL),
+	la(NULL)
+{
+	maxT = 13;
+
+	if (!errors) {   // add in default error handling
+		errors = new Errors();
+	}
+}
+
+
+bool Parser::StartOf(int s) {
+	const bool T = true;
+	const bool x = false;
+
+	static bool set[2][15] = {
+		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
+		{x,x,x,T, T,x,x,x, T,x,x,T, x,x,x}
+	};
+
+
+
+	return set[s][la->kind];
+}
+
+
+Parser::~Parser() {
+	if (deleteErrorsDestruct_) {    // delete default error handling
+		delete errors;
+	}
+	delete dummyToken;
+}
+
+
+// ----------------------------------------------------------------------------
+// Errors Implementation
+// ----------------------------------------------------------------------------
+
+Errors::Errors()
+:
+	count(0)
+{}
+
+
+Errors::~Errors()
+{}
+
+
+void Errors::clear() {
+	count = 0;
+}
+
+
+wchar_t* Errors::strerror(int n)
+{
+	wchar_t* s;
+	switch (n) {
+			case 0: s = coco_string_create(L"EOF expected"); break;
+			case 1: s = coco_string_create(L"ident expected"); break;
+			case 2: s = coco_string_create(L"string expected"); break;
+			case 3: s = coco_string_create(L"variable expected"); break;
+			case 4: s = coco_string_create(L"number expected"); break;
+			case 5: s = coco_string_create(L"\"{\" expected"); break;
+			case 6: s = coco_string_create(L"\"}\" expected"); break;
+			case 7: s = coco_string_create(L"\"+\" expected"); break;
+			case 8: s = coco_string_create(L"\"-\" expected"); break;
+			case 9: s = coco_string_create(L"\"*\" expected"); break;
+			case 10: s = coco_string_create(L"\"/\" expected"); break;
+			case 11: s = coco_string_create(L"\"(\" expected"); break;
+			case 12: s = coco_string_create(L"\")\" expected"); break;
+			case 13: s = coco_string_create(L"??? expected"); break;
+			case 14: s = coco_string_create(L"invalid SimpleCalc"); break;
+			case 15: s = coco_string_create(L"invalid Factor"); break;
+
+		default:
+		{
+			wchar_t format[20];
+			coco_swprintf(format, 20, L"error %d", n);
+			s = coco_string_create(format);
+		}
+		break;
+	}
+	return s;
+}
+
+
+void Errors::Warning(const wchar_t* msg) {
+	wprintf(L"%ls\n", msg);
+}
+
+
+void Errors::Warning(int line, int col, const wchar_t* msg) {
+	wprintf(L"-- line %d col %d: %ls\n", line, col, msg);
+}
+
+
+void Errors::Error(int line, int col, const wchar_t* msg) {
+	wprintf(L"-- line %d col %d: %ls\n", line, col, msg);
+	count++;
+}
+
+
+void Errors::SynErr(int line, int col, int n) {
+	wchar_t* msg = this->strerror(n);
+	this->Error(line, col, msg);
+	coco_string_delete(msg);
+}
+
+
+void Errors::Exception(const wchar_t* msg) {
+	wprintf(L"%ls", msg);
+	::exit(1);
+}
+
+} // namespace
+} // namespace
+} // namespace
+
+
diff --git a/applications/test/dictionary/calcEntry/calcEntryParser.h b/applications/test/dictionary/calcEntry/calcEntryParser.h
new file mode 100644
index 0000000000000000000000000000000000000000..d3da4d05fc487a09e18e9b80a4196796737d5130
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/calcEntryParser.h
@@ -0,0 +1,192 @@
+
+
+#ifndef COCO_calcEntryPARSER_H__
+#define COCO_calcEntryPARSER_H__
+
+#include "dictionary.H"
+#include "scalar.H"
+#include "error.H"
+#include "wchar.H"
+
+
+#include "calcEntryScanner.h"
+
+namespace Foam {
+namespace functionEntries {
+namespace calcEntryInternal {
+
+
+//! Parser error handing
+class Errors {
+public:
+	int count;      //!< The number of errors detected
+
+	//! Allocate and return a string describing the given error code.
+	/** It is the responsibility of the caller to free this string,
+	 *  eg, with coco_string_delete()
+	 */
+	static wchar_t* strerror(int n);
+
+	Errors();               //!< Construct null - start with no errors
+	virtual ~Errors();      //!< Destructor
+	virtual void clear();   //!< Clear the error count
+
+	//! Handle a general warning 'msg'
+	virtual void Warning(const wchar_t* msg);
+	//! Handle a general warning 'msg'
+	virtual void Warning(int line, int col, const wchar_t* msg);
+	//! Handle general error 'msg' (eg, a semantic error)
+	virtual void Error(int line, int col, const wchar_t* msg);
+	//! Handle syntax error 'n', uses strerror for the message, calls Error()
+	virtual void SynErr(int line, int col, int n);
+	//! Handle a general exception 'msg'
+	virtual void Exception(const wchar_t* msg);
+
+}; // Errors
+
+
+//! A Coco/R Parser
+class Parser {
+private:
+	enum {
+		_EOF=0,
+		_ident=1,
+		_string=2,
+		_variable=3,
+		_number=4,
+	};
+	int maxT;
+
+	Token *dummyToken;
+	bool deleteErrorsDestruct_; //!< delete the 'errors' member in destructor
+	int  minErrDist;
+	int  errDist;
+
+	void SynErr(int n);         //!< Handle syntax error 'n'
+	void Get();
+	void Expect(int n);
+	bool StartOf(int s);
+	void ExpectWeak(int n, int follow);
+	bool WeakSeparator(int n, int syFol, int repFol);
+
+public:
+	Scanner *scanner;
+	Errors  *errors;
+
+	Token *t;                   //!< last recognized token
+	Token *la;                  //!< lookahead token
+
+static const int debug = 0;
+
+    //! The parent dictionary
+    mutable dictionary* dict_;
+
+    //! The calculation result
+    scalar val;
+
+    //! token -> scalar
+    scalar getScalar() const
+    {
+        return coco_string_toDouble(t->val);
+    }
+
+    //! token -> string
+    std::string getString() const
+    {
+        char* str = coco_string_create_char(t->val);
+        std::string s(str);
+        coco_string_delete(str);
+        return s;
+    }
+
+
+    //! attach a dictionary
+    void dict(const dictionary& dict) const
+    {
+        dict_ = const_cast<dictionary*>(&dict);
+    }
+
+
+    //! lookup dictionary entry
+    scalar getDictLookup() const
+    {
+        scalar dictValue = 0;
+
+        if (!dict_)
+        {
+            FatalErrorIn
+            (
+                "SimpleCalc::getDictEntry() const"
+            )   << "No dictionary attached!"
+                << exit(FatalError);
+
+            return 0;
+        }
+
+        char* chars = coco_string_create_char
+        (
+            t->val,
+            1,
+            (coco_string_length(t->val) - 1)
+        );
+        word keyword(chars);
+        coco_string_delete(chars);
+
+        if (debug)
+        {
+            Info<<"lookup: " << keyword << nl;
+        }
+
+        entry* entryPtr = dict_->lookupEntryPtr(keyword, true, false);
+        if (entryPtr && !entryPtr->isDict())
+        {
+            entryPtr->stream() >> dictValue;
+        }
+        else
+        {
+            FatalErrorIn
+            (
+                "SimpleCalc::getDictEntry() const"
+            )   << "keyword " << keyword << " is undefined in dictionary "
+                << exit(FatalError);
+        }
+
+
+        return dictValue;
+    }
+
+    scalar Result() const
+    {
+        return val;
+    }
+
+
+// * * * * * * * * * * * * * * *  CHARACTERS * * * * * * * * * * * * * * * * //
+
+
+
+	//! Construct for the specified scanner
+	/**
+	 *  Use the default error handling, or optionally provide an error
+	 *  handler, which will not be deleted upon destruction.
+	 */
+	Parser(Scanner* scan, Errors* err = 0);
+	~Parser();      //!< Destructor - cleanup errors and dummyToken
+	void SemErr(const wchar_t* msg);    //!< Handle semantic error
+
+	void SimpleCalc();
+	void Expr(scalar& val);
+	void Term(scalar& val);
+	void Factor(scalar& val);
+
+	void Parse();                       //!< Execute the parse operation
+
+}; // end Parser
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif // COCO_calcEntryPARSER_H__
+
diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.cpp b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..86a92d32333c0b39ff53f707cb1f0a0026a1e5ab
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/calcEntryScanner.cpp
@@ -0,0 +1,825 @@
+
+
+#include <memory.h>
+#include <string.h>
+#include "calcEntryScanner.h"
+
+namespace Foam {
+namespace functionEntries {
+namespace calcEntryInternal {
+
+
+// * * * * * * * * * *  Wide Character String Routines * * * * * * * * * * * //
+
+// string handling, wide character
+
+wchar_t* coco_string_create(const wchar_t* str) {
+	int len = coco_string_length(str);
+	wchar_t* dest = new wchar_t[len + 1];
+	if (len) {
+		wcsncpy(dest, str, len);
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+wchar_t* coco_string_create(const wchar_t* str, int index, int length) {
+	int len = coco_string_length(str);
+	if (len) {
+		len = length;
+	}
+	wchar_t* dest = new wchar_t[len + 1];
+	if (len) {
+		wcsncpy(dest, &(str[index]), len);
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+wchar_t* coco_string_create_upper(const wchar_t* str) {
+	if (!str) { return NULL; }
+	return coco_string_create_upper(str, 0, wcslen(str));
+}
+
+
+wchar_t* coco_string_create_upper(const wchar_t* str, int index, int len) {
+	if (!str) { return NULL; }
+	wchar_t* dest = new wchar_t[len + 1];
+
+	for (int i = 0; i < len; i++) {
+		const wchar_t ch = str[index + i];
+		if ((L'a' <= ch) && (ch <= L'z')) {
+			dest[i] = ch + (L'A' - L'a');
+		}
+		else {
+			dest[i] = ch;
+		}
+	}
+	dest[len] = L'\0';
+	return dest;
+}
+
+
+wchar_t* coco_string_create_lower(const wchar_t* str) {
+	if (!str) { return NULL; }
+	return coco_string_create_lower(str, 0, wcslen(str));
+}
+
+
+wchar_t* coco_string_create_lower(const wchar_t* str, int index, int len) {
+	if (!str) { return NULL; }
+	wchar_t* dest = new wchar_t[len + 1];
+
+	for (int i = 0; i < len; i++) {
+		const wchar_t ch = str[index + i];
+		if ((L'A' <= ch) && (ch <= L'Z')) {
+			dest[i] = ch - (L'A' - L'a');
+		}
+		else {
+			dest[i] = ch;
+		}
+	}
+	dest[len] = L'\0';
+	return dest;
+}
+
+
+wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2) {
+	int str1Len = coco_string_length(str1);
+	int str2Len = coco_string_length(str2);
+
+	wchar_t* dest = new wchar_t[str1Len + str2Len + 1];
+
+	if (str1Len) { wcscpy(dest, str1); }
+	if (str2Len) { wcscpy(dest + str1Len, str2); }
+
+	dest[str1Len + str2Len] = 0;
+	return dest;
+}
+
+wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t ch) {
+	int len = coco_string_length(str1);
+	wchar_t* dest = new wchar_t[len + 2];
+	wcsncpy(dest, str1, len);   // or use if (len) { wcscpy(dest, str1); }
+	dest[len] = ch;
+	dest[len + 1] = 0;
+	return dest;
+}
+
+void coco_string_delete(wchar_t* &str) {
+	delete [] str;
+	str = NULL;
+}
+
+int coco_string_length(const wchar_t* str) {
+	return str ? wcslen(str) : 0;
+}
+
+bool coco_string_endswith(const wchar_t* str, const wchar_t* endstr) {
+	int strLen = wcslen(str);
+	int endLen = wcslen(endstr);
+	return (endLen <= strLen) && (wcscmp(str + strLen - endLen, endstr) == 0);
+}
+
+int coco_string_indexof(const wchar_t* str, const wchar_t ch) {
+	const wchar_t* fnd = wcschr(str, ch);
+	return fnd ? (fnd - str) : -1;
+}
+
+int coco_string_lastindexof(const wchar_t* str, const wchar_t ch) {
+	const wchar_t* fnd = wcsrchr(str, ch);
+	return fnd ? (fnd - str) : -1;
+}
+
+void coco_string_merge(wchar_t* &dest, const wchar_t* str) {
+	if (!str) { return; }
+	wchar_t* newstr = coco_string_create_append(dest, str);
+	delete [] dest;
+	dest = newstr;
+}
+
+bool coco_string_equal(const wchar_t* str1, const wchar_t* str2) {
+	return wcscmp(str1, str2) == 0;
+}
+
+int coco_string_compareto(const wchar_t* str1, const wchar_t* str2) {
+	return wcscmp(str1, str2);
+}
+
+int coco_string_hash(const wchar_t* str) {
+	int h = 0;
+	if (!str) { return 0; }
+	while (*str != 0) {
+		h = (h * 7) ^ *str;
+		++str;
+	}
+	if (h < 0) { h = -h; }
+	return h;
+}
+
+
+double coco_string_toDouble(const wchar_t* str)
+{
+	return str ? wcstod(str, NULL) : 0;
+}
+
+float coco_string_toFloat(const wchar_t* str)
+{
+	return str ? wcstof(str, NULL) : 0;
+}
+
+
+
+//
+// string handling, byte character
+//
+
+wchar_t* coco_string_create(const char* str) {
+	int len = str ? strlen(str) : 0;
+	wchar_t* dest = new wchar_t[len + 1];
+	for (int i = 0; i < len; ++i) {
+		dest[i] = (wchar_t) str[i];
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+wchar_t* coco_string_create(const char* str, int index, int length) {
+	int len = str ? length : 0;
+	wchar_t* dest = new wchar_t[len + 1];
+	for (int i = 0; i < len; ++i) {
+		dest[i] = (wchar_t) str[index + i];
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+
+char* coco_string_create_char(const wchar_t* str) {
+	int len = coco_string_length(str);
+	char *dest = new char[len + 1];
+	for (int i = 0; i < len; ++i)
+	{
+		dest[i] = (char) str[i];
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+char* coco_string_create_char(const wchar_t* str, int index, int length) {
+	int len = coco_string_length(str);
+	if (len) {
+		len = length;
+	}
+	char *dest = new char[len + 1];
+	for (int i = 0; i < len; ++i) {
+		dest[i] = (char) str[index + i];
+	}
+	dest[len] = 0;
+	return dest;
+}
+
+
+void coco_string_delete(char* &str) {
+	delete [] str;
+	str = NULL;
+}
+
+
+double coco_string_toDouble(const char* str)
+{
+	return str ? strtod(str, NULL) : 0;
+}
+
+float coco_string_toFloat(const char* str)
+{
+	return str ? strtof(str, NULL) : 0;
+}
+
+
+// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * //
+
+
+Token::Token()
+:
+    kind(0),
+    pos(0),
+    col(0),
+    line(0),
+    val(NULL),
+    next(NULL)
+{}
+
+
+Token::~Token() {
+	coco_string_delete(val);
+}
+
+
+Buffer::Buffer(FILE* s, bool isUserStream) {
+// ensure binary read on windows
+#if _MSC_VER >= 1300
+	_setmode(_fileno(s), _O_BINARY);
+#endif
+	stream = s; this->isUserStream = isUserStream;
+	if (CanSeek()) {
+		fseek(s, 0, SEEK_END);
+		fileLen = ftell(s);
+		fseek(s, 0, SEEK_SET);
+		bufLen = (fileLen < MAX_BUFFER_LENGTH) ? fileLen : MAX_BUFFER_LENGTH;
+		bufStart = INT_MAX; // nothing in the buffer so far
+	}
+	else {
+		fileLen = bufLen = bufStart = 0;
+	}
+	bufCapacity = (bufLen > 0) ? bufLen : MIN_BUFFER_LENGTH;
+	buf = new unsigned char[bufCapacity];
+	if (fileLen > 0) SetPos(0);          // setup buffer to position 0 (start)
+	else bufPos = 0; // index 0 is already after the file, thus Pos = 0 is invalid
+	if (bufLen == fileLen && CanSeek()) Close();
+}
+
+
+Buffer::Buffer(Buffer* b) {
+	buf = b->buf;
+	bufCapacity = b->bufCapacity;
+	b->buf = NULL;
+	bufStart = b->bufStart;
+	bufLen = b->bufLen;
+	fileLen = b->fileLen;
+	bufPos = b->bufPos;
+	stream = b->stream;
+	b->stream = NULL;
+	isUserStream = b->isUserStream;
+}
+
+
+Buffer::Buffer(const unsigned char* buf, int len) {
+	this->buf = new unsigned char[len];
+	memcpy(this->buf, buf, len*sizeof(unsigned char));
+	bufStart = 0;
+	bufCapacity = bufLen = len;
+	fileLen = len;
+	bufPos = 0;
+	stream = NULL;
+}
+
+
+Buffer::Buffer(const char* buf, int len) {
+	this->buf = new unsigned char[len];
+	memcpy(this->buf, buf, len*sizeof(unsigned char));
+	bufStart = 0;
+	bufCapacity = bufLen = len;
+	fileLen = len;
+	bufPos = 0;
+	stream = NULL;
+}
+
+
+Buffer::~Buffer() {
+	Close();
+	if (buf != NULL) {
+		delete [] buf;
+		buf = NULL;
+	}
+}
+
+
+void Buffer::Close() {
+	if (!isUserStream && stream != NULL) {
+		fclose(stream);
+		stream = NULL;
+	}
+}
+
+
+int Buffer::Read() {
+	if (bufPos < bufLen) {
+		return buf[bufPos++];
+	} else if (GetPos() < fileLen) {
+		SetPos(GetPos()); // shift buffer start to Pos
+		return buf[bufPos++];
+	} else if ((stream != NULL) && !CanSeek() && (ReadNextStreamChunk() > 0)) {
+		return buf[bufPos++];
+	} else {
+		return EoF;
+	}
+}
+
+
+int Buffer::Peek() {
+	int curPos = GetPos();
+	int ch = Read();
+	SetPos(curPos);
+	return ch;
+}
+
+
+wchar_t* Buffer::GetString(int beg, int end) {
+	int len = 0;
+	wchar_t *buf = new wchar_t[end - beg];
+	int oldPos = GetPos();
+	SetPos(beg);
+	while (GetPos() < end) buf[len++] = (wchar_t) Read();
+	SetPos(oldPos);
+	wchar_t *res = coco_string_create(buf, 0, len);
+	coco_string_delete(buf);
+	return res;
+}
+
+
+int Buffer::GetPos() {
+	return bufPos + bufStart;
+}
+
+
+void Buffer::SetPos(int value) {
+	if ((value >= fileLen) && (stream != NULL) && !CanSeek()) {
+		// Wanted position is after buffer and the stream
+		// is not seek-able e.g. network or console,
+		// thus we have to read the stream manually till
+		// the wanted position is in sight.
+		while ((value >= fileLen) && (ReadNextStreamChunk() > 0))
+		{}
+	}
+
+	if ((value < 0) || (value > fileLen)) {
+		wprintf(L"--- buffer out of bounds access, position: %d\n", value);
+		::exit(1);
+	}
+
+	if ((value >= bufStart) && (value < (bufStart + bufLen))) { // already in buffer
+		bufPos = value - bufStart;
+	} else if (stream != NULL) { // must be swapped in
+		fseek(stream, value, SEEK_SET);
+		bufLen = fread(buf, sizeof(unsigned char), bufCapacity, stream);
+		bufStart = value; bufPos = 0;
+	} else {
+		bufPos = fileLen - bufStart; // make Pos return fileLen
+	}
+}
+
+
+// Read the next chunk of bytes from the stream, increases the buffer
+// if needed and updates the fields fileLen and bufLen.
+// Returns the number of bytes read.
+int Buffer::ReadNextStreamChunk() {
+	int freeLen = bufCapacity - bufLen;
+	if (freeLen == 0) {
+		// in the case of a growing input stream
+		// we can neither seek in the stream, nor can we
+		// foresee the maximum length, thus we must adapt
+		// the buffer size on demand.
+		bufCapacity = bufLen * 2;
+		unsigned char *newBuf = new unsigned char[bufCapacity];
+		memcpy(newBuf, buf, bufLen*sizeof(unsigned char));
+		delete [] buf;
+		buf = newBuf;
+		freeLen = bufLen;
+	}
+	int read = fread(buf + bufLen, sizeof(unsigned char), freeLen, stream);
+	if (read > 0) {
+		fileLen = bufLen = (bufLen + read);
+		return read;
+	}
+	// end of stream reached
+	return 0;
+}
+
+
+bool Buffer::CanSeek() {
+	return (stream != NULL) && (ftell(stream) != -1);
+}
+
+
+int UTF8Buffer::Read() {
+	int ch;
+	do {
+		ch = Buffer::Read();
+		// until we find a utf8 start (0xxxxxxx or 11xxxxxx)
+	} while ((ch >= 128) && ((ch & 0xC0) != 0xC0) && (ch != EoF));
+	if (ch < 128 || ch == EoF) {
+		// nothing to do, first 127 chars are the same in ascii and utf8
+		// 0xxxxxxx or end of file character
+	} else if ((ch & 0xF0) == 0xF0) {
+		// 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
+		int c1 = ch & 0x07; ch = Buffer::Read();
+		int c2 = ch & 0x3F; ch = Buffer::Read();
+		int c3 = ch & 0x3F; ch = Buffer::Read();
+		int c4 = ch & 0x3F;
+		ch = (((((c1 << 6) | c2) << 6) | c3) << 6) | c4;
+	} else if ((ch & 0xE0) == 0xE0) {
+		// 1110xxxx 10xxxxxx 10xxxxxx
+		int c1 = ch & 0x0F; ch = Buffer::Read();
+		int c2 = ch & 0x3F; ch = Buffer::Read();
+		int c3 = ch & 0x3F;
+		ch = (((c1 << 6) | c2) << 6) | c3;
+	} else if ((ch & 0xC0) == 0xC0) {
+		// 110xxxxx 10xxxxxx
+		int c1 = ch & 0x1F; ch = Buffer::Read();
+		int c2 = ch & 0x3F;
+		ch = (c1 << 6) | c2;
+	}
+	return ch;
+}
+
+
+Scanner::Scanner(const unsigned char* buf, int len) {
+	buffer = new Buffer(buf, len);
+	Init();
+}
+
+
+Scanner::Scanner(const char* buf, int len) {
+	buffer = new Buffer(buf, len);
+	Init();
+}
+
+
+Scanner::Scanner(const wchar_t* fileName) {
+	FILE* stream;
+	char *chFileName = coco_string_create_char(fileName);
+	if ((stream = fopen(chFileName, "rb")) == NULL) {
+		wprintf(L"--- Cannot open file %ls\n", fileName);
+		::exit(1);
+	}
+	coco_string_delete(chFileName);
+	buffer = new Buffer(stream, false);
+	Init();
+}
+
+
+Scanner::Scanner(FILE* s) {
+	buffer = new Buffer(s, true);
+	Init();
+}
+
+
+Scanner::~Scanner() {
+	char* cur = (char*) firstHeap;
+
+	while (cur != NULL) {
+		cur = *(char**) (cur + HEAP_BLOCK_SIZE);
+		free(firstHeap);
+		firstHeap = cur;
+	}
+	delete [] tval;
+	delete buffer;
+}
+
+
+void Scanner::Init() {
+	maxT = 13;
+	noSym = 13;
+	int i;
+	for (i = 65; i <= 90; ++i) start.set(i, 1);
+	for (i = 97; i <= 122; ++i) start.set(i, 1);
+	for (i = 36; i <= 36; ++i) start.set(i, 5);
+	start.set(45, 20);
+	for (i = 48; i <= 57; ++i) start.set(i, 9);
+	start.set(34, 2);
+	start.set(46, 7);
+	start.set(123, 14);
+	start.set(125, 15);
+	start.set(43, 21);
+	start.set(42, 16);
+	start.set(47, 17);
+	start.set(40, 18);
+	start.set(41, 19);
+		start.set(Buffer::EoF, -1);
+
+
+	tvalLength = 128;
+	tval = new wchar_t[tvalLength]; // text of current token
+
+	// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
+	heap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
+	firstHeap = heap;
+	heapEnd = (void**) (((char*) heap) + HEAP_BLOCK_SIZE);
+	*heapEnd = 0;
+	heapTop = heap;
+	if (sizeof(Token) > HEAP_BLOCK_SIZE) {
+		wprintf(L"--- Too small HEAP_BLOCK_SIZE\n");
+		::exit(1);
+	}
+
+	pos = -1; line = 1; col = 0;
+	oldEols = 0;
+	NextCh();
+	if (ch == 0xEF) { // check optional byte order mark for UTF-8
+		NextCh(); int ch1 = ch;
+		NextCh(); int ch2 = ch;
+		if (ch1 != 0xBB || ch2 != 0xBF) {
+			wprintf(L"Illegal byte order mark at start of file");
+			::exit(1);
+		}
+		Buffer *oldBuf = buffer;
+		buffer = new UTF8Buffer(buffer); col = 0;
+		delete oldBuf; oldBuf = NULL;
+		NextCh();
+	}
+
+
+	pt = tokens = CreateToken(); // first token is a dummy
+}
+
+
+void Scanner::NextCh() {
+	if (oldEols > 0) {
+		ch = EOL;
+		oldEols--;
+	}
+	else {
+		pos = buffer->GetPos();
+		ch = buffer->Read(); col++;
+		// replace isolated '\r' by '\n' in order to make
+		// eol handling uniform across Windows, Unix and Mac
+		if (ch == L'\r' && buffer->Peek() != L'\n') ch = EOL;
+		if (ch == EOL) { line++; col = 0; }
+	}
+
+}
+
+
+void Scanner::AddCh() {
+	if (tlen >= tvalLength) {
+		tvalLength *= 2;
+		wchar_t *newBuf = new wchar_t[tvalLength];
+		memcpy(newBuf, tval, tlen*sizeof(wchar_t));
+		delete [] tval;
+		tval = newBuf;
+	}
+	if (ch != Buffer::EoF) {
+		tval[tlen++] = ch;
+		NextCh();
+	}
+}
+
+
+
+bool Scanner::Comment0() {
+	int level = 1, pos0 = pos, line0 = line, col0 = col;
+	NextCh();
+	if (ch == L'/') {
+		NextCh();
+		for(;;) {
+			if (ch == 10) {
+				level--;
+				if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+				NextCh();
+			} else if (ch == buffer->EoF) return false;
+			else NextCh();
+		}
+	} else {
+		buffer->SetPos(pos0); NextCh(); line = line0; col = col0;
+	}
+	return false;
+}
+
+bool Scanner::Comment1() {
+	int level = 1, pos0 = pos, line0 = line, col0 = col;
+	NextCh();
+	if (ch == L'*') {
+		NextCh();
+		for(;;) {
+			if (ch == L'*') {
+				NextCh();
+				if (ch == L'/') {
+					level--;
+					if (level == 0) { oldEols = line - line0; NextCh(); return true; }
+					NextCh();
+				}
+			} else if (ch == L'/') {
+				NextCh();
+				if (ch == L'*') {
+					level++; NextCh();
+				}
+			} else if (ch == buffer->EoF) return false;
+			else NextCh();
+		}
+	} else {
+		buffer->SetPos(pos0); NextCh(); line = line0; col = col0;
+	}
+	return false;
+}
+
+
+void Scanner::CreateHeapBlock() {
+	void* newHeap;
+	char* cur = (char*) firstHeap;
+
+	while (((char*) tokens < cur) || ((char*) tokens > (cur + HEAP_BLOCK_SIZE))) {
+		cur = *((char**) (cur + HEAP_BLOCK_SIZE));
+		free(firstHeap);
+		firstHeap = cur;
+	}
+
+	// HEAP_BLOCK_SIZE byte heap + pointer to next heap block
+	newHeap = malloc(HEAP_BLOCK_SIZE + sizeof(void*));
+	*heapEnd = newHeap;
+	heapEnd = (void**) (((char*) newHeap) + HEAP_BLOCK_SIZE);
+	*heapEnd = 0;
+	heap = newHeap;
+	heapTop = heap;
+}
+
+
+Token* Scanner::CreateToken() {
+	Token *t;
+	if (((char*) heapTop + (int) sizeof(Token)) >= (char*) heapEnd) {
+		CreateHeapBlock();
+	}
+	t = (Token*) heapTop;
+	heapTop = (void*) ((char*) heapTop + sizeof(Token));
+	t->val = NULL;
+	t->next = NULL;
+	return t;
+}
+
+
+void Scanner::AppendVal(Token *t) {
+	int reqMem = (tlen + 1) * sizeof(wchar_t);
+	if (((char*) heapTop + reqMem) >= (char*) heapEnd) {
+		if (reqMem > HEAP_BLOCK_SIZE) {
+			wprintf(L"--- Too long token value\n");
+			::exit(1);
+		}
+		CreateHeapBlock();
+	}
+	t->val = (wchar_t*) heapTop;
+	heapTop = (void*) ((char*) heapTop + reqMem);
+
+	wcsncpy(t->val, tval, tlen);
+	t->val[tlen] = L'\0';
+}
+
+
+Token* Scanner::NextToken() {
+	while (ch == ' ' ||
+			ch <= 31 || (ch >= 127 && ch <= 65535)
+	) NextCh();
+	if ((ch == L'/' && Comment0()) || (ch == L'/' && Comment1())) return NextToken();
+	t = CreateToken();
+	t->pos = pos; t->col = col; t->line = line;
+	int state = start.state(ch);
+	tlen = 0; AddCh();
+
+	switch (state) {
+		case -1: { t->kind = eofSym; break; } // NextCh already done
+		case 0: { t->kind = noSym; break; }   // NextCh already done
+		case 1:
+			case_1:
+			if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_1;}
+			else {t->kind = 1; break;}
+		case 2:
+			case_2:
+			if (ch <= 9 || (ch >= 11 && ch <= 12) || (ch >= 14 && ch <= L'!') || (ch >= L'#' && ch <= L'[') || (ch >= L']' && ch <= 65535)) {AddCh(); goto case_2;}
+			else if (ch == L'"') {AddCh(); goto case_4;}
+			else if (ch == 92) {AddCh(); goto case_3;}
+			else {t->kind = noSym; break;}
+		case 3:
+			case_3:
+			if ((ch >= L' ' && ch <= L'~')) {AddCh(); goto case_2;}
+			else {t->kind = noSym; break;}
+		case 4:
+			case_4:
+			{t->kind = 2; break;}
+		case 5:
+			if ((ch >= L'A' && ch <= L'Z') || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;}
+			else {t->kind = noSym; break;}
+		case 6:
+			case_6:
+			if ((ch >= L'0' && ch <= L':') || (ch >= L'A' && ch <= L'Z') || ch == L'_' || (ch >= L'a' && ch <= L'z')) {AddCh(); goto case_6;}
+			else {t->kind = 3; break;}
+		case 7:
+			case_7:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;}
+			else {t->kind = noSym; break;}
+		case 8:
+			case_8:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_8;}
+			else {t->kind = 4; break;}
+		case 9:
+			case_9:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_9;}
+			else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;}
+			else if (ch == L'.') {AddCh(); goto case_13;}
+			else {t->kind = 4; break;}
+		case 10:
+			case_10:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
+			else if (ch == L'+' || ch == L'-') {AddCh(); goto case_11;}
+			else {t->kind = noSym; break;}
+		case 11:
+			case_11:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
+			else {t->kind = noSym; break;}
+		case 12:
+			case_12:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_12;}
+			else {t->kind = 4; break;}
+		case 13:
+			case_13:
+			if ((ch >= L'0' && ch <= L'9')) {AddCh(); goto case_13;}
+			else if (ch == L'E' || ch == L'e') {AddCh(); goto case_10;}
+			else {t->kind = 4; break;}
+		case 14:
+			{t->kind = 5; break;}
+		case 15:
+			{t->kind = 6; break;}
+		case 16:
+			{t->kind = 9; break;}
+		case 17:
+			{t->kind = 10; break;}
+		case 18:
+			{t->kind = 11; break;}
+		case 19:
+			{t->kind = 12; break;}
+		case 20:
+			if (ch == L'.') {AddCh(); goto case_7;}
+			else {t->kind = 8; break;}
+		case 21:
+			if (ch == L'.') {AddCh(); goto case_7;}
+			else {t->kind = 7; break;}
+
+	}
+	AppendVal(t);
+	return t;
+}
+
+
+// get the next token (possibly a token already seen during peeking)
+Token* Scanner::Scan() {
+	if (tokens->next == NULL) {
+		return pt = tokens = NextToken();
+	} else {
+		pt = tokens = tokens->next;
+		return tokens;
+	}
+}
+
+
+// peek for the next token, ignore pragmas
+Token* Scanner::Peek() {
+	do {
+		if (pt->next == NULL) {
+			pt->next = NextToken();
+		}
+		pt = pt->next;
+	} while (pt->kind > maxT); // skip pragmas
+
+	return pt;
+}
+
+
+// make sure that peeking starts at the current scan position
+void Scanner::ResetPeek() {
+	pt = tokens;
+}
+
+
+} // namespace
+} // namespace
+} // namespace
+
+
diff --git a/applications/test/dictionary/calcEntry/calcEntryScanner.h b/applications/test/dictionary/calcEntry/calcEntryScanner.h
new file mode 100644
index 0000000000000000000000000000000000000000..8847c9fd2e2e7ab24b714dc3fb3cedf2ab65364c
--- /dev/null
+++ b/applications/test/dictionary/calcEntry/calcEntryScanner.h
@@ -0,0 +1,379 @@
+
+
+#ifndef COCO_calcEntrySCANNER_H__
+#define COCO_calcEntrySCANNER_H__
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+// io.h and fcntl are used to ensure binary read from streams on windows
+#if _MSC_VER >= 1300
+#include <io.h>
+#include <fcntl.h>
+#endif
+
+#if _MSC_VER >= 1400
+#define coco_swprintf swprintf_s
+#elif _MSC_VER >= 1300
+#define coco_swprintf _snwprintf
+#else
+// assume every other compiler knows swprintf
+#define coco_swprintf swprintf
+#endif
+
+#define COCO_WCHAR_MAX    65535
+#define MIN_BUFFER_LENGTH 1024
+#define MAX_BUFFER_LENGTH (64*MIN_BUFFER_LENGTH)
+#define HEAP_BLOCK_SIZE   (64*1024)
+
+
+namespace Foam {
+namespace functionEntries {
+namespace calcEntryInternal {
+
+
+
+// * * * * * * * * * *  Wide Character String Routines * * * * * * * * * * * //
+
+//
+// string handling, wide character
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+//! Create by copying str
+wchar_t* coco_string_create(const wchar_t* str);
+
+//! Create a substring of str starting at index and length characters long
+wchar_t* coco_string_create(const wchar_t* str, int index, int length);
+
+//! Create an uppercase string from str
+wchar_t* coco_string_create_upper(const wchar_t* str);
+
+//! Create an uppercase substring from str starting at index and length characters long
+wchar_t* coco_string_create_upper(const wchar_t* str, int index, int length);
+
+//! Create a lowercase string from str
+wchar_t* coco_string_create_lower(const wchar_t* str);
+
+//! Create a lowercase substring from str starting at index and length characters long
+wchar_t* coco_string_create_lower(const wchar_t* str, int index, int length);
+
+//! Create a string by concatenating str1 and str2
+wchar_t* coco_string_create_append(const wchar_t* str1, const wchar_t* str2);
+
+//! Create a string by concatenating a character to the end of str
+wchar_t* coco_string_create_append(const wchar_t* str, const wchar_t ch);
+
+//! Free storage and nullify the argument
+void  coco_string_delete(wchar_t* &str);
+
+//! The length of the str, or 0 if the str is NULL
+int   coco_string_length(const wchar_t* str);
+
+//! Return true if the str ends with the endstr
+bool  coco_string_endswith(const wchar_t* str, const wchar_t* endstr);
+
+//! Return the index of the first occurrence of ch.
+//  Return -1 if nothing is found.
+int   coco_string_indexof(const wchar_t* str, const wchar_t ch);
+
+//! Return the index of the last occurrence of ch.
+//  Return -1 if nothing is found.
+int   coco_string_lastindexof(const wchar_t* str, const wchar_t ch);
+
+//! Append str to dest
+void  coco_string_merge(wchar_t* &dest, const wchar_t* str);
+
+//! Compare strings, return true if they are equal
+bool  coco_string_equal(const wchar_t* str1, const wchar_t* str2);
+
+//! Compare strings, return 0 if they are equal
+int   coco_string_compareto(const wchar_t* str1, const wchar_t* str2);
+
+//! Simple string hashing function
+int   coco_string_hash(const wchar_t* str);
+
+//
+// String conversions
+// ~~~~~~~~~~~~~~~~~~
+
+//! Convert wide string to double
+double coco_string_toDouble(const wchar_t* str);
+
+//! Convert wide string to float
+float coco_string_toFloat(const wchar_t* str);
+
+//
+// String handling, byte character
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+//! Create by copying byte str
+wchar_t* coco_string_create(const char* str);
+
+//! Create a substring of byte str starting at index and length characters long
+wchar_t* coco_string_create(const char* str, int index, int length);
+
+//! Create a byte string by copying str
+char* coco_string_create_char(const wchar_t* str);
+
+//! Create a byte substring of str starting at index and length characters long
+char* coco_string_create_char(const wchar_t* str, int index, int length);
+
+//! Free storage and nullify the argument
+void  coco_string_delete(char* &str);
+
+
+//
+// String conversions, byte character
+// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+//! Convert byte string to double
+double coco_string_toDouble(const char* str);
+
+//! Convert byte string to float
+float coco_string_toFloat(const char* str);
+
+// * * * * * * * * * End of Wide Character String Routines * * * * * * * * * //
+
+
+
+//! Scanner Token
+class Token
+{
+public:
+	int kind;       //!< token kind
+	int pos;        //!< token position in the source text (starting at 0)
+	int col;        //!< token column (starting at 1)
+	int line;       //!< token line (starting at 1)
+	wchar_t* val;   //!< token value
+	Token *next;    //!< Peek tokens are kept in linked list
+
+	Token();        //!< Construct null
+	~Token();       //!< Destructor - cleanup allocated val
+};
+
+
+//! Scanner Buffer
+//
+//! This Buffer supports the following cases:
+//! -# seekable stream (file)
+//!    -# whole stream in buffer
+//!    -# part of stream in buffer
+//! -# non seekable stream (network, console)
+class Buffer {
+private:
+	unsigned char *buf; //!< input buffer
+	int bufCapacity;    //!< capacity of buf
+	int bufStart;       //!< position of first byte in buffer relative to input stream
+	int bufLen;         //!< length of buffer
+	int fileLen;        //!< length of input stream (may change if the stream is no file)
+	int bufPos;         //!< current position in buffer
+	FILE* stream;       //!< input stream (seekable)
+	bool isUserStream;  //!< was the stream opened by the user?
+
+	int ReadNextStreamChunk();
+	bool CanSeek();     //!< true if stream can be seeked otherwise false
+
+public:
+	static const int EoF = COCO_WCHAR_MAX + 1;
+
+	Buffer(FILE*, bool isUserStream);
+	Buffer(const unsigned char* buf, int len);
+	Buffer(const char* buf, int len);
+	Buffer(Buffer*);
+	virtual ~Buffer();
+
+	virtual void Close();
+	virtual int Read();
+	virtual int Peek();
+	virtual wchar_t* GetString(int beg, int end);
+	virtual int GetPos();
+	virtual void SetPos(int value);
+};
+
+
+//! A Scanner buffer that handles UTF-8 characters
+class UTF8Buffer : public Buffer {
+public:
+	UTF8Buffer(Buffer* b) : Buffer(b) {}
+	virtual int Read();
+};
+
+
+//------------------------------------------------------------------------------
+// StartStates
+//------------------------------------------------------------------------------
+//! maps characters to start states of tokens
+class StartStates {
+private:
+	class Elem {
+	public:
+		int key, val;
+		Elem *next;
+		Elem(int key, int val) {
+			this->key = key;
+			this->val = val;
+			next = NULL;
+		}
+	};
+
+	Elem **tab;
+
+public:
+	StartStates() {
+		tab = new Elem*[128];
+		memset(tab, 0, 128 * sizeof(Elem*));
+	}
+	virtual ~StartStates() {
+		for (int i = 0; i < 128; ++i) {
+			Elem *e = tab[i];
+			while (e != NULL) {
+				Elem *next = e->next;
+				delete e;
+				e = next;
+			}
+		}
+		delete [] tab;
+	}
+
+	void set(int key, int val) {
+		Elem *e = new Elem(key, val);
+		int k = ((unsigned int) key) % 128;
+		e->next = tab[k];
+		tab[k] = e;
+	}
+
+	int state(int key) {
+		Elem *e = tab[((unsigned int) key) % 128];
+		while (e != NULL && e->key != key) e = e->next;
+		return e == NULL ? 0 : e->val;
+	}
+};
+
+
+//------------------------------------------------------------------------------
+// KeywordMap
+//------------------------------------------------------------------------------
+//! maps strings to integers (identifiers to keyword kinds)
+class KeywordMap {
+private:
+	class Elem {
+	public:
+		wchar_t *key;
+		int val;
+		Elem *next;
+		Elem(const wchar_t *key, int val) {
+			this->key = coco_string_create(key);
+			this->val = val;
+			next = NULL;
+		}
+		virtual ~Elem() {
+			coco_string_delete(key);
+		}
+	};
+
+	Elem **tab;
+
+public:
+	KeywordMap() {
+		tab = new Elem*[128];
+		memset(tab, 0, 128 * sizeof(Elem*));
+	}
+	virtual ~KeywordMap() {
+		for (int i = 0; i < 128; ++i) {
+			Elem *e = tab[i];
+			while (e != NULL) {
+				Elem *next = e->next;
+				delete e;
+				e = next;
+			}
+		}
+		delete [] tab;
+	}
+
+	void set(const wchar_t *key, int val) {
+		Elem *e = new Elem(key, val);
+		int k = coco_string_hash(key) % 128;
+		e->next = tab[k]; tab[k] = e;
+	}
+
+	int get(const wchar_t *key, int defaultVal) {
+		Elem *e = tab[coco_string_hash(key) % 128];
+		while (e != NULL && !coco_string_equal(e->key, key)) e = e->next;
+		return e == NULL ? defaultVal : e->val;
+	}
+};
+
+
+//! A Coco/R Scanner
+class Scanner {
+private:
+	static const unsigned char EOL = '\n';   // end-of-line character
+	static const int eofSym = 0;             // end-of-file token id
+
+	void *firstHeap;
+	void *heap;
+	void *heapTop;
+	void **heapEnd;
+
+	int noSym;        //!< noSym gets highest number, set in Parser
+	int maxT;
+	int charSetSize;  //!< unused?
+	StartStates start;
+	KeywordMap keywords;
+
+	Token *t;         //!< current token
+	wchar_t *tval;    //!< text of current token
+	int tvalLength;   //!< length of text of current token
+	int tlen;         //!< length of current token
+
+	Token *tokens;    //!< list of tokens already peeked (first token is a dummy)
+	Token *pt;        //!< current peek token
+
+	int ch;           //!< current input character
+
+	int pos;          //!< byte position of current character
+	int line;         //!< line number of current character
+	int col;          //!< column number of current character
+	int oldEols;      //!< EOLs that appeared in a comment;
+
+	void CreateHeapBlock();
+	Token* CreateToken();
+	void AppendVal(Token*);
+
+	void Init();
+	void NextCh();
+	void AddCh();
+	bool Comment0();
+	bool Comment1();
+
+	Token* NextToken();
+
+public:
+	//! scanner buffer
+	Buffer *buffer;
+
+	//! Attach scanner to an existing character buffer
+	Scanner(const unsigned char* buf, int len);
+	//! Attach scanner to an existing character buffer
+	Scanner(const char* buf, int len);
+	//! Open a file for reading and attach scanner
+	Scanner(const wchar_t* fileName);
+	//! Using an existing open file handle for the scanner
+	Scanner(FILE* s);
+	~Scanner();
+	Token* Scan();
+	Token* Peek();
+	void ResetPeek();
+
+}; // end Scanner
+
+} // namespace
+} // namespace
+} // namespace
+
+
+#endif // COCO_calcEntrySCANNER_H__
+
diff --git a/applications/test/dictionary/dictionaryTest.C b/applications/test/dictionary/dictionaryTest.C
index 2c2395e9fb956b769db5a48bec0798fd945ca2d5..ff2add8169b156cd75213095cfad581c9d286daa 100644
--- a/applications/test/dictionary/dictionaryTest.C
+++ b/applications/test/dictionary/dictionaryTest.C
@@ -43,70 +43,86 @@ using namespace Foam;
 int main(int argc, char *argv[])
 {
     argList::noParallel();
-    argList args(argc, argv);
+    argList::validArgs.insert("dict .. dictN");
+    argList args(argc, argv, false, true);
 
     Info<< nl
         << "FOAM_CASE=" << getEnv("FOAM_CASE") << nl
         << "FOAM_CASENAME=" << getEnv("FOAM_CASENAME") << nl
         << endl;
 
-
+    if (args.additionalArgs().empty())
     {
-        dictionary dict1(IFstream("testDict")());
-        Info<< "dict1: " << dict1 << nl
-            << "toc: " << dict1.toc() << nl
-            << "keys: " << dict1.keys() << nl
-            << "patterns: " << dict1.keys(true) << endl;
-
-        dictionary dict2(dict1.xfer());
-
-        Info<< "dict1.toc(): " << dict1.name() << " " << dict1.toc() << nl
-            << "dict2.toc(): " << dict2.name() << " " << dict2.toc() << endl;
-
-        // copy back
-        dict1 = dict2;
-        Info<< "dict1.toc(): " << dict1.name() << " " << dict1.toc() << endl;
-
-        dictionary dict3(dict2.subDictPtr("boundaryField"));
-        dictionary dict4(dict2.subDictPtr("NONEXISTENT"));
-
-        Info<< "dictionary construct from pointer" << nl
-            << "ok = " << dict3.name() << " " << dict3.toc() << nl
-            << "no = " << dict4.name() << " " << dict4.toc() << endl;
+        {
+            dictionary dict1(IFstream("testDict")());
+            Info<< "dict1: " << dict1 << nl
+                << "toc: " << dict1.toc() << nl
+                << "keys: " << dict1.keys() << nl
+                << "patterns: " << dict1.keys(true) << endl;
+
+            dictionary dict2(dict1.xfer());
+
+            Info<< "dict1.toc(): " << dict1.name() << " " << dict1.toc() << nl
+                << "dict2.toc(): " << dict2.name() << " " << dict2.toc() << endl;
+
+            // copy back
+            dict1 = dict2;
+            Info<< "dict1.toc(): " << dict1.name() << " " << dict1.toc() << endl;
+
+            dictionary dict3(dict2.subDictPtr("boundaryField"));
+            dictionary dict4(dict2.subDictPtr("NONEXISTENT"));
+
+            Info<< "dictionary construct from pointer" << nl
+                << "ok = " << dict3.name() << " " << dict3.toc() << nl
+                << "no = " << dict4.name() << " " << dict4.toc() << endl;
+        }
+
+
+        IOobject::writeDivider(Info);
+
+        {
+            dictionary dict(IFstream("testDictRegex")());
+            dict.add(keyType("fooba[rz]", true), "anything");
+
+            Info<< "dict:" << dict << nl
+                << "toc: " << dict.toc() << nl
+                << "keys: " << dict.keys() << nl
+                << "patterns: " << dict.keys(true) << endl;
+
+            Info<< "Pattern find \"abc\" in top directory : "
+                << dict.lookup("abc") << endl;
+            Info<< "Pattern find \"abc\" in sub directory : "
+                << dict.subDict("someDict").lookup("abc")
+                    << endl;
+            Info<< "Recursive pattern find \"def\" in sub directory : "
+                << dict.subDict("someDict").lookup("def", true)
+                    << endl;
+            Info<< "Recursive pattern find \"foo\" in sub directory : "
+                << dict.subDict("someDict").lookup("foo", true)
+                    << endl;
+            Info<< "Recursive pattern find \"fooz\" in sub directory : "
+                << dict.subDict("someDict").lookup("fooz", true)
+                    << endl;
+            Info<< "Recursive pattern find \"bar\" in sub directory : "
+                << dict.subDict("someDict").lookup("bar", true)
+                    << endl;
+            Info<< "Recursive pattern find \"xxx\" in sub directory : "
+                << dict.subDict("someDict").lookup("xxx", true)
+                    << endl;
+        }
     }
+    else
+    {
+        IOobject::writeDivider(Info);
+        forAll(args.additionalArgs(), argI)
+        {
+            const string& dictFile = args.additionalArgs()[argI];
+            IFstream is(dictFile);
 
+            dictionary dict(is);
 
-    IOobject::writeDivider(Info);
-
-    {
-        dictionary dict(IFstream("testDictRegex")());
-        dict.add(keyType("fooba[rz]", true), "anything");
-
-        Info<< "dict:" << dict << nl
-            << "toc: " << dict.toc() << nl
-            << "keys: " << dict.keys() << nl
-            << "patterns: " << dict.keys(true) << endl;
-
-        Info<< "Pattern find \"abc\" in top directory : "
-            << dict.lookup("abc") << endl;
-        Info<< "Pattern find \"abc\" in sub directory : "
-            << dict.subDict("someDict").lookup("abc")
-            << endl;
-        Info<< "Recursive pattern find \"def\" in sub directory : "
-            << dict.subDict("someDict").lookup("def", true)
-            << endl;
-        Info<< "Recursive pattern find \"foo\" in sub directory : "
-            << dict.subDict("someDict").lookup("foo", true)
-            << endl;
-        Info<< "Recursive pattern find \"fooz\" in sub directory : "
-            << dict.subDict("someDict").lookup("fooz", true)
-            << endl;
-        Info<< "Recursive pattern find \"bar\" in sub directory : "
-            << dict.subDict("someDict").lookup("bar", true)
-            << endl;
-        Info<< "Recursive pattern find \"xxx\" in sub directory : "
-            << dict.subDict("someDict").lookup("xxx", true)
-            << endl;
+            Info<< dict << endl;
+        }
     }
 
     return 0;
diff --git a/applications/test/dictionary/testDictCalc b/applications/test/dictionary/testDictCalc
new file mode 100644
index 0000000000000000000000000000000000000000..cfce0e0b525dd0bb0f7f2d09ba2a5e4a52633d30
--- /dev/null
+++ b/applications/test/dictionary/testDictCalc
@@ -0,0 +1,33 @@
+/*--------------------------------*- C++ -*----------------------------------*\
+| =========                 |                                                 |
+| \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox           |
+|  \\    /   O peration     | Version:  Any                                   |
+|   \\  /    A nd           | Web:      www.OpenFOAM.org                      |
+|    \\/     M anipulation  |                                                 |
+\*---------------------------------------------------------------------------*/
+FoamFile
+{
+    version     2.0;
+    format      ascii;
+    class       dictionary;
+    object      testDictTest;
+}
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+x       10 /* what ever */ 20;
+y       20;
+// z       #test{ // this
+//     123 - 456
+//         // comments // are
+//         /* stripped
+//         * 10
+//          * {}
+//          */
+//         + 1 /*100 */  10
+// };
+
+p       #test{ 1 + 2 + 10 * 15 + $x - $y };
+
+foo     30;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //