import java.util.Scanner; // Scanner is used strictly for testing purposes, // in the main() method /* ExpressionScanner.java ** CMPS 144 Spring 2020 Prog. Assg. #2 ** Author: R. McCloskey and < STUDENT's NAME > ** Collaborated with: ... ** Known Defects: ... */ /* An instance of this class, which is analogous to the java.util.Scanner ** class, acts as a scanner of an expression. That is, via calls to its ** next() method, it provides the tokens/elements within the expression, ** one after the other. There are five categories of tokens: ** ** (1) left parenthesis : "(" ** (2) right parenthesis : ")" ** (3) operator symbol: ** (3a) arithmetic operator: Any of "+", "-", "*", or "/" ** (3b) relational operator: Any of "==", "!=", "<", "<=", ">", ">=" ** (4) integer literal: Any maximal sequence of the digit characters '0'..'9'. ** (5) identifier: Any maximal sequence of letters 'A'..'Z' or 'a'..'z'. ** ** The hasNextX() (X = LeftParenthesis, Operator, etc.) methods allow the ** client to determine whether the next token (i.e., that to be returned ** by a call to next()) is in category X. */ public class ExpressionScanner { // class constants // --------------- //RWM: Suggested // Declarations of constants of type int having distinct values, // each one serving as the code for a particular token category. // instance variables //RWM: Suggested // ------------------ private final int N; // length of the expression to be scanned private String expr; // the expression to be scanned. private int left, right; // the next token is expr.substring(left..right) private int codeOfNext; // code indicating the category of the next // token (see class constants) // constructor // ----------- /* Initializes this ExpressionScanner object in preparation for scanning ** the given expression. */ public ExpressionScanner(String expression) { // STUB } // observers // --------- /* Reports whether or not there is a next token. */ public boolean hasNext() { return true; } // STUB /* Reports whether or not the next token is a left parenthesis. ** pre: hasNext() */ public boolean hasNextLeftParenthesis() { return true; } // STUB } /* Reports whether or not the next token is a right parenthesis. ** pre: hasNext() */ public boolean hasNextRightParenthesis() { return true; } // STUB /* Reports whether or not the next token is an operator ** pre: hasNext() */ public boolean hasNextOperator() { return true; } // STUB /* Reports whether or not the next token is an arithmetic operator ** pre: hasNext() */ public boolean hasNextArithOperator() { return true; } // STUB /* Reports whether or not the next token is a relational operator ** pre: hasNext() */ public boolean hasNextRelatOperator() { return true; } // STUB /* Reports whether or not the next token is an integer literal. ** pre: hasNext() */ public boolean hasNextIntLit() { return true; } // STUB /* Reports whether or not the next token is an identifier. ** pre: hasNext() */ public boolean hasNextIdentifier() { return true; } // STUB /* Reports whether or not the next token is of an unknown kind. ** pre: hasNext() */ public boolean hasNextUnknown() { return false; } // STUB // observer/mutator // ---------------- /* Returns the next token and advances past it. ** pre: hasNext() */ public String next() { //RWM: Suggested String result = expr.substring(left, right); left = right; findNext(); return result; } // private utilities // ----------------- /* Advances the values of instance variables left and right so that ** expr.substring(left,right) is the token following the one most ** recently found. */ private void findNext() { // STUB } /* Increases the value of instance variable 'left' until it either ** "falls off" the end of the string (i.e., becomes equal to N) or ** it reaches a position at which a non-whitespace character occurs. */ private void advancePastWhiteSpace() { while (left != N && Character.isWhitespace(expr.charAt(left))) { left = left + 1; } } /* Reports whether or not the given char value is an arithmetic operator. */ private boolean isArithOp(char ch) { final String ARITH_OPS = "+-*/"; return ARITH_OPS.indexOf(ch) != -1; } /* Reports whether or not the given character is one that can ** be the first character in a relational operator. */ private boolean isRelatOpSymbol(char ch) { final String RELAT_OPS = "<>!="; return RELAT_OPS.indexOf(ch) != -1; } // main() method for testing purposes // ---------------------------------- public static void main(String[] args) { Scanner input = new Scanner(System.in); System.out.print("Enter an expression: "); String response = input.nextLine(); ExpressionScanner eScanner = new ExpressionScanner(response); while (eScanner.hasNext()) { String remark; if (eScanner.hasNextLeftParenthesis()) { remark = ": left parenthesis"; } else if (eScanner.hasNextRightParenthesis()) { remark = ": right parenthesis"; } else if (eScanner.hasNextArithOperator()) { remark = ": arithmetic operator"; } else if (eScanner.hasNextRelatOperator()) { remark = ": relational operator"; } else if (eScanner.hasNextIntLit()) { remark = ": integer literal"; } else if (eScanner.hasNextIdentifier()) { remark = ": identifier"; } else if (eScanner.hasNextUnknown()) { remark = ": unknown"; } else { remark = ": impossible !!!!"; } System.out.println(eScanner.next() + remark); } } }