package fanch.multijeu.numbers.data;

public class ExpressionParser {

    protected ExpressionLexer mLexer;

    protected String mString;
    protected ExpressionLexer.Lexem mLex;

    public ExpressionParser(String s)
    {
        mLexer=new ExpressionLexer(s);
    }

    public Expression parse()
    {
        next();
        return expr();
    }

    public Expression secureParse()
    {
        Expression ex;
        try{
            ex=parse();
            return ex;
        }catch (Exception e)
        {
            return null;
        }
    }

    private void next()
    {
        mLex=mLexer.next();
        mString=mLexer.getString();
    }

    private Expression expr() {
        Expression first;
        Expression sec;
        first= expr1();
        switch(mLex)
        {
            case PLUS:
                next();
                sec= expr();
                return new OperationExpr(OperationExpr.Operation.ADD, first, sec);

            case MINUS:
                next();
                sec= expr();
                return new OperationExpr(OperationExpr.Operation.SUB, first, sec);

            default:
                return first;
        }
    }

    private Expression expr1() {
        Expression first;
        Expression sec;
        first= expr2();
        switch(mLex)
        {
            case MULT:
                next();
                sec= expr1();
                return new OperationExpr(OperationExpr.Operation.MULT, first, sec);

            default:
                return first;
        }
    }

    private Expression expr2() {
        Expression expr;
        switch (mLex)
        {
            case P_OPEN:
                next();
                expr=expr();
                if(mLex== ExpressionLexer.Lexem.P_CLOSE)
                {
                    next();
                    return expr;
                }
            case NUMBER:
                int x = mLexer.getInt();
                next();
                return new NumberExpr(x);

            case MINUS:
                next();
                int y = mLexer.getInt();
                next();
                return new NumberExpr(-y);
        }
        throw new RuntimeException("Parser error expected Number' or parethesis : "+mLex);
    }

    public static Expression parse(String s)
    {
        ExpressionParser xp = new ExpressionParser(s);
        return xp.secureParse();
    }
}
