import java.util.*; import java.io.*; public class Expression { Scanner scanner; private StringBuilder soFar = new StringBuilder(); public static void main(String[] argv) { Expression p = new Expression(new Scanner("5 * 3 + 2")); if (argv.length > 0) { // om man gett String s = padWithSpace(argv[0]); p = new Expression(new Scanner(s)); } double result = p.readExpr(); System.out.println("Parsed line: " + p.soFar); System.out.println(result); } /** * @param s Expression String where operators will be space separated * 1+2*3*(1-2) -> 1 + 2 * 3 * ( 1 - 2 ) */ static String padWithSpace(String s) { s = s.replaceAll("\\+", " + "); s = s.replaceAll("-" , " - "); s = s.replaceAll("\\*", " * "); s = s.replaceAll("/" , " / "); s = s.replaceAll("\\)", " ) "); s = s.replaceAll("\\(", " ( "); return s; } ///////////////////////////////////////////////////////////////////////////// // Constructor Expression(Scanner s) { scanner = s; } ///////////////////////////////////////////////////////////////////////////// // I/O methods - note must have space between tokens, 3*2 will not be parsed private double popValue() { String next = scanner.next(); soFar.append(" " + next); return Double.parseDouble(next); } private double popNegativeValue() { scanner.next("-"); String next = scanner.next(); soFar.append(" -" + next); return -1 * Double.parseDouble(next); } private String popToken() { String next = scanner.next(); soFar.append(" " + next); return next; } private boolean peek(char s) { if (scanner.hasNext()) { if (scanner.hasNext("\\" + s)) // if s = '*' then must prefix "\\*" return true; } return false; } ///////////////////////////////////////////////////////////////////////////// // Recursive descent // // Tip trace outputs with: // System.out.println("in method X:Parsed so far: " + soFar); double readExpr() { // expr ::= term | term + expr | term - expr double x = readTerm(); // expr ::= term ... if (peek('+')) { // expr ::= term + expr popToken(); x += readExpr(); } // TODO expr ::= term - expr // OBS lurigt, tänk på 1 - 2 + 3 // gör inte popToken() på en gång. return x; } protected double readTerm() { // term ::= factor | factor * term | factor / term double x = readFactor(); // term ::= factor if (peek('*')) { // term ::= factor * term popToken(); return x * readTerm(); } // TODO term ::= factor / term return x; } protected double readFactor() { // factor ::= ( expr ) | value if (peek('(')) { popToken(); // '(' double x = readExpr(); popToken(); // ')' // TODO check if ')' return x; } else { return readVal(); } } protected double readVal() { return popValue(); // TODO negative numbers? } }