001 package aima.logic.fol.parsing; 002 003 import java.util.ArrayList; 004 import java.util.List; 005 006 import aima.logic.common.LogicTokenTypes; 007 import aima.logic.common.Token; 008 import aima.logic.fol.domain.FOLDomain; 009 import aima.logic.fol.parsing.ast.ConnectedSentence; 010 import aima.logic.fol.parsing.ast.Constant; 011 import aima.logic.fol.parsing.ast.Function; 012 import aima.logic.fol.parsing.ast.NotSentence; 013 import aima.logic.fol.parsing.ast.Predicate; 014 import aima.logic.fol.parsing.ast.QuantifiedSentence; 015 import aima.logic.fol.parsing.ast.Sentence; 016 import aima.logic.fol.parsing.ast.Term; 017 import aima.logic.fol.parsing.ast.TermEquality; 018 import aima.logic.fol.parsing.ast.Variable; 019 020 /** 021 * @author Ravi Mohan 022 * 023 */ 024 public class FOLParser { 025 private FOLLexer lexer; 026 027 protected Token[] lookAheadBuffer; 028 029 protected int lookAhead = 1; 030 031 public FOLParser(FOLLexer lexer) { 032 this.lexer = lexer; 033 lookAheadBuffer = new Token[lookAhead]; 034 } 035 036 public FOLParser(FOLDomain domain) { 037 this(new FOLLexer(domain)); 038 } 039 040 public FOLDomain getFOLDomain() { 041 return lexer.getFOLDomain(); 042 } 043 044 public Sentence parse(String s) { 045 setUpToParse(s); 046 return parseSentence(); 047 } 048 049 public void setUpToParse(String s) { 050 lexer.clear(); 051 lookAheadBuffer = new Token[1]; 052 lexer.setInput(s); 053 fillLookAheadBuffer(); 054 055 } 056 057 private Term parseTerm() { 058 Token t = lookAhead(1); 059 int tokenType = t.getType(); 060 if (tokenType == LogicTokenTypes.CONSTANT) { 061 return parseConstant(); 062 } else if (tokenType == LogicTokenTypes.VARIABLE) { 063 return parseVariable(); 064 } else if (tokenType == LogicTokenTypes.FUNCTION) { 065 return parseFunction(); 066 } 067 068 else { 069 return null; 070 } 071 } 072 073 public Term parseVariable() { 074 Token t = lookAhead(1); 075 String value = t.getText(); 076 consume(); 077 return new Variable(value); 078 } 079 080 public Term parseConstant() { 081 Token t = lookAhead(1); 082 String value = t.getText(); 083 consume(); 084 return new Constant(value); 085 } 086 087 public Term parseFunction() { 088 Token t = lookAhead(1); 089 String functionName = t.getText(); 090 List<Term> terms = processTerms(); 091 return new Function(functionName, terms); 092 } 093 094 public Sentence parsePredicate() { 095 Token t = lookAhead(1); 096 String predicateName = t.getText(); 097 List<Term> terms = processTerms(); 098 return new Predicate(predicateName, terms); 099 } 100 101 private List<Term> processTerms() { 102 consume(); 103 List<Term> terms = new ArrayList<Term>(); 104 match("("); 105 Term term = parseTerm(); 106 terms.add(term); 107 108 while (lookAhead(1).getType() == LogicTokenTypes.COMMA) { 109 match(","); 110 term = parseTerm(); 111 terms.add(term); 112 } 113 match(")"); 114 return terms; 115 } 116 117 public Sentence parseTermEquality() { 118 Term term1 = parseTerm(); 119 match("="); 120 // System.out.println("="); 121 Term term2 = parseTerm(); 122 return new TermEquality(term1, term2); 123 } 124 125 public Sentence parseNotSentence() { 126 match("NOT"); 127 return new NotSentence(parseSentence()); 128 } 129 130 private Sentence parseSentence() { 131 Token t = lookAhead(1); 132 if (lParen(t)) { 133 return parseParanthizedSentence(); 134 } else if ((lookAhead(1).getType() == LogicTokenTypes.QUANTIFIER)) { 135 136 return parseQuantifiedSentence(); 137 } else if (notToken(t)) { 138 return parseNotSentence(); 139 } else if (predicate(t)) { 140 return parsePredicate(); 141 } else if (term(t)) { 142 return parseTermEquality(); 143 } 144 145 throw new RuntimeException("parse failed with Token " + t.getText()); 146 } 147 148 private Sentence parseQuantifiedSentence() { 149 String quantifier = lookAhead(1).getText(); 150 consume(); 151 List<Variable> variables = new ArrayList<Variable>(); 152 Variable var = (Variable) parseVariable(); 153 variables.add(var); 154 while (lookAhead(1).getType() == LogicTokenTypes.COMMA) { 155 consume(); 156 var = (Variable) parseVariable(); 157 variables.add(var); 158 } 159 Sentence sentence = parseSentence(); 160 return new QuantifiedSentence(quantifier, variables, sentence); 161 } 162 163 private Sentence parseParanthizedSentence() { 164 match("("); 165 Sentence sen = parseSentence(); 166 while (binaryConnector(lookAhead(1))) { 167 String connector = lookAhead(1).getText(); 168 consume(); 169 Sentence other = parseSentence(); 170 sen = new ConnectedSentence(connector, sen, other); 171 } 172 match(")"); 173 return sen; /* new ParanthizedSentence */ 174 175 } 176 177 private boolean binaryConnector(Token t) { 178 if ((t.getType() == LogicTokenTypes.CONNECTOR) 179 && (!(t.getText().equals("NOT")))) { 180 return true; 181 } else { 182 return false; 183 } 184 } 185 186 private boolean lParen(Token t) { 187 if (t.getType() == LogicTokenTypes.LPAREN) { 188 return true; 189 } else { 190 return false; 191 } 192 } 193 194 private boolean term(Token t) { 195 if ((t.getType() == LogicTokenTypes.FUNCTION) 196 || (t.getType() == LogicTokenTypes.CONSTANT) 197 || (t.getType() == LogicTokenTypes.VARIABLE)) { 198 return true; 199 } else { 200 return false; 201 } 202 203 } 204 205 private boolean predicate(Token t) { 206 if ((t.getType() == LogicTokenTypes.PREDICATE)) { 207 return true; 208 } else { 209 return false; 210 } 211 } 212 213 private boolean notToken(Token t) { 214 if ((t.getType() == LogicTokenTypes.CONNECTOR) 215 && (t.getText().equals("NOT"))) { 216 return true; 217 } else { 218 return false; 219 } 220 } 221 222 protected Token lookAhead(int i) { 223 return lookAheadBuffer[i - 1]; 224 } 225 226 protected void consume() { 227 // System.out.println("consuming" +lookAheadBuffer[0].getText()); 228 loadNextTokenFromInput(); 229 // System.out.println("next token " +lookAheadBuffer[0].getText()); 230 } 231 232 protected void loadNextTokenFromInput() { 233 234 boolean eoiEncountered = false; 235 for (int i = 0; i < lookAhead - 1; i++) { 236 237 lookAheadBuffer[i] = lookAheadBuffer[i + 1]; 238 if (isEndOfInput(lookAheadBuffer[i])) { 239 eoiEncountered = true; 240 break; 241 } 242 } 243 if (!eoiEncountered) { 244 try { 245 lookAheadBuffer[lookAhead - 1] = lexer.nextToken(); 246 } catch (Exception e) { 247 e.printStackTrace(); 248 } 249 } 250 251 } 252 253 protected boolean isEndOfInput(Token t) { 254 return (t.getType() == LogicTokenTypes.EOI); 255 } 256 257 protected void fillLookAheadBuffer() { 258 for (int i = 0; i < lookAhead; i++) { 259 lookAheadBuffer[i] = lexer.nextToken(); 260 } 261 } 262 263 protected void match(String terminalSymbol) { 264 if (lookAhead(1).getText().equals(terminalSymbol)) { 265 consume(); 266 } else { 267 throw new RuntimeException( 268 "Syntax error detected at match. Expected " 269 + terminalSymbol + " but got " 270 + lookAhead(1).getText()); 271 } 272 273 } 274 275 }