Example Application: Simple Expression Calculator

The first example application is a simple calculator.

It takes the arguments on the command line as an expresssion string, parses it and evaluates the resulting tree using a stx::BasicSymbolTable. This page will guide you through the workings of the example.

Detailed Example Code Guide

#include "ExpressionParser.h"

The include file ExpressionParser.h contains the required classes and also includes AnyScalar.h

int main(int argc, char *argv[])
{
    // collect expression by joining all input arguments
    std::string args;
    for(int i = 1; i < argc; i++) {
        if (!args.empty()) args += " ";
        args += argv[i];
    }

The first step in main is to collect all command line parameters into a single std::string. When invoking the exprcalc program from the command line it is better to quote the whole expression into one argument: ./exprcalc "4 + 19 2". This will work correctly with special symbols processed by the shell like <, > or !.

    // parse expression into a parse tree
    stx::ParseTree pt;
    try
    {
        pt = stx::parseExpression(args);
        std::cout << "parsed: " << pt.toString() << "\n";
    }
    catch (stx::ExpressionParserException &e)
    {
        std::cout << "ExpressionParserException: " << e.what() << "\n";
        return 0;
    }

Next the concatenated arguments are parsed by the expression parser using stx::parseExpression(const std::string&). The parse function returns a stx::ParseTree object by value; the stx::ParseTree object is actually a pimpl front-end to the top-most stx::ParseNode of the tree.

Many thing can go wrong while parsing the user input string and will result in parseExpression throwing an exception. The top exception class used by the parser is stx::ExpressionParserException. If the user enters an invalid expression like "3 + " then a stx::BadSyntaxException is thrown and will be caught by the catch-block and the application terminated after printing an error.

If the input could successfully be parsed then the program prints the resulting parse tree using stx::ParseTree::toString(). This function converts the internal tree structure back to a string, which can be re-parsed into the same tree. Usually this string will include extra brackets like "(4 + (19 * x))".

    // evaluate the expression with a very simple symbol table
    stx::BasicSymbolTable bst;
    bst.setVariable("x", 42);

Then an instance of stx::BasicSymbolTable is created. stx::BasicSymbolTable is a derivative of the abstract stx::SymbolTable which is used by the evaluation functions to fill in variables and functions. The stx::BasicSymbolTable includes some basic mathematical functions like sin() and exp().

For our simple calculator we define a single variable: x is set to 42.

    try
    {
        stx::AnyScalar val = pt.evaluate(bst);

        std::cout << "evaluated: " << val << "\n";
    }
    catch (stx::UnknownSymbolException &e)
    {
        std::cout << "UnknownSymbolException: " << e.what() << "\n";
        return 0;
    }
    catch (stx::ExpressionParserException &e)
    {
        std::cout << "ExpressionParserException: " << e.what() << "\n";
        return 0;
    }

    return 0;
}

Once the symbol table is filled in, the parse tree is evaluated using it. The evaluation result is returned as a stx::AnyScalar and printed out to the user.

During evaluation variable placeholders are filled in. If the expression requires a non-existing variable of function, then the standard behaviour of stx::BasicSymbolTable is to throw a stx::UnknownSymbolException.

Further exceptions can be thrown during different operations on the stx::AnyScalar objects. These operators will throw a stx::ConversionException if incompatible types are used. For example boolean + integer is not allowed and will throw.

Complete Example Source Code

The example can be found in the distribution in examples/simple/

// $Id: exprcalc.cc 59 2007-07-17 14:43:23Z tb $

/*
 * STX Expression Parser C++ Framework v0.7
 * Copyright (C) 2007 Timo Bingmann
 *
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 *
 * This library 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 Lesser General Public License
 * for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

// Simple Expression Calculator Example

#include <iostream>
 
#include "ExpressionParser.h"

int main(int argc, char *argv[])
{
    // collect expression by joining all input arguments
    std::string args;
    for(int i = 1; i < argc; i++) {
        if (!args.empty()) args += " ";
        args += argv[i];
    }

    std::cout << "input string: " << args << "\n";

    // parse expression into a parse tree
    stx::ParseTree pt;
    try
    {
        pt = stx::parseExpression(args);
        std::cout << "parsed: " << pt.toString() << "\n";
    }
    catch (stx::ExpressionParserException &e)
    {
        std::cout << "ExpressionParserException: " << e.what() << "\n";
        return 0;
    }

    // evaluate the expression with a very simple symbol table
    stx::BasicSymbolTable bst;
    bst.setVariable("x", 42);

    try
    {
        stx::AnyScalar val = pt.evaluate(bst);

        std::cout << "evaluated: " << val << "\n";
    }
    catch (stx::UnknownSymbolException &e)
    {
        std::cout << "UnknownSymbolException: " << e.what() << "\n";
        return 0;
    }
    catch (stx::ExpressionParserException &e)
    {
        std::cout << "ExpressionParserException: " << e.what() << "\n";
        return 0;
    }

    return 0;
}

Generated on Tue Jul 17 16:51:58 2007 for STX Expression Parser by  doxygen 1.5.2