📄 logikusparser.java
字号:
/*
* $Id: LogikusParser.java,v 1.1 2003/08/19 01:12:57 jonesde Exp $
*
* Copyright (c) 1999 Steven J. Metsker.
* Copyright (c) 2001 The Open For Business Project - www.ofbiz.org
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT
* OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
* THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
package org.ofbiz.rules.logikus;
import org.ofbiz.rules.parse.*;
import org.ofbiz.rules.parse.tokens.*;
/**
* <p>This class provides a parser for Logikus, a logic
* language similar to Prolog.
* <p>The grammar this class supports is:
* <blockquote><pre>
*
* <old> <!-- note: this is the original grammar, see the current one below -->
* structure = functor ('(' commaList(term) ')' | Empty);
* functor = '.' | LowercaseWord | QuotedString;
* term = structure | Num | list | variable;
* variable = UppercaseWord | '_';
* factor = '(' expression ')' | Num | variable;
* </old>
*
* axiom = structure (ruleDef | Empty);
* structure = functor ('(' commaList(term) ')');
* functor = '.' | LowercaseWord | UppercaseWord;
* term = structure | Num | QuotedString | list | variable;
* variable = LowercaseWord | UppercaseWord | '_';
* <br>
* ruleDef = ":-" commaList(condition);
* condition = structure | not | evaluation | comparison | list;
* <br>
* not = "not" structure ;
* <br>
* evaluation = '#' '(' arg ',' arg ')';
* comparison = operator '(' arg ',' arg ')';
* arg = expression | functor;
* operator = '<' | '>' | '=' | "<=" | ">=" | "!=" ;
* expression = phrase ('+' phrase | '-' phrase)*;
* phrase = factor ('*' factor | '/' factor)*;
* factor = '(' expression ')' | Num | QuotedString | variable;
* <br>
* list = '[' (listContents | Empty) ']';
* listContents = commaList(term) listTail;
* listTail = ('|' (variable | list)) | Empty;
* <br>
* commaList(p) = p (',' p)*;
* </pre></blockquote>
*
* The following program and query use most of the features of
* the Logikus grammar:
*
* <blockquote><pre>
* // program
* member(X, [X | Rest]);
* member(X, [Y | Rest]) :- member(X, Rest);
* primes([2, 3, 5, 7, 11, 13]);
* factor(X, P, Q) :-
* primes(Primes),
* member(P, Primes), member(Q, Primes), =(P*Q, X);
* <br>
* // query
* factor(91, A, B)
* <br>
* // results
* A = 7.0, B = 13.0
* A = 13.0, B = 7.0
* no
* </pre></blockquote>
*
* The class <code>LogikusFacade</code> simplifies the
* construction of <code>Program</code> and <code>Query</code>
* objects from the text given above. A Java program can prove
* the query to generate the results.
*
* <p>
* The class <code>LogikusIde</code> is an example of using the
* <code>Logikus</code> parser in practice. It uses
* <code>LogikusFacade</code> to create a <code>Query</code>,
* proves the query, and displays the query's variables for
* each proof. As in Prolog, the Logikus development
* environment prints "no" when no further proofs remain.
*
* @author Steven J. Metsker
* @version 1.0
*/
public class LogikusParser {
protected Sequence structure;
protected Sequence expression;
protected Sequence list;
/**
* Return a parser that recognizes the grammar:
*
* arg = expression | functor;
*/
protected Parser arg() {
Alternation a = new Alternation();
a.add(expression());
a.add(functor().setAssembler(new AtomAssembler()));
return a;
}
/**
* Return a parser that recognizes the grammar:
*
* <blockquote><pre>
* axiom = structure (ruleDef | Empty);
* </pre></blockquote>
*
* @return a parser that recognizes an axiom
*/
public Parser axiom() {
Sequence s = new Sequence("axiom");
s.add(structure());
Alternation a = new Alternation();
a.add(ruleDef());
a.add(new Empty());
s.add(a);
s.setAssembler(new AxiomAssembler());
return s;
}
/**
* Using the given parser, this method composes a new
* parser with the grammar:
*
* commaList(p) = p (',' p)*;
*
* The Logikus language uses this construction several
* times.
*/
protected static Sequence commaList(Parser p) {
Sequence commaP = new Track();
commaP.add(new Symbol(',').discard());
commaP.add(p);
Sequence s = new Sequence();
s.add(p);
s.add(new Repetition(commaP));
return s;
}
/**
* Return a parser that recognizes the grammar:
*
* <blockquote><pre>
* comparison = operator '(' arg ',' arg ')';
* </pre></blockquote>
*
* @return a parser that recognizes a comparison
*/
public Sequence comparison() {
Track t = new Track("comparison");
t.add(operator());
t.add(new Symbol('(').discard());
t.add(arg());
t.add(new Symbol(',').discard());
t.add(arg());
t.add(new Symbol(')').discard());
t.setAssembler(new ComparisonAssembler());
return t;
}
/**
* Return a parser that recognizes the grammar:
*
* <blockquote><pre>
* condition = structure | not | evaluation | comparison |
* list;
* </pre></blockquote>
*
* @return a parser that recognizes a condition
*/
public Alternation condition() {
Alternation a = new Alternation("condition");
a.add(structure());
a.add(not());
a.add(evaluation());
a.add(comparison());
a.add(list());
return a;
}
/**
* Return a parser that recognizes the grammar:
*
* divideFactor = '/' factor;
*/
protected Parser divideFactor() {
Sequence s = new Sequence("divideFactor");
s.add(new Symbol('/').discard());
s.add(factor());
s.setAssembler(new ArithmeticAssembler('/'));
return s;
}
/**
* Return a parser that recognizes the grammar:
*
* evaluation = '#' '(' arg ',' arg ')';
*
* For example, this parser will recognize
* "#(X, 12321/111)", translating it to an Evaluation
* object. When asked to prove itself, the Evaluation
* object will unify its first term with the value of
* its second term.
*/
protected Parser evaluation() {
Track t = new Track("evaluation");
t.add(new Symbol('#').discard());
t.add(new Symbol('(').discard());
t.add(arg());
t.add(new Symbol(',').discard());
t.add(arg());
t.add(new Symbol(')').discard());
t.setAssembler(new EvaluationAssembler());
return t;
}
/**
* Return a parser that recognizes the grammar:
*
* expression = phrase ('+' phrase | '-' phrase)*;
*/
protected Parser expression() {
/*
* This use of a static variable avoids the infinite
* recursion inherent in the language definition.
*/
if (expression == null) {
expression = new Sequence("expression");
expression.add(phrase());
Alternation a = new Alternation();
a.add(plusPhrase());
a.add(minusPhrase());
expression.add(new Repetition(a));
}
return expression;
}
/**
* Return a parser that recognizes the grammar:
*
* factor = '(' expression ')' | Num | QuotedString | variable;
*/
protected Parser factor() {
Alternation a = new Alternation("factor");
Sequence s = new Sequence();
s.add(new Symbol('(').discard());
s.add(expression());
s.add(new Symbol(')').discard());
a.add(s);
a.add(num());
a.add(string());
a.add(variable());
return a;
}
/**
* Return a parser that recognizes the grammar:
*
* functor = '.' | LowercaseWord | UppercaseWord;
*/
protected Parser functor() {
Alternation a = new Alternation("functor");
a.add(new LowercaseWord());
a.add(new UppercaseWord());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -