/****************************************************************************************
* Copyright (c) 2014 Michael Goldbach <michael@wildplot.com> *
* *
* This program 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. *
* *
* This program 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 *
* this program. If not, see <http://www.gnu.org/licenses/>. *
****************************************************************************************/
package com.wildplot.android.parsing;
public class Pow implements TreeElement{
private TopLevelParser parser;
public static enum PowType {ATOM, ATOM_POW_FACTOR, ATOM_SQRT_FACTOR, INVALID};
private PowType powType = PowType.INVALID;
private Atom atom;
private Factor factor;
public Pow(String powString, TopLevelParser parser){
this.parser = parser;
if(!TopLevelParser.stringHasValidBrackets(powString)){
this.powType = PowType.INVALID;
return;
}
boolean isReady;
isReady = initAsAtom(powString);
if(!isReady)
isReady = initAsAtomPowFactor(powString);
if(!isReady)
isReady = initAsAtomSqrtFactor(powString);
if(!isReady)
this.powType = PowType.INVALID;
}
private boolean initAsAtom(String powString){
Atom atom = new Atom(powString, parser);
boolean isValidAtom = atom.getAtomType() != Atom.AtomType.INVALID;
if(isValidAtom){
this.powType = PowType.ATOM;
this.atom = atom;
return true;
}
return false;
}
private boolean initAsAtomPowFactor(String powString){
int opPos = powString.indexOf("^");
if(opPos > 0){
String leftAtomString = powString.substring(0,opPos);
String rightFactorString = powString.substring(opPos+1, powString.length());
if(!TopLevelParser.stringHasValidBrackets(leftAtomString) || !TopLevelParser.stringHasValidBrackets(rightFactorString))
return false;
Atom leftAtom = new Atom(leftAtomString, parser);
boolean isValidAtom = leftAtom.getAtomType() != Atom.AtomType.INVALID;
if(isValidAtom){
Factor rightFactor = new Factor(rightFactorString, parser);
boolean isValidFactor = rightFactor.getFactorType() != Factor.FactorType.INVALID;
if(isValidFactor){
this.powType= PowType.ATOM_POW_FACTOR;
this.atom = leftAtom;
this.factor = rightFactor;
return true;
}
}
}
return false;
}
private boolean initAsAtomSqrtFactor(String powString){
int opPos = powString.indexOf("**");
if(opPos > 0){
String leftAtomString = powString.substring(0,opPos);
String rightFactorString = powString.substring(opPos+2, powString.length());
if(!TopLevelParser.stringHasValidBrackets(leftAtomString) || !TopLevelParser.stringHasValidBrackets(rightFactorString))
return false;
Atom leftAtom = new Atom(leftAtomString, parser);
boolean isValidAtom = leftAtom.getAtomType() != Atom.AtomType.INVALID;
if(isValidAtom){
Factor rightFactor = new Factor(rightFactorString, parser);
boolean isValidFactor = rightFactor.getFactorType() != Factor.FactorType.INVALID;
if(isValidFactor){
this.powType= PowType.ATOM_SQRT_FACTOR;
this.atom = leftAtom;
this.factor = rightFactor;
return true;
}
}
}
return false;
}
@Override
public double getValue() throws ExpressionFormatException{
switch (powType) {
case ATOM:
return atom.getValue();
case ATOM_POW_FACTOR:
return Math.pow(atom.getValue(), factor.getValue());
case ATOM_SQRT_FACTOR:
return Math.pow(atom.getValue(), 1.0/factor.getValue());
case INVALID:
default:
throw new ExpressionFormatException("cannot parse Atom expression");
}
}
@Override
public boolean isVariable() throws ExpressionFormatException{
switch (powType) {
case ATOM:
return atom.isVariable();
case ATOM_POW_FACTOR:
case ATOM_SQRT_FACTOR:
return atom.isVariable() || factor.isVariable();
case INVALID:
default:
throw new ExpressionFormatException("cannot parse Atom expression");
}
}
public PowType getPowType() {
return powType;
}
}