1 /******************************************************************************* 2 * Copyright (c) 2009, 2018 Mountainminds GmbH & Co. KG and Contributors 3 * All rights reserved. This program and the accompanying materials 4 * are made available under the terms of the Eclipse Public License v1.0 5 * which accompanies this distribution, and is available at 6 * http://www.eclipse.org/legal/epl-v10.html 7 * 8 * Contributors: 9 * Marc R. Hoffmann - initial API and implementation 10 * 11 *******************************************************************************/ 12 package org.jacoco.examples.parser; 13 14 import static java.io.StreamTokenizer.TT_EOF; 15 import static java.io.StreamTokenizer.TT_NUMBER; 16 17 import java.io.IOException; 18 import java.io.StreamTokenizer; 19 import java.io.StringReader; 20 21 import org.jacoco.examples.expressions.Add; 22 import org.jacoco.examples.expressions.Const; 23 import org.jacoco.examples.expressions.Div; 24 import org.jacoco.examples.expressions.IExpression; 25 import org.jacoco.examples.expressions.Mul; 26 import org.jacoco.examples.expressions.Sub; 27 28 public class ExpressionParser { 29 30 private final StreamTokenizer tokenizer; 31 32 public ExpressionParser(final String s) throws IOException { 33 tokenizer = new StreamTokenizer(new StringReader(s)); 34 tokenizer.ordinaryChar('('); 35 tokenizer.ordinaryChar(')'); 36 tokenizer.ordinaryChar('+'); 37 tokenizer.ordinaryChar('-'); 38 tokenizer.ordinaryChar('*'); 39 tokenizer.ordinaryChar('/'); 40 } 41 42 public IExpression parse() throws IOException { 43 tokenizer.nextToken(); 44 final IExpression e = term(); 45 expect(TT_EOF); 46 return e; 47 } 48 49 private IExpression term() throws IOException { 50 IExpression e = product(); 51 while (true) { 52 if (accept('+')) { 53 e = new Add(e, product()); 54 } else if (accept('-')) { 55 e = new Sub(e, product()); 56 } else { 57 return e; 58 } 59 } 60 } 61 62 private IExpression product() throws IOException { 63 IExpression e = factor(); 64 while (true) { 65 if (accept('*')) { 66 e = new Mul(e, factor()); 67 } else if (accept('/')) { 68 e = new Div(e, factor()); 69 } else { 70 return e; 71 } 72 } 73 } 74 75 private IExpression factor() throws IOException { 76 final IExpression e; 77 if (accept('(')) { 78 e = term(); 79 expect(')'); 80 } else { 81 expect(TT_NUMBER); 82 e = new Const(tokenizer.nval); 83 } 84 return e; 85 } 86 87 private boolean accept(final int type) throws IOException { 88 if (tokenizer.ttype == type) { 89 tokenizer.nextToken(); 90 return true; 91 } 92 return false; 93 } 94 95 private void expect(final int type) throws IOException { 96 if (tokenizer.ttype != type) { 97 throw new IOException("Invalid Syntax."); 98 } 99 tokenizer.nextToken(); 100 } 101 102 } 103