001: /*
002: * $Id: LogikusFacade.java,v 1.1 2003/08/19 01:12:57 jonesde Exp $
003: *
004: * Copyright (c) 1999 Steven J. Metsker.
005: * Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
006: *
007: * Permission is hereby granted, free of charge, to any person obtaining a
008: * copy of this software and associated documentation files (the "Software"),
009: * to deal in the Software without restriction, including without limitation
010: * the rights to use, copy, modify, merge, publish, distribute, sublicense,
011: * and/or sell copies of the Software, and to permit persons to whom the
012: * Software is furnished to do so, subject to the following conditions:
013: *
014: * The above copyright notice and this permission notice shall be included
015: * in all copies or substantial portions of the Software.
016: *
017: * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
018: * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
019: * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
020: * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
021: * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
022: * OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
023: * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
024: */
025:
026: package org.ofbiz.rules.logikus;
027:
028: import org.ofbiz.rules.parse.*;
029: import org.ofbiz.rules.parse.tokens.*;
030: import org.ofbiz.rules.engine.*;
031:
032: /**
033: * This class provides utility methods that simplify the use of the Logikus parser.
034: *
035: * @author Steven J. Metsker
036: * @version 1.0
037: */
038: public class LogikusFacade {
039:
040: /**
041: * Translate one axiom string into an Axiom object.
042: */
043: public static Axiom axiom(String s) {
044: return axiom(new TokenString(s));
045: }
046:
047: /**
048: * Parse the text of a Logikus program and return a
049: * <code>Program</code> object.
050: *
051: * @param String the text of the program
052: * @return a <code>Program</code> object
053: * @exception RuntimeException if parsing fails
054: */
055: public static Program program(String s) {
056: Program p = new Program();
057: TokenStringSource tss = new TokenStringSource(new Tokenizer(s),
058: ";");
059:
060: while (true) {
061: TokenString ts = tss.nextTokenString();
062:
063: if (ts == null) { // no more token strings
064: break;
065: }
066: p.addAxiom(axiom(ts));
067: }
068: return p;
069: }
070:
071: /**
072: * Parse the text of a Logikus query and return a
073: * <code>Query</code> object.
074: *
075: * @param String the text of the query
076: * @return a <code>Query</code> object
077: * @exception RuntimeException if parsing fails
078: */
079: public static Query query(String s, AxiomSource as) {
080: Object o = parse(new TokenString(s), LogikusParser.query(),
081: "query");
082:
083: if (o instanceof Fact) {
084: Fact f = (Fact) o;
085:
086: return new Query(as, f);
087: }
088: return new Query(as, (Rule) o);
089: }
090:
091: /**
092: * Translate the tokens for one axiom into an Axiom
093: * object (either a Fact or a Rule);
094: */
095: protected static Axiom axiom(TokenString ts) {
096: Parser p = new LogikusParser().axiom();
097: Object o = parse(ts, p, "axiom");
098:
099: return (Axiom) o;
100: }
101:
102: /**
103: * Parse the given token string with the given parser,
104: * throwing runtime exceptions if parsing fails
105: * or is incomplete.
106: */
107: protected static Object parse(TokenString ts, Parser p, String type) {
108: TokenAssembly ta = new TokenAssembly(ts);
109: Assembly out = p.bestMatch(ta);
110:
111: if (out == null) {
112: reportNoMatch(ts, type);
113: }
114: if (out.hasMoreElements()) {
115: // allow an extra semicolon
116: if (!out.remainder("").equals(";")) {
117: reportLeftovers(out, type);
118: }
119: }
120: return out.pop();
121: }
122:
123: /**
124: * Throws a runtime exception reporting an incomplete parse.
125: */
126: protected static Object reportLeftovers(Assembly out, String type) {
127: throw new LogikusException("> Input for " + type
128: + " appears complete after : \n> " + out.consumed(" ")
129: + "\n");
130: }
131:
132: /**
133: * Throws a runtime exception reporting failed parse.
134: */
135: protected static void reportNoMatch(TokenString ts, String type) {
136: // checkForUppercase(ts, type);
137: throw new LogikusException("> Cannot parse " + type + " : "
138: + ts + "\n");
139: }
140:
141: /**
142: * Throws an informative runtime exception if the provided
143: * string begins with an uppercase letter.
144: *
145: * NOTE: This is not currently used.
146: */
147: protected static void checkForUppercase(TokenString ts, String type) {
148: if (ts.length() > 0) {
149: Token t = ts.tokenAt(0);
150: String s = t.sval();
151:
152: if (s.length() > 0 && Character.isUpperCase(s.charAt(0))) {
153: throw new LogikusException("> Uppercase " + s
154: + " indicates a variable and cannot begin a "
155: + type + ".\n");
156: }
157: }
158: }
159: }
|