KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jmock > examples > calculator > InfixParser


1 /* Copyright (c) 2000-2004 jMock.org
2  */

3 package org.jmock.examples.calculator;
4
5 import java.io.IOException JavaDoc;
6
7
8 /**
9  * A recursive descent parser for the following grammar:
10  * <pre>
11  * expr = add_expr
12  * add_expr = mul_expr ("+" add_expr | "-" add_expr)*
13  * mul_expr = mul_expr ("*" pow_expr | "/" pow_expr)*
14  * pow_expr = val_expr ("^" pow_expr)*
15  * val_expr = number | varref | "(" expr ")"
16  * number ~= [0-9]+\.[0-9]+
17  * varref = identifier
18  * expr_list = expr ("," expr)*
19  * </pre>
20  */

21 public class InfixParser implements Parser
22 {
23     private ExpressionFactory factory;
24
25     public InfixParser() {
26         this(new SimpleExpressionFactory());
27     }
28
29     public InfixParser( ExpressionFactory factory ) {
30         this.factory = factory;
31     }
32
33     public Expression parse( String JavaDoc expressionString ) throws ParseException {
34         Lexer lexer = new Lexer(expressionString);
35         try {
36             return parseExpression(lexer);
37         }
38         catch (IOException JavaDoc ex) {
39             throw new ParseException("I/O error when parsing expression", ex);
40         }
41     }
42
43     private Expression parseExpression( Lexer lexer )
44             throws ParseException, IOException JavaDoc {
45         return parseAddExpr(lexer);
46     }
47
48     private Expression parseAddExpr( Lexer lexer )
49             throws ParseException, IOException JavaDoc {
50         Expression left = parseMulExpr(lexer);
51
52         for (; ;) {
53             Token token = lexer.nextToken();
54
55             switch (token.getType()) {
56             case Token.ADD:
57                 left = factory.newAddition(left, parseAddExpr(lexer));
58                 break;
59             case Token.SUBTRACT:
60                 left = factory.newSubtraction(left, parseAddExpr(lexer));
61                 break;
62             default:
63                 lexer.pushBack(token);
64                 return left;
65             }
66         }
67     }
68
69     private Expression parseMulExpr( Lexer lexer )
70             throws ParseException, IOException JavaDoc {
71         Expression left = parsePowExpr(lexer);
72
73         for (; ;) {
74             Token token = lexer.nextToken();
75
76             switch (token.getType()) {
77             case Token.MULTIPLY:
78                 left = factory.newMultiplication(left, parseMulExpr(lexer));
79                 break;
80             case Token.DIVIDE:
81                 left = factory.newDivision(left, parseMulExpr(lexer));
82                 break;
83             default:
84                 lexer.pushBack(token);
85                 return left;
86             }
87         }
88     }
89
90     private Expression parsePowExpr( Lexer lexer )
91             throws ParseException, IOException JavaDoc {
92         Expression left = parseValExpr(lexer);
93
94         for (; ;) {
95             Token token = lexer.nextToken();
96
97             switch (token.getType()) {
98             case Token.POWER:
99                 left = factory.newPower(left, parsePowExpr(lexer));
100                 break;
101             default:
102                 lexer.pushBack(token);
103                 return left;
104             }
105         }
106     }
107
108     private Expression parseValExpr( Lexer lexer )
109             throws ParseException, IOException JavaDoc {
110         Token token = lexer.nextToken();
111
112         switch (token.getType()) {
113         case Token.NUMBER:
114             return factory.newLiteral(parseValue(token.getValue()));
115
116         case Token.IDENTIFIER:
117             return factory.newVariableReference(token.getValue());
118
119         case Token.PAREN_OPEN:
120             {
121                 Expression result = parseExpression(lexer);
122
123                 if (lexer.nextToken().getType() != Token.PAREN_CLOSE) {
124                     throw new ParseException("closing parenthesis missing");
125                 }
126
127                 return result;
128             }
129
130         case Token.END:
131             throw new ParseException("unexpected end of input");
132
133         default:
134             throw new ParseException("unexpected token \"" + token.getValue() + "\"");
135         }
136     }
137
138     public double parseValue( String JavaDoc valueString )
139             throws ParseException {
140         try {
141             return Double.parseDouble(valueString);
142         }
143         catch (NumberFormatException JavaDoc ex) {
144             throw new ParseException("invalid number literal \"" + valueString + "\"");
145         }
146     }
147 }
148
149
Popular Tags