AuD
Lecture 'Algorithmen und Datenstrukturen' (code examples)
aud.example.expr.ExpressionParser Class Reference

Simple expression parser. More...

+ Collaboration diagram for aud.example.expr.ExpressionParser:

Public Member Functions

ExpressionTree parse (String input)
 parse input More...
 
void setVerbose (boolean b)
 set verbose mode (report state to System.err) More...
 

Static Public Member Functions

static void main (String[] args)
 test and example for usage More...
 

Protected Member Functions

String errorNear ()
 helper: generate a simple error message More...
 
int lookahead ()
 helper: "lookahead" is the usual phrasing More...
 
void nextToken ()
 helper: consume current token and advance to next token More...
 
String matchedText ()
 helper: get match corresponding to lookahead More...
 
void expect (int tokenid, String text)
 helper: check token (without calling nextToken!) More...
 
void verbose (int level, String message)
 helper: print out information More...
 
ExpressionTree expression (int level)
 parse expression More...
 
ExpressionTree sum (int level)
 parse sum More...
 
ExpressionTree product (int level)
 parse product More...
 
ExpressionTree factor (int level)
 parse factor More...
 

Detailed Description

Simple expression parser.

Build ExpressionTree from (infix) string representation of a term.

Implements a top-down recusive descent parser based on the following rules in BNF form (w/o <> to ease HTML formatting of this page)


expression ::= sum

sum        ::= product |
               product '+' sum | product '-' sum

product    ::= factor |
               factor '*' product | factor '/' product

factor     ::= number | symbol | '(' expression ')' |
               '+' factor | '-' factor

<number> and <symbol> are identified during the lexcical analysis. They correspond to AtomicExpression instances, which are used to build the tree. The same applies to operators '+',...

Notes

  • The left-hand-sides of the BNF rules are "mapped" to (recursive) method calls, e.g. expression.

  • The level argument is provided only for formatting verbose output.

  • The parser uses a Tokenizer for lexcical scanning.

  • The current token is used for "looking ahead" (lookahead): it is advanced (by nextToken only if this token is "consumed" by part of a BNF rule.

  • The current implementation has a problem! Do you see what and why?

See also
ExpressionTree
Tokenizer
AtomicExpression

Definition at line 61 of file ExpressionParser.java.

Member Function Documentation

◆ errorNear()

String aud.example.expr.ExpressionParser.errorNear ( )
protected

helper: generate a simple error message

Definition at line 85 of file ExpressionParser.java.

85 {
86 return "near '"+scanner_.matchedText()+
87 "'\nbefore '"+scanner_.remainder()+"'";
88 }
String matchedText()
get text of last match or call to next
String remainder()
get remaining text

Referenced by aud.example.expr.ExpressionParser.factor().

+ Here is the caller graph for this function:

◆ expect()

void aud.example.expr.ExpressionParser.expect ( int  tokenid,
String  text 
)
protected

helper: check token (without calling nextToken!)

Exceptions
SyntaxErrorif token does not match

Definition at line 112 of file ExpressionParser.java.

112 {
113 if (lookahead()!=tokenid)
114 throw new SyntaxError("expected '"+text+"' got '"+
115 scanner_.matchedText()+"'\nbefore '"+
116 scanner_.remainder());
117 }
int lookahead()
helper: "lookahead" is the usual phrasing

References aud.example.expr.ExpressionParser.lookahead().

Referenced by aud.example.expr.ExpressionParser.factor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ expression()

ExpressionTree aud.example.expr.ExpressionParser.expression ( int  level)
protected

parse expression

expression ::= sum

Definition at line 134 of file ExpressionParser.java.

134 {
135 verbose(level,"<expression>");
136 return sum(level+1);
137 }
ExpressionTree sum(int level)
parse sum
void verbose(int level, String message)
helper: print out information

References aud.example.expr.ExpressionParser.sum(), and aud.example.expr.ExpressionParser.verbose().

Referenced by aud.example.expr.ExpressionParser.factor().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ factor()

ExpressionTree aud.example.expr.ExpressionParser.factor ( int  level)
protected

parse factor


factor ::= number | symbol | '(' expression ')' |
           '+' factor | '-' factor

The last part of the rule correspong to unary plus and minus operators +x and -x. The implementation ignores unary plus, i.e., +x -> x.

Definition at line 199 of file ExpressionParser.java.

199 {
200 verbose(level,"<factor>");
201
202 ExpressionTree tree=null;
203
204 if (lookahead()==Tokenizer.NUMBER) {
205 tree=new ExpressionTree
206 (new Number(Double.parseDouble(matchedText())));
207 }
208 else if (lookahead()==Tokenizer.IDENTIFIER) {
209 tree=new ExpressionTree(new Symbol(matchedText()));
210 }
211 else if (lookahead()==Tokenizer.LEFT_PAREN) {
212 nextToken();
213 tree=expression(level+1);
214 expect(Tokenizer.RIGHT_PAREN,"closing parenthesis )");
215 }
216 else if (lookahead()==Tokenizer.PLUS) { // unary plus
217 nextToken();
218 return factor(level+1); // ignore: +x == x
219 }
220 else if (lookahead()==Tokenizer.MINUS) { // unary minus
221 nextToken();
222 return new ExpressionTree(new UnaryMinus(),factor(level+1),null);
223 }
224 else
225 throw new SyntaxError(errorNear());
226
227 nextToken();
228 assert(tree!=null);
229
230 return tree;
231 }
String errorNear()
helper: generate a simple error message
ExpressionTree factor(int level)
parse factor
void expect(int tokenid, String text)
helper: check token (without calling nextToken!)
ExpressionTree expression(int level)
parse expression
String matchedText()
helper: get match corresponding to lookahead
void nextToken()
helper: consume current token and advance to next token

References aud.example.expr.ExpressionParser.errorNear(), aud.example.expr.ExpressionParser.expect(), aud.example.expr.ExpressionParser.expression(), aud.example.expr.ExpressionParser.factor(), aud.example.expr.Tokenizer.IDENTIFIER, aud.example.expr.Tokenizer.LEFT_PAREN, aud.example.expr.ExpressionParser.lookahead(), aud.example.expr.ExpressionParser.matchedText(), aud.example.expr.Tokenizer.MINUS, aud.example.expr.ExpressionParser.nextToken(), aud.example.expr.Tokenizer.NUMBER, aud.example.expr.Tokenizer.PLUS, aud.example.expr.Tokenizer.RIGHT_PAREN, and aud.example.expr.ExpressionParser.verbose().

Referenced by aud.example.expr.ExpressionParser.factor(), and aud.example.expr.ExpressionParser.product().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ lookahead()

int aud.example.expr.ExpressionParser.lookahead ( )
protected

helper: "lookahead" is the usual phrasing

Definition at line 91 of file ExpressionParser.java.

91 {
92 return scanner_.matchedTokenId();
93 }
int matchedTokenId()
get result of last call to next()

Referenced by aud.example.expr.ExpressionParser.expect(), aud.example.expr.ExpressionParser.factor(), aud.example.expr.ExpressionParser.product(), and aud.example.expr.ExpressionParser.sum().

+ Here is the caller graph for this function:

◆ main()

static void aud.example.expr.ExpressionParser.main ( String[]  args)
static

test and example for usage

Definition at line 237 of file ExpressionParser.java.

237 {
238
239 String input=(args.length>0) ? args[0] : "1+2*(3+4)";
240
241 System.out.println("input = '"+input+"'");
242
243 ExpressionParser p=new ExpressionParser();
244 p.setVerbose(true);
245 ExpressionTree tree=p.parse(input);
246
247 System.out.println("output = '"+tree+"'");
248
249 System.out.println(tree.postorder().toString());
250
251 System.out.println(tree.toTikZ());
252 }

References aud.example.expr.ExpressionParser.parse(), aud.BinaryTree< T >.postorder(), aud.example.expr.ExpressionParser.setVerbose(), aud.BinaryTreeTraversal< T >.Traversal.toString(), and aud.BinaryTree< T >.toTikZ().

+ Here is the call graph for this function:

◆ matchedText()

String aud.example.expr.ExpressionParser.matchedText ( )
protected

helper: get match corresponding to lookahead

Returns
Tokenizer#matchedText

Definition at line 105 of file ExpressionParser.java.

105 {
106 return scanner_.matchedText();
107 }

Referenced by aud.example.expr.ExpressionParser.factor().

+ Here is the caller graph for this function:

◆ nextToken()

void aud.example.expr.ExpressionParser.nextToken ( )
protected

helper: consume current token and advance to next token

Definition at line 96 of file ExpressionParser.java.

96 {
97 if (scanner_.next()==Tokenizer.NO_MATCH)
98 throw new SyntaxError("unknown token: lexcial analysis failed at '"+
99 scanner_.remainder()+"'");
100 }
int next(Rule[] rules)
match remainder to table of rules @endiliteral

Referenced by aud.example.expr.ExpressionParser.factor(), aud.example.expr.ExpressionParser.product(), and aud.example.expr.ExpressionParser.sum().

+ Here is the caller graph for this function:

◆ parse()

ExpressionTree aud.example.expr.ExpressionParser.parse ( String  input)

parse input

Parameters
inputterm
Exceptions
SyntaxErroron syntax error
Returns
extression tree that represents input term

Definition at line 71 of file ExpressionParser.java.

71 {
72 scanner_ = new Tokenizer(input);
73 scanner_.next(); // use as "lookahead"
74 ExpressionTree tree=expression(0);
75 expect(Tokenizer.END_OF_INPUT,"<end of input>");
76 return tree;
77 }

Referenced by aud.example.expr.ExpressionParser.main(), and aud.example.expr.ExpressionTreeTraversal.main().

+ Here is the caller graph for this function:

◆ product()

ExpressionTree aud.example.expr.ExpressionParser.product ( int  level)
protected

parse product


product ::= factor |
            factor '*' product | factor '/' product

Definition at line 170 of file ExpressionParser.java.

170 {
171 verbose(level,"<product>");
172
173 ExpressionTree left=factor(level+1);
174
175 if (lookahead()==Tokenizer.TIMES) {
176 nextToken();
177 ExpressionTree right=product(level+1);
178 return new ExpressionTree(new Times(),left,right);
179 }
180 else if (lookahead()==Tokenizer.DIVIDE) {
181 nextToken();
182 ExpressionTree right=product(level+1);
183 return new ExpressionTree(new Divide(),left,right);
184 }
185
186 return left;
187 }
ExpressionTree product(int level)
parse product

References aud.example.expr.Tokenizer.DIVIDE, aud.example.expr.ExpressionParser.factor(), aud.example.expr.ExpressionParser.lookahead(), aud.example.expr.ExpressionParser.nextToken(), aud.example.expr.ExpressionParser.product(), aud.example.expr.Tokenizer.TIMES, and aud.example.expr.ExpressionParser.verbose().

Referenced by aud.example.expr.ExpressionParser.product(), and aud.example.expr.ExpressionParser.sum().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ setVerbose()

void aud.example.expr.ExpressionParser.setVerbose ( boolean  b)

set verbose mode (report state to System.err)

Definition at line 80 of file ExpressionParser.java.

80 {
81 verbose_=b;
82 }

Referenced by aud.example.expr.ExpressionParser.main().

+ Here is the caller graph for this function:

◆ sum()

ExpressionTree aud.example.expr.ExpressionParser.sum ( int  level)
protected

parse sum


sum ::= product |
        product '+' sum | product '-' sum

Definition at line 145 of file ExpressionParser.java.

145 {
146 verbose(level,"<sum>");
147
148 ExpressionTree left=product(level+1);
149
150 if (lookahead()==Tokenizer.PLUS) {
151 nextToken();
152 ExpressionTree right=sum(level+1);
153 return new ExpressionTree(new Plus(),left,right);
154 }
155 else if (lookahead()==Tokenizer.MINUS) {
156 nextToken();
157 ExpressionTree right=sum(level+1);
158 return new ExpressionTree(new Minus(),left,right);
159 }
160
161 return left;
162 }

References aud.example.expr.ExpressionParser.lookahead(), aud.example.expr.Tokenizer.MINUS, aud.example.expr.ExpressionParser.nextToken(), aud.example.expr.Tokenizer.PLUS, aud.example.expr.ExpressionParser.product(), aud.example.expr.ExpressionParser.sum(), and aud.example.expr.ExpressionParser.verbose().

Referenced by aud.example.expr.ExpressionParser.expression(), and aud.example.expr.ExpressionParser.sum().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ verbose()

void aud.example.expr.ExpressionParser.verbose ( int  level,
String  message 
)
protected

helper: print out information

Definition at line 120 of file ExpressionParser.java.

120 {
121 if (verbose_) {
122 System.err.println(Sys.indent(level)+message+
123 " ['"+scanner_.matchedText()+"','"+
124 scanner_.remainder()+"']");
125 }
126 }

Referenced by aud.example.expr.ExpressionParser.expression(), aud.example.expr.ExpressionParser.factor(), aud.example.expr.ExpressionParser.product(), and aud.example.expr.ExpressionParser.sum().

+ Here is the caller graph for this function:

The documentation for this class was generated from the following file: