General Interests & Hobbies > Java Programming

hey guys what do you think of my toy prefix notation calculator

<<< (2/2)

z:

--- Quote from: object on May 26, 2016, 05:22:52 PM ---Just a tip: Use java.util.Scanner rather than java.util.StringTokenizer, as that is more a legacy class these days.

Edit: I saw you're using both. Why?

--- End quote ---
Good point, I'll incorporate that now.

Here is the latest code. I refactored the inner class structure, but it's still not parsing arbitrary arguments (yet):

--- Code: Java ---import java.util.Iterator;import java.util.LinkedList;import java.util.Queue;import java.util.Scanner;import java.util.function.DoubleUnaryOperator;import java.util.function.DoubleBinaryOperator; /** * calc - a prefix notation calculator */public class calc {    public calc() {        Scanner scanner = new Scanner(System.in);        while(true) {            System.out.print("> ");            String expr = scanner.nextLine();            if(expr.equals("quit")) break;            if(expr.equals("help") || expr.equals("?"))                usage();            Queue<String> q = new LinkedList<>();            Scanner exprScanner = new Scanner(expr);            while(exprScanner.hasNext())                q.add(exprScanner.next());            System.out.println(q);            try {                Expression res = parse(q);                System.out.println(res.eval());            } catch(Exception e) {                System.err.println("Error: " + e.getMessage());            }        }    }     private Expression parse(Queue<String> q) throws Exception {        if(q.isEmpty()) throw new Exception("Invalid input.");        String token = q.remove().replace(")","");        try {            return new Number(Double.parseDouble(token));        } catch(NumberFormatException nfe) {            if(token.equals("(+")) {                return new Add(parse(q), parse(q));            } else if(token.equals("(-")) {                if(q.peek().contains(")"))                    return new Negate(parse(q));                else                    return new Subtract(parse(q), parse(q));            } else if(token.equals("(*")) {                return new Multiply(parse(q), parse(q));            } else if(token.equals("(/")) {                return new Divide(parse(q), parse(q));            } else if(token.equals("(sqrt")) {                return new SquareRoot(parse(q));            }        }        throw new Exception("Invalid input.");    }     public static void main(String[] args) throws Exception {        try {            new calc();        } catch(Exception e) {            System.exit(1);        }    }     private static void usage() {        System.out.println("calc - a prefix notation calculator");        System.out.println("Enter an expression below to be evaluated.");    }     public interface Expression {        public double eval();        public String toString();    }     static class Number implements Expression {        double val;         Number(double val) {            this.val = val;        }         public double eval() {            return val;        }         public String toString() {            return ""+val;        }    }     static class UnaryExpression implements Expression {        private String operator;        private double defaultValue;        private DoubleUnaryOperator op;        private Expression expression;         UnaryExpression(String operator, double defaultValue,                        DoubleUnaryOperator op, Expression expression) {            this.operator = operator;            this.defaultValue = defaultValue;            this.op = op;            this.expression = expression;        }         public double eval() {            return op.applyAsDouble(expression.eval());        }         public String toString() {            return operator + "(" + expression.toString() + ")";        }    }     static class BinaryExpression implements Expression {        private String operator;        private double defaultValue;        private DoubleBinaryOperator op;        private Queue<Expression> expressions;         BinaryExpression(String operator, double defaultValue,                         DoubleBinaryOperator op, Expression[] expressions) {            this.operator = operator;            this.defaultValue = defaultValue;            this.op = op;            this.expressions = new LinkedList<Expression>();            for(Expression expression : expressions)                this.expressions.add(expression);        }         public double eval() {            return expressions.stream()                              .mapToDouble(Expression::eval)                              .reduce(op)                              .orElse(defaultValue);        }         public String toString() {            Iterator it = expressions.iterator();            String ret = it.next().toString();            for(Expression expression : expressions)                ret += operator + it.next().toString();            return ret;        }    }     static class Negate extends UnaryExpression {        Negate(Expression expression) {            super("-", 0.0, (v) -> -v, expression);        }    }     static class SquareRoot extends UnaryExpression {        SquareRoot(Expression expression) {            super("?", 0.0, (v) -> Math.sqrt(v), expression);        }    }     static class Add extends BinaryExpression {        Add(Expression... expressions) {            super("+", 0.0, (l, r) -> l + r, expressions);        }    }     static class Subtract extends BinaryExpression {        Subtract(Expression... expressions) {            super("-", 0.0, (l, r) -> l - r, expressions);        }    }     static class Multiply extends BinaryExpression {        Multiply(Expression... expressions) {            super("*", 0.0, (l, r) -> l * r, expressions);        }    }     static class Divide extends BinaryExpression {        Divide(Expression... expressions) {            super("/", 0.0, (l, r) -> l / r, expressions);        }    }}

janetfdoss:
Whole of this thread is a master piece and shall convey the solution to many problems.

matzie:
Consider parsing it into a tree. Where the leaf nodes are numbers and all others will evaluate to expressions. If the tree contains an action(+,-)  in the leaf node then it is invalid syntax.

In your pre-order parsing you need to write them to the tree in pre-order form. Meaning the first symbol will be your root node.

Example:
+ 2 3

--- Code: ---(+) root
2  3
--- End code ---
+ - 1 2 3

--- Code: ---    +
  -   3
1  2
--- End code ---

Since it is a preoder parser your precedence is given by the order in which you write the terms.
If the tree has a format that shows correctly (where all numbers are the leaf's and all actions are the internal nodes) you are safe to use a stack parser to compute the value.

Your invalid ones:
+ 2 2 2 2

--- Code: ---    +
  2   2
(syntax error)



--- End code ---
- + 2 2


--- Code: ---     -
  +    ?
2   2
--- End code ---

Navigation

[0] Message Index

[*] Previous page

Go to full version
Powered by SMFPacks SEO Pro Mod |