001: /*
002: * JBoss, Home of Professional Open Source.
003: * Copyright 2006, Red Hat Middleware LLC, and individual contributors
004: * as indicated by the @author tags. See the copyright.txt file in the
005: * distribution for a full listing of individual contributors.
006: *
007: * This is free software; you can redistribute it and/or modify it
008: * under the terms of the GNU Lesser General Public License as
009: * published by the Free Software Foundation; either version 2.1 of
010: * the License, or (at your option) any later version.
011: *
012: * This software is distributed in the hope that it will be useful,
013: * but WITHOUT ANY WARRANTY; without even the implied warranty of
014: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
015: * Lesser General Public License for more details.
016: *
017: * You should have received a copy of the GNU Lesser General Public
018: * License along with this software; if not, write to the Free
019: * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
020: * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
021: */
022: package org.jboss.aspects.dbc.condition.parser;
023:
024: /**
025: * A very simple expression parser, for the reason that I really,
026: * really cannot get my head around defining grammars in
027: * JavaCC. If this grammar gets more complex I guess JavaCC
028: * is the way forward...
029: *
030: * @author <a href="mailto:kabir.khan@jboss.org">Kabir Khan</a>
031: * @version $Revision: 57186 $
032: */
033: public class ExpressionParser {
034: static final String FORALL = "forall ";
035: static final String EXISTS = "exists ";
036: static final String IMPLIES = " implies ";
037: static final String JAVA = "java: ";
038: static final String IN = " in ";
039: static final String SEPARATOR = " | ";
040:
041: public static Expression parseExpression(String expr) {
042: return parse(expr);
043: }
044:
045: private static Expression parse(String expr) {
046: expr = expr.trim();
047: if (expr.startsWith(FORALL)) {
048: return parseForAll(expr);
049: } else if (expr.startsWith(EXISTS)) {
050: return parseExists(expr);
051: } else if (expr.indexOf(IMPLIES) > 0) {
052: return parseImplies(expr);
053: } else if (expr.startsWith(JAVA)) {
054: return parseJava(expr);
055: } else {
056: return parseBoolean(expr);
057: }
058: }
059:
060: private static Expression parseForAll(String expr) {
061: int in = expr.indexOf(IN);
062: if (in < 0)
063: throw new RuntimeException(
064: "forall expressions must have an 'in' clause: "
065: + expr);
066:
067: String declaration = expr.substring(FORALL.length(), in);
068:
069: int sep = expr.indexOf(SEPARATOR);
070: if (sep < 0)
071: throw new RuntimeException(
072: "forall expressions must have a '|': " + expr);
073: String collection = expr.substring(in + IN.length(), sep);
074:
075: String body = expr.substring(sep + SEPARATOR.length());
076: Expression sub = parse(body);
077: ForAllExpression forAll = new ForAllExpression(declaration,
078: collection, sub);
079: return forAll;
080: }
081:
082: private static Expression parseExists(String expr) {
083: int in = expr.indexOf(IN);
084: if (in < 0)
085: throw new RuntimeException(
086: "exists expressions must have an 'in' clause: "
087: + expr);
088:
089: String declaration = expr.substring(EXISTS.length(), in);
090:
091: int sep = expr.indexOf(SEPARATOR);
092: if (sep < 0)
093: throw new RuntimeException(
094: "exists expressions must have a '|': " + expr);
095: String collection = expr.substring(in + IN.length(), sep);
096:
097: String body = expr.substring(sep + SEPARATOR.length());
098: Expression sub = parse(body);
099: ExistsExpression exists = new ExistsExpression(declaration,
100: collection, sub);
101: return exists;
102: }
103:
104: private static Expression parseImplies(String expr) {
105: int impl = expr.indexOf(IMPLIES);
106: String exprA = expr.substring(0, impl);
107: String exprB = expr.substring(impl + IMPLIES.length());
108:
109: if (exprA.trim().length() == 0 || exprB.trim().length() == 0) {
110: throw new RuntimeException(
111: "implies expressions must take two simple boolean expressions: "
112: + expr);
113: }
114:
115: if (exprA.endsWith(";")) {
116: exprA = expr.substring(0, expr.length() - 1);
117: }
118:
119: try {
120: Expression condA = parse(exprA);
121: Expression condB = parse(exprB);
122:
123: ImpliesExpression implies = new ImpliesExpression(
124: (BooleanExpression) condA,
125: (BooleanExpression) condB);
126: return implies;
127: } catch (ClassCastException e) {
128: throw new RuntimeException(
129: "implies expressions must take two simple boolean expressions: "
130: + expr);
131: }
132: }
133:
134: private static Expression parseJava(String expr) {
135: expr = expr.substring(JAVA.length());
136: return new JavaExpression(expr);
137: }
138:
139: private static Expression parseBoolean(String expr) {
140: if (expr.endsWith(";")) {
141: expr = expr.substring(0, expr.length() - 1);
142: }
143: return new BooleanExpression(expr);
144: }
145:
146: public static void main(String[] args) {
147: doit("a == b");
148: doit("a == b implies b == a");
149: doit("forall IEmployee e in getEmployees() | getRooms().contains(e.getOffice());");
150: doit("exists IEmployee e in getEmployees() | !getRooms().contains(e.getOffice())");
151: doit("forall IEmployee e1 in getEmployees() | forall IEmployee e2 in getEmployees() | (e1 != e2) implies e1.getOffice() != e2.getOffice()");
152: doit("java: for (int i = 0){i > 0;}");
153: }
154:
155: public static void doit(String str) {
156: System.out.println(str);
157: System.out.println();
158: Expression expr = ExpressionParser.parseExpression(str);
159: BeanshellGenerator gen = new BeanshellGenerator(expr);
160: System.out.println(gen.createBeanshellCode());
161: System.out.println("-----------------------");
162: }
163: }
|