Answered step by step
Verified Expert Solution
Link Copied!

Question

1 Approved Answer

Java Only Skeleton code: Evaluator.java: package evaluator; import java.util.*; import operand.Operand; import operator.Operator; public class Evaluator { private Stack operandStack; private Stack operatorStack; private StringTokenizer

image text in transcribed

Java Only

Skeleton code:

Evaluator.java:

package evaluator;

import java.util.*; import operand.Operand; import operator.Operator;

public class Evaluator {

private Stack operandStack; private Stack operatorStack;

private StringTokenizer tokenizer; private static final String DELIMITERS = "+-*^/() ";

public Evaluator() { operandStack = new Stack(); operatorStack = new Stack(); }

public int eval(String expression) { String token;

// The 3rd argument is true to indicate that the delimiters should be used // as tokens, too. But, we'll need to remember to filter out spaces. this.tokenizer = new StringTokenizer(expression, DELIMITERS, true);

while (this.tokenizer.hasMoreTokens()) { // filter out spaces if (!(token = this.tokenizer.nextToken()).equals(" ")) { // check if token is an operand if (Operand.check(token)) { operandStack.push(new Operand(token)); } else { if (!Operator.check(token)) { System.out.println("*****invalid token******"); System.exit(1); }

// TODO Operator is abstract - this line will need to be fixed: // ( The Operator class should contain an instance of a HashMap, // and values will be instances of the Operators. See Operator class // skeleton for an example. ) Operator newOperator = null; // new Operator( token );

while (operatorStack.peek().priority() >= newOperator.priority()) { // note that when we eval the expression 1 - 2 we will // push the 1 then the 2 and then do the subtraction operation // This means that the first number to be popped is the // second operand, not the first operand - see the following code Operator oldOpr = operatorStack.pop(); Operand op2 = operandStack.pop(); Operand op1 = operandStack.pop(); operandStack.push(oldOpr.execute(op1, op2)); }

operatorStack.push(newOperator); } } }

// Control gets here when we've picked up all of the tokens; you must add // code to complete the evaluation - consider how the code given here // will evaluate the expression 1+2*3 // When we have no more tokens to scan, the operand stack will contain 1 2 // and the operator stack will have + * with 2 and * on the top; // In order to complete the evaluation we must empty the stacks (except // the init operator on the operator stack); that is, we should keep // evaluating the operator stack until empty // Suggestion: create a method that takes an operator as argument and // then executes the while loop; also, move the stacks out of the main // method

return 0; }

/** * Class to help test your Evaluator: * javac EvaluatorTester * java EvaluatorTester "1+2" "3*5" */ public static void main(String[] args) { Evaluator evaluator = new Evaluator();

for (String arg : args) { System.out.format("%s = %d ", arg, evaluator.eval(arg)); } } }

Operand.java

package operand;

public class Operand {

public Operand( String token ) {

}

public Operand( int value ) {

}

public int getValue() { return 0; }

public static boolean check( String token ) { return false; } }

Operator.java:

package operator;

import operand.Operand;

public abstract class Operator {

// The Operator class should contain an instance of a HashMap // This map will use keys as the tokens we're interested in, // and values will be instances of the Operators.

// Example: // Where does this declaration go? What should its access level be? // Class or instance variable? Is this the right declaration? // HashMap operators = new HashMap(); // operators.put( "+", new AdditionOperator() ); // operators.put( "-", new SubtractionOperator() );

public abstract int priority();

public abstract Operand execute(Operand leftOperand, Operand rightOperand);

public static boolean check(String token) { return false; } }

Evaluatortest.java:

package tests;

import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals;

import evaluator.Evaluator;

public class EvaluatorTest { @Test void testSimpleAddition() { Evaluator evaluator = new Evaluator();

assertEquals(3, evaluator.eval("1 +2")); }

@Test void testSimpleDivision() { Evaluator evaluator = new Evaluator();

assertEquals(0, evaluator.eval("1/2")); }

@Test void testSimpleExpression() { Evaluator evaluator = new Evaluator();

assertEquals(7, evaluator.eval("1+2*3")); }

@Test void testSimpleParenthesizedExpression() { Evaluator evaluator = new Evaluator();

assertEquals(9, evaluator.eval("(1+2)*3")); }

@Test void testComplexExpressionWithNegativeResult() { Evaluator evaluator = new Evaluator();

assertEquals(-1, evaluator.eval("2-(3/10)+2-5")); }

@Test void testAnotherComplexExpressionWithNegativeResult() { Evaluator evaluator = new Evaluator();

assertEquals(-6, evaluator.eval("(6-12*2)/3")); }

@Test void testSimpleExponentiation() { Evaluator evaluator = new Evaluator();

assertEquals(9, evaluator.eval("3^2")); }

@Test void testSlightlyMoreComplexExponentiation() { Evaluator evaluator = new Evaluator();

assertEquals(4, evaluator.eval("3^2/2")); }

@Test void testHardMode() { Evaluator evaluator = new Evaluator();

assertEquals(1176, evaluator.eval("2+3-5*((2-3)*2-5*2+3*(2-3-5-5*6)+4/2)*2-9")); }

@Test void testProperStackUsage() { Evaluator evaluator = new Evaluator();

// Stacks should be emptied and in a valid state after the first evaluation occurs, // so the second evaluation should run without exception and provide assertEquals(6, evaluator.eval("1+2+3")); assertEquals(1, evaluator.eval("10-8-1")); } }

Operandtest.java:

package tests;

import static org.junit.Assert.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue;

import java.util.ArrayList; import java.util.Arrays;

import org.junit.jupiter.api.Test; import operand.Operand;

public class OperandTest { @Test void testCheck() { ArrayList validOperands = new ArrayList(Arrays.asList( "0", "1", "2", "3", "4", "5", "6", "7", "8", "9" ));

validOperands.forEach(operand -> assertTrue(Operand.check(operand))); assertFalse(Operand.check("a")); }

@Test void testGetValueFromOriginalString() { Operand operandOne = new Operand("3"); assertEquals(3, operandOne.getValue()); } @Test void testGetValueFromOriginalInt() { Operand operandTwo = new Operand(7); assertEquals(7, operandTwo.getValue()); } }

Operatortest.java:

package tests;

import org.junit.jupiter.api.Test; import static org.junit.Assert.assertTrue; import static org.junit.jupiter.api.Assertions.assertFalse;

import java.util.ArrayList; import java.util.Arrays;

import operator.Operator;

public class OperatorTest { @Test void testCheck() { ArrayList validOperators = new ArrayList(Arrays.asList( "+", "-", "*", "/", "^" ));

validOperators.forEach(operator -> assertTrue(Operator.check(operator))); assertFalse(Operator.check("1")); } }

The expressions are composed of integer operands and operators drawn from the set +. Requirement 3 Implement the following classes: The algorithm that is partially implemented in nval processes the tokens in the expression string using two stacks; one tor operators and one for operands (alcorithm reproduced here from htt sicsis.pace.edu' murthy/ProgrammingProblemsi 16 Evaluation of infix expressions): - If an operand token is scanned: an operand object is created from the token, and pushed to the operand Strack - If an operator token is scanned, and the operator stack is empty, then an operator object is created from the token, and pushed to the operator stack - If an operator token is scanned, and the cperator stack is not empty, and the operator's precedence is gregter than the precedence of the opcrat or at the top of the stack, then an operator object is created trom the token, and pushed to the operator stack - If the token is 6 , an oparator object is created from the token, and pushed to the operator stack - If the token is \}, then process Operators until the corresponding \{ is encountered. The Oyere_or class is the abstract base class for all of our operators. This class Pop the ( operator. serves as the root of our Strategy Pattern, as well as a repository that allows the wuluator class to retrieve a concrete instance of an Operatar. - If none of the above cases apply, proceas an operator. Note that the res shvap that stores instances of cperators is private! You must provide a means by which the Iva-uator can ask the oparator for concrete oparator instances whour wolating encepsulation. Processing an Dperator means to: In addition, the following methods must be implemented: - Pop the operand stack twice (tor each operand - note the orderili) - boolean checki sering token I - Pop the operator stack This method should retum true if the token passed as a parameter is a valid operator token - Execute the operator with the two operands - atitract int priuzityoj - Push the result orito the operand Stack This method gives us a way to specity the priarity tor each of the subclasses created from Operatcr When all tokens are read, process operators until the operator stack is empty. rtchtoperand ! This method is the strategy in our Strategy Pattern, where we will define the specific algorithm (addition, subtraction, etc.) for the subclass, and return the gperand Requirement 1 resulting from the operation. Implement the above algorithm within the Evaluator class. Individual orerator classes must be subclassed trom ope rat or to implement each of the operations allowed in the expressions defined above. Pemember to properly Requirement 2 organize your code! (Multiple classes should not be detined in a single file, and classes Test this implementation with expressions that test all possible cases (you may use the should be crganized into packages when appropriate.)

Step by Step Solution

There are 3 Steps involved in it

Step: 1

blur-text-image

Get Instant Access to Expert-Tailored Solutions

See step-by-step solutions with expert insights and AI powered tools for academic success

Step: 2

blur-text-image

Step: 3

blur-text-image

Ace Your Homework with AI

Get the answers you need in no time with our AI-driven, step-by-step assistance

Get Started

Students also viewed these Databases questions