// @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 **************** */