/* * Copyright 2010 NCHOVY * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.krakenapps.bnf; import static org.krakenapps.bnf.Syntax.*; import static org.junit.Assert.*; import java.text.ParseException; import java.util.ArrayList; import java.util.List; import org.junit.Test; public class CalculatorTest { @SuppressWarnings("unchecked") @Test public void test() throws ParseException { Syntax s = new Syntax(); s.add("expr", new ExprParser(), ref("factor"), option(repeat(rule(choice(t("+"), t("-")), ref("factor"))))); s.add("factor", new FactorParser(), uint()); s.addRoot("expr"); Expr expr = (Expr) s.eval("1"); assertEquals(1, expr.eval()); List<Expr> exprs = (List<Expr>) s.eval("1 + 2 - 3 - 4"); System.out.println(exprs); int eval = 0; for (Expr e : exprs) { eval += e.eval(); } assertEquals(-4, eval); } private static class Expr { private Integer value; private String sign; private Expr expr; public Expr(int value) { this.value = value; } public Expr(String sign, Expr expr) { this.sign = sign; this.expr = expr; } public int eval() { if (value != null) return value; return sign.equals("-") ? -expr.eval() : expr.eval(); } @Override public String toString() { if (value != null) return value.toString(); return (sign.equals("-") ? "-" : "") + expr; } } private static class ExprParser implements Parser { @Override public Object parse(Binding b) { List<Expr> exprs = new ArrayList<Expr>(); if (b.getChildren() == null) return b.getValue(); exprs.add((Expr) b.getChildren()[0].getValue()); trace(b.getChildren()[1], exprs); return exprs; } private void trace(Binding b, List<Expr> exprs) { Binding[] children = b.getChildren(); if (children[0].getChildren() == null) { String sign = (String) children[0].getValue(); Expr expr = (Expr) children[1].getValue(); exprs.add(new Expr(sign, expr)); return; } String sign = (String) children[0].getChildren()[0].getValue(); Expr expr = (Expr) children[0].getChildren()[1].getValue(); exprs.add(new Expr(sign, expr)); trace(children[1], exprs); } } private static class FactorParser implements Parser { @Override public Object parse(Binding b) { return new Expr((Integer) b.getValue()); } } }