// @copyright@
// This file is part of nzdis-kif package. See the file LICENSE for copyright information and
// the terms and conditions for copying, distribution and modification of nzdis-kif package.
package nzdis.lang.kif.tool;
/**/
import nzdis.lang.kif.node.*;
import nzdis.lang.kif.pattern.analysis.*;
import nzdis.lang.kif.pattern.node.*;
import nzdis.lang.kif.pattern.lexer.*;
import nzdis.lang.kif.pattern.parser.*;
import java.util.*;
import java.io.*;
/**
* KIF Abstract Syntax Tree pattern matcher. This class is
* responsible for interpreting pattern against KIF AST. It follows
* the KIFPattern grammar (refer to KIFPattern.txt).
*
*
The intrpreter is not fully imlemented yet.
* Report what you need, and
* I will add it! (so called incremental development ;o)
*
NOW IMPLEMENTED ONLY:
* funterms, relsentences, and, not, or
* indvar seqvar
* = /=
*
*@author Mariusz Nowostawski
*@version @version@ $Revision: 1.1 $
*/
class PatternMatcherWalker extends DepthFirstAdapter {
nzdis.lang.kif.node.Node KIFtree;
nzdis.lang.kif.node.Node subtree;
Vector result;
Hashtable current;
boolean success;
Vector wordList = new Vector(1,1);
/**
* Performs pattern parsing and interpretation. The method takes two parameters,
* parses the pattern creating its own AST, interprets each node of this AST and
* tries to match it to KIF node (for KIF Start or KnowledgeBase node it will be
* list of nodes).
*@param String pattern, this is simple the pattern in KIFPattern grammar
*@param Node astKIF, this should point to the KIF node after KIF parsing
*@return array of Hashtables. For each matching node to the pattern there
* is single Hashtable element in the table. Each Hashtable element consists of
* entry "sentence" containing matching node, and for each pattern variable there is
* a matching node accessibile by this variable name, e.g. for :x1 there will be entry
* under "x1" with the matching node. */
public Hashtable[] match(String pattern, nzdis.lang.kif.node.Node astKIF){
result = new Vector(10,5);
current = new Hashtable();
nzdis.lang.kif.pattern.node.Node ast = null;
try {
/* lets prepare the tree of the pattern */
Lexer lexer = new Lexer(
new PushbackReader(
new StringReader(pattern)));
Parser parser = new Parser(lexer);
ast = parser.parse();
} catch(Exception e) {
e.printStackTrace();
}
KIFtree = subtree = astKIF;
/* processing the pattern tree */
ast.apply(this);
final Hashtable[] a = new Hashtable[result.size()];
result.copyInto(a);
return a;
}
/****************************************/
/**
* Starting node of the query interpretation. If the KIFtree variable
* is KIF Start or KnowledgeBase, we will walk through the pattern for each
* KIF sentence.
*/
public void caseStart(nzdis.lang.kif.pattern.node.Start node)
{
inStart(node);
/* Start */
if (subtree instanceof nzdis.lang.kif.node.Start){
subtree = ((nzdis.lang.kif.node.Start)subtree).getPBase();
}
/* KnowledgeBase */
if (subtree instanceof nzdis.lang.kif.node.AKnowledgeBase){
Object temp[] = ((nzdis.lang.kif.node.AKnowledgeBase)subtree).getForm().toArray();
for(int i = 0; i < temp.length; i++) {
success = true;
KIFtree = subtree = ((nzdis.lang.kif.node.PForm) temp[i]);
node.getPQuery().apply(this);
if(success && wordList.size()==0) {
current.put("sentence", (Object)KIFtree);
result.addElement(current);
current = new Hashtable();
}
}
node.getEOF().apply(this);
}else{
success = true;
node.getPQuery().apply(this);
node.getEOF().apply(this);
if(success) {
current.put("sentence", KIFtree);
result.addElement(current);
current = new Hashtable();
}
}
outStart(node);
}
/**
* Consumes PVar from the pattern. If appropriate term is available in
* wordList variable, we will add it to current hashtable under
* appropriate name, which is this variable identifier (without colon).
*/
public void caseAPVarTerm(nzdis.lang.kif.pattern.node.APVarTerm node) {
inAPVarTerm(node);
if(node.getPVar() != null) {
String s = node.getPVar().toString().trim();
s = s.substring(1); //get rid of colon
if(wordList.size()<1) {success = false; return;}
current.put(s, (Object)wordList.elementAt(0));
wordList.removeElementAt(0);
}
outAPVarTerm(node);
}
/**
* Consumes PList from the pattern. If appropriate term/terms are available in
* wordList variable, we will add it a single Vector and than this Vector
* object will be added to current hashtable under
* appropriate name, which is this variable identifier (without colons).
*/
public void caseAList(nzdis.lang.kif.pattern.node.AList node) {
inAList(node);
if(node.getPList() != null) {
Vector list = new Vector(5,5);
String s = node.getPList().toString().trim();
s = s.substring(2); //get rid of colons
Object temp[] = node.getTerm().toArray();
int num_left = temp.length;
int num_current = wordList.size();
if(num_left > num_current) {success = false; return;}
int i;
for(i = 0; i < num_current - num_left; i++){
list.addElement(wordList.elementAt(0));
wordList.removeElementAt(0);
}
/* add matching list to hashtable */
current.put(s, (Object)list);
/* match the rest of terms */
for(i = 0; i < temp.length; i++) {
((nzdis.lang.kif.pattern.node.PTerm) temp[i]).apply(this);
}
}
outAList(node);
}
/**
* Consumes the whole expression. Quite messy though.... NOT FINISHED!!!!
*/
public void caseAExpression(nzdis.lang.kif.pattern.node.AExpression node) {
inAExpression(node);
if(wordList.size()>0) {
subtree = (nzdis.lang.kif.node.Node) wordList.elementAt(0);
wordList.removeElementAt(0);
}
Vector oldWordList = wordList;
int i = 0;
/****************/
/* SentenceForm */
if (subtree instanceof nzdis.lang.kif.node.ASentenceForm){
subtree = ((nzdis.lang.kif.node.ASentenceForm)subtree).getSentence(); i++;
}
/* DefinitionForm */
if (subtree instanceof nzdis.lang.kif.node.ADefinitionForm){
subtree = ((nzdis.lang.kif.node.ADefinitionForm)subtree).getDefinition(); i++;
}
/***************/
/* ConstantSentence failure! */
if (subtree instanceof nzdis.lang.kif.node.AConstantSentence){
success = false;
return;
}
/* EquationSentence */
if (subtree instanceof nzdis.lang.kif.node.AEquationSentence){
subtree = ((nzdis.lang.kif.node.AEquationSentence)subtree).getEquation(); i++;
}
/* InequalitySentence */
if (subtree instanceof nzdis.lang.kif.node.AInequalitySentence){
subtree = ((nzdis.lang.kif.node.AInequalitySentence)subtree).getInequality(); i++;
}
/* RelsentSentence */
if (subtree instanceof nzdis.lang.kif.node.ARelsentSentence){
subtree = ((nzdis.lang.kif.node.ARelsentSentence)subtree).getRelsent(); i++;
}
/* LogsentSentence */
if (subtree instanceof nzdis.lang.kif.node.ALogsentSentence){
subtree = ((nzdis.lang.kif.node.ALogsentSentence)subtree).getLogsent(); i++;
}
/* QuantsentSentence */
if (subtree instanceof nzdis.lang.kif.node.AQuantsentSentence){
subtree = ((nzdis.lang.kif.node.AQuantsentSentence)subtree).getQuantsent(); i++;
}
/* FuntermTerm */
if (subtree instanceof nzdis.lang.kif.node.AFuntermTerm){
subtree = ((nzdis.lang.kif.node.AFuntermTerm)subtree).getFunterm(); i++;
}
if (i==0) {success = false; return;}
int k;
/*********************/
/* AEquation */
if (subtree instanceof nzdis.lang.kif.node.AEquation){
wordList = new Vector(10,5);
if(((nzdis.lang.kif.node.AEquation)subtree).getEq() != null) {
wordList.addElement(((nzdis.lang.kif.node.AEquation)subtree).getEq());
}
if(((nzdis.lang.kif.node.AEquation)subtree).getLeft() != null) {
wordList.addElement(((nzdis.lang.kif.node.AEquation)subtree).getLeft());
}
if(((nzdis.lang.kif.node.AEquation)subtree).getRight() != null) {
wordList.addElement(((nzdis.lang.kif.node.AEquation)subtree).getRight());
}
}
/* AInequality */
if (subtree instanceof nzdis.lang.kif.node.AInequality){
wordList = new Vector(10,5);
if(((nzdis.lang.kif.node.AInequality)subtree).getIneq() != null) {
wordList.addElement(((nzdis.lang.kif.node.AInequality)subtree).getIneq());
}
if(((nzdis.lang.kif.node.AInequality)subtree).getLeft() != null) {
wordList.addElement(((nzdis.lang.kif.node.AInequality)subtree).getLeft());
}
if(((nzdis.lang.kif.node.AInequality)subtree).getRight() != null) {
wordList.addElement(((nzdis.lang.kif.node.AInequality)subtree).getRight());
}
}
/********************/
/* AImplicitRelsent */
if (subtree instanceof nzdis.lang.kif.node.AImplicitRelsent){
wordList = new Vector(5,5);
if(((nzdis.lang.kif.node.AImplicitRelsent)subtree).getConstant() != null){
wordList.addElement(((nzdis.lang.kif.node.AImplicitRelsent)subtree).getConstant());
}
Object temp[] = ((nzdis.lang.kif.node.AImplicitRelsent)subtree).getTerm().toArray();
for(k = 0; k < temp.length; k++) {
wordList.addElement((nzdis.lang.kif.node.PTerm) temp[k]);
}
if(((nzdis.lang.kif.node.AImplicitRelsent)subtree).getSeqvar() != null) {
wordList.addElement(((nzdis.lang.kif.node.AImplicitRelsent)subtree).getSeqvar());
}
}
/***********************/
/* AConjunctionLogsent */
if (subtree instanceof nzdis.lang.kif.node.AConjunctionLogsent){
wordList = new Vector(5,5);
if(((nzdis.lang.kif.node.AConjunctionLogsent)subtree).getAnd() != null) {
wordList.addElement(((nzdis.lang.kif.node.AConjunctionLogsent)subtree).getAnd());
}
Object temp[] = ((nzdis.lang.kif.node.AConjunctionLogsent)subtree).getSentence().toArray();
for(k = 0; k < temp.length; k++) {
wordList.addElement((nzdis.lang.kif.node.PSentence) temp[k]);
}
}
/* ADisjunctionLogsent */
if (subtree instanceof nzdis.lang.kif.node.ADisjunctionLogsent){
wordList = new Vector(5,5);
if(((nzdis.lang.kif.node.ADisjunctionLogsent)subtree).getOr() != null) {
wordList.addElement(((nzdis.lang.kif.node.ADisjunctionLogsent)subtree).getOr());
}
Object temp[] = ((nzdis.lang.kif.node.ADisjunctionLogsent)subtree).getSentence().toArray();
for(k = 0; k < temp.length; k++) {
wordList.addElement((nzdis.lang.kif.node.PSentence) temp[k]);
}
}
/* ANegationLogsent */
if (subtree instanceof nzdis.lang.kif.node.ANegationLogsent){
wordList = new Vector(5,5);
if(((nzdis.lang.kif.node.ANegationLogsent)subtree).getNot() != null) {
wordList.addElement(((nzdis.lang.kif.node.ANegationLogsent)subtree).getNot());
}
if(((nzdis.lang.kif.node.ANegationLogsent)subtree).getSentence() != null) {
wordList.addElement(((nzdis.lang.kif.node.ANegationLogsent)subtree).getSentence());
}
}
/*********************/
/* ImplicitFunterm */
if (subtree instanceof nzdis.lang.kif.node.AImplicitFunterm) {
wordList = new Vector(10,5);
if(((nzdis.lang.kif.node.AImplicitFunterm)subtree).getConstant() != null){
wordList.addElement(((nzdis.lang.kif.node.AImplicitFunterm)subtree).getConstant());
}
Object temp[] = ((nzdis.lang.kif.node.AImplicitFunterm)subtree).getTerm().toArray();
for(k = 0; k < temp.length; k++) {
wordList.addElement((nzdis.lang.kif.node.PTerm) temp[k]);
}
if(((nzdis.lang.kif.node.AImplicitFunterm)subtree).getSeqvar() != null){
wordList.addElement(((nzdis.lang.kif.node.AImplicitFunterm)subtree).getSeqvar());
}
}
/************************************/
/* well, proceed with our tokens from
query string int this expression */
Object temp[] = node.getLeft().toArray();
for(int j = 0; j < temp.length; j++) {
((nzdis.lang.kif.pattern.node.PTerm) temp[j]).apply(this);
}
if(node.getList() != null) {
node.getList().apply(this);
}
wordList = oldWordList;
outAExpression(node);
}
/**
* Consumes word from the query string. Checks if there is proper object waiting
* in the wordList table, must be such token as elementAt(0), which will give
* true in compareWords method - string.equalsIgnoreCase() */
public void caseAWordConstant(nzdis.lang.kif.pattern.node.AWordConstant node) {
inAWordConstant(node);
if(node.getWord() != null) {
String s = node.getWord().toString().trim();
if(compareWords(s))
wordList.removeElementAt(0);
else
success = false;
}
outAWordConstant(node);
}
/**
* Consumes indvar from the query string. Checks if there is proper object waiting
* in the wordList table, must be indvar token as elementAt(0), with the same
* variable name as in query. */
public void caseAIndvar(nzdis.lang.kif.pattern.node.AIndvar node) {
inAIndvar(node);
if(node.getTIndvar() != null) {
String s = node.getTIndvar().toString().trim();
if(compareWords(s))
wordList.removeElementAt(0);
else
success = false;
}
outAIndvar(node);
}
/**
* Consumes seqvar from the query string. Checks if there is proper object waiting
* in the wordList table, must be seqvar token as elementAt(0), with the same
* variable name as in query. */
public void caseASeqvar(nzdis.lang.kif.pattern.node.ASeqvar node) {
inASeqvar(node);
if(node.getTSeqvar() != null) {
String s = node.getTSeqvar().toString().trim();
if(compareWords(s))
wordList.removeElementAt(0);
else
success = false;
}
outASeqvar(node);
}
/**
* Consumes '=' symbol. Checks if there is proper object waiting
* in the wordList table, must be TEq token as elementAt(0). */
public void caseAEqDefined(nzdis.lang.kif.pattern.node.AEqDefined node) {
inAEqDefined(node);
if(node.getEq() != null) {
if(wordList.size()<1) {success = false; return;}
nzdis.lang.kif.node.Node term = (nzdis.lang.kif.node.Node)wordList.elementAt(0);
if(term instanceof nzdis.lang.kif.node.TEq)
wordList.removeElementAt(0);
else
success = false;
}
outAEqDefined(node);
}
/**
* Consumes '/=' symbol. Checks if there is proper object waiting
* in the wordList table, must be TIneq token as elementAt(0). */
public void caseAIneqDefined(nzdis.lang.kif.pattern.node.AIneqDefined node) {
inAIneqDefined(node);
if(node.getIneq() != null) {
if(wordList.size()<1) {success = false; return;}
nzdis.lang.kif.node.Node term = (nzdis.lang.kif.node.Node)wordList.elementAt(0);
if(term instanceof nzdis.lang.kif.node.TIneq)
wordList.removeElementAt(0);
else success = false;
}
outAIneqDefined(node);
}
/**
* Consumes 'not' symbol. Checks if there is proper object waiting
* in the wordList table, must be TNot token as elementAt(0). */
public void caseANotDefined(nzdis.lang.kif.pattern.node.ANotDefined node) {
inANotDefined(node);
if(node.getNot() != null) {
if(wordList.size()<1) {success = false; return;}
nzdis.lang.kif.node.Node term = (nzdis.lang.kif.node.Node)wordList.elementAt(0);
if(term instanceof nzdis.lang.kif.node.TNot)
wordList.removeElementAt(0);
else success = false;
}
outANotDefined(node);
}
/**
* Consumes 'and' symbol. Checks if there is proper object waiting
* in the wordList table, must be TAnd token as elementAt(0). */
public void caseAAndDefined(nzdis.lang.kif.pattern.node.AAndDefined node) {
inAAndDefined(node);
if(node.getAnd() != null) {
if(wordList.size()<1) {success = false; return;}
nzdis.lang.kif.node.Node term = (nzdis.lang.kif.node.Node)wordList.elementAt(0);
if(term instanceof nzdis.lang.kif.node.TAnd)
wordList.removeElementAt(0);
else success = false;
}
outAAndDefined(node);
}
/**
* Consumes 'or' symbol. Checks if there is proper object waiting
* in the wordList table, must be TOr token as elementAt(0). */
public void caseAOrDefined(nzdis.lang.kif.pattern.node.AOrDefined node)
{
inAOrDefined(node);
if(node.getOr() != null) {
if(wordList.size()<1) {success = false; return;}
nzdis.lang.kif.node.Node term = (nzdis.lang.kif.node.Node)wordList.elementAt(0);
if(term instanceof nzdis.lang.kif.node.TOr)
wordList.removeElementAt(0);
else success = false;
}
outAOrDefined(node);
}
/** ** ** **
*/
public boolean compareWords(String s){
if(wordList.size()<1) return false;
String ws = wordList.elementAt(0).toString().trim();
return ws.equalsIgnoreCase(s);
}
}
/* *********** end of file **************** */