/*  Simple integer calculator.
 *  Calculates the integer value of expressions like 4*(23*4+(12-4)*12)
 *  with correct operator precedence.
 *  Compile the generated D file and call it for example like this: arithmetic "4*(23*4+(12-4)*12)"
 */

APDDeclaration
{
    version(Tango) {
        import tango.io.Stdout;
        import tango.text.convert.Integer;
    }
    else
        import std.stdio;

    void main(string[] args)
    {
        if ( args.length < 2 )
            throw new Exception("Usage: arithmetic <expression>");
        SyntaxTree* root;
        if ( parse("", args[1], root, true) ) {
            int value;
            root.Expr(value);
            debug root.print;
            version(Tango)
                Stdout.format("{} = {}\n", args[1], value);
            else
                writefln("%s = %d", args[1], value);
        }
        else
        {
            version(Tango)
                Stdout.format("Invalid expression: {}\n", args[1]);
            else
                writefln("Invalid expression: %s", args[1]);
        }
    }
}

Whitespace
{
    regexp("[ \\t\\n\\r]+");
}

Expr(out int value)
{
    MulExpr "+" Expr
    {
        int val;
        Expr(val);
        MulExpr(value);
        value += val;
    }

    MulExpr "-" Expr
    {
        int val;
        Expr(val);
        MulExpr(value);
        value -= val;
    }

    MulExpr
    { MulExpr(value); }
}

MulExpr(out int value)
{
    Atom "*" MulExpr
    {
        int num;
        Atom(num);
        MulExpr(value);
        value *= num;
    }

    Atom
    { Atom(value); }
}

Atom(out int value)
{
    regexp("[0-9]+")
    {
        version(Tango)
            value = atoi(_ST_match);
        else
            value = atoi(_ST_match);
    }

    "(" Expr ")"
    { Expr(value); }
}