Heres a little sample program that should get you going. It only handles the basic operators '-','+','/','*' and doesn't handle parens (). Hope you find it useful. public class MathParser { private static final char[] validOperators = {'/','*','+','-'}; private MathParser() { /* Using a private contructor to prevent instantiation Using class as a simple static utility class */ } private static int evaluate(String leftSide, char oper, String rightSide) throws IllegalArgumentException { System.out.println("Evaluating: " + leftSide + " (" + oper + ") " + rightSide); int total = 0; int leftResult = 0; int rightResult = 0; int operatorLoc = findOperatorLocation(leftSide); if( operatorLoc > 0 && operatorLoc < leftSide.length()-1 ) { leftResult = evaluate(leftSide.substring(0,operatorLoc), leftSide.charAt(operatorLoc), leftSide.substring(operatorLoc+1,leftSide.length())); } else { try { leftResult = Integer.parseInt(leftSide); } catch(Exception e) { throw new IllegalArgumentException("Invalid value found in portion of equation: " + leftSide); } } operatorLoc = findOperatorLocation(rightSide); if( operatorLoc > 0 && operatorLoc < rightSide.length()-1 ) { rightResult = evaluate(rightSide.substring(0,operatorLoc), rightSide.charAt(operatorLoc), rightSide.substring(operatorLoc+1,rightSide.length())); } else { try { rightResult = Integer.parseInt(rightSide); } catch(Exception e) { throw new IllegalArgumentException("Invalid value found in portion of equation: " + rightSide); } } System.out.println("Getting result of: " + leftResult + " " + oper + " " + rightResult); switch(oper) { case '/': total = leftResult / rightResult; break; case '*': total = leftResult * rightResult; break; case '+': total = leftResult + rightResult; break; case '-': total = leftResult - rightResult; break; default: throw new IllegalArgumentException("Unknown operator."); } System.out.println("Returning a result of: " + total); return total; } private static int findOperatorLocation(String string) { int index = -1; for(int i = validOperators.length-1; i >= 0; i--) { index = string.indexOf(validOperators[i]); if(index >= 0) return index; } return index; } public static int processEquation(String equation) throws IllegalArgumentException { return evaluate(equation,'+',"0"); } public static void main(String[] args) { String usage = "Usage: java MathParser equation\nWhere equation is a series" + " of integers separated by valid operators (+,-,/,*)"; if(args.length < 1 || args[0].length() == 0) System.out.println(usage); String equation = args[0]; try { int result = MathParser.processEquation(equation); System.out.println("The result of your equation (" + equation + ") is: " + result); } catch(IllegalArgumentException iae) { System.out.println(iae.getMessage() + "\n" + usage); } } }
Perl only support regexp. And such expression is not regexp. You could use some parser generator like JavaCC. Basically, you define the grammar in Javacc, it will build the ast for you. Then simply evaluate the ast.
Not really. As long as you feel comfortable with BNF, you are ok. JavaCC uses LL(1), and you don't have to deal with the tricky optimization part.
public class MathParser
{
private static final char[] validOperators = {'/','*','+','-'}; private MathParser()
{
/* Using a private contructor to prevent instantiation
Using class as a simple static utility class
*/
} private static int evaluate(String leftSide, char oper, String rightSide)
throws IllegalArgumentException
{
System.out.println("Evaluating: " + leftSide + " (" + oper + ") " + rightSide);
int total = 0;
int leftResult = 0;
int rightResult = 0; int operatorLoc = findOperatorLocation(leftSide);
if( operatorLoc > 0 && operatorLoc < leftSide.length()-1 )
{
leftResult = evaluate(leftSide.substring(0,operatorLoc),
leftSide.charAt(operatorLoc),
leftSide.substring(operatorLoc+1,leftSide.length()));
}
else
{
try
{
leftResult = Integer.parseInt(leftSide);
}
catch(Exception e)
{
throw new IllegalArgumentException("Invalid value found in portion of equation: "
+ leftSide);
}
} operatorLoc = findOperatorLocation(rightSide);
if( operatorLoc > 0 && operatorLoc < rightSide.length()-1 )
{
rightResult = evaluate(rightSide.substring(0,operatorLoc),
rightSide.charAt(operatorLoc),
rightSide.substring(operatorLoc+1,rightSide.length()));
}
else
{
try
{
rightResult = Integer.parseInt(rightSide);
}
catch(Exception e)
{
throw new IllegalArgumentException("Invalid value found in portion of equation: "
+ rightSide);
}
} System.out.println("Getting result of: " + leftResult + " " + oper + " " + rightResult);
switch(oper)
{
case '/':
total = leftResult / rightResult; break;
case '*':
total = leftResult * rightResult; break;
case '+':
total = leftResult + rightResult; break;
case '-':
total = leftResult - rightResult; break;
default:
throw new IllegalArgumentException("Unknown operator.");
}
System.out.println("Returning a result of: " + total);
return total;
} private static int findOperatorLocation(String string)
{
int index = -1;
for(int i = validOperators.length-1; i >= 0; i--)
{
index = string.indexOf(validOperators[i]);
if(index >= 0)
return index;
}
return index;
}
public static int processEquation(String equation)
throws IllegalArgumentException
{
return evaluate(equation,'+',"0");
} public static void main(String[] args)
{
String usage = "Usage: java MathParser equation\nWhere equation is a series"
+ " of integers separated by valid operators (+,-,/,*)"; if(args.length < 1 || args[0].length() == 0)
System.out.println(usage); String equation = args[0];
try
{
int result = MathParser.processEquation(equation);
System.out.println("The result of your equation ("
+ equation + ") is: " + result);
}
catch(IllegalArgumentException iae)
{
System.out.println(iae.getMessage() + "\n" + usage);
}
}
}
You could use some parser generator like JavaCC.
Basically, you define the grammar in Javacc, it will build the ast for you.
Then simply evaluate the ast.
As long as you feel comfortable with BNF, you are ok. JavaCC uses LL(1), and you don't have to deal with the tricky optimization part.