/**
*
*/
package xhail.core.parser;
import java.io.InputStream;
import java.util.AbstractMap.SimpleEntry;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import xhail.core.Logger;
import xhail.core.entities.Values;
import xhail.core.parser.Parser.ParserErrorException;
/**
* @author stefano
*
*/
public class Acquirer {
private static final String FOUND = "FOUND";
private static final String OPTIMIZATION = "Optimization:";
private static final String OPTIMUM = "OPTIMUM";
private static final String SATISFIABLE = "SATISFIABLE";
private static final String UNKNOWN = "UNKNOWN";
private static final String UNSATISFIABLE = "UNSATISFIABLE";
public static Acquirer from(InputStream stream) {
if (null == stream)
throw new IllegalArgumentException("Illegal 'stream' argument in Acquirer.from(InputStream): " + stream);
return new Acquirer(Tokeniser.from(stream));
}
private Set<Collection<String>> answers;
private Set<String> atoms;
private String token;
private Tokeniser tokeniser;
private Values values = new Values();
private Acquirer(Tokeniser tokeniser) {
if (null == tokeniser)
throw new IllegalArgumentException("Illegal 'tokeniser' argument in Acquirer(Tokeniser): " + tokeniser);
this.tokeniser = tokeniser;
this.token = tokeniser.next();
}
private boolean isNumber(String token) {
if (null == token || (token = token.trim()).isEmpty())
return false;
boolean result = true;
for (int i = 0; result && i < token.length(); i++)
result = Character.isDigit(token.charAt(i));
return result;
}
public Map.Entry<Values, Collection<Collection<String>>> parse() {
this.answers = new HashSet<>();
try {
if (UNKNOWN.equals(token))
parseUNKNOWN();
else if (UNSATISFIABLE.equals(token))
parseUNSATISFIABLE();
else
parseAnswer();
parseEOF();
} catch (ParserErrorException e) {
Logger.error(e.getMessage());
// return null;
}
return new SimpleEntry<Values, Collection<Collection<String>>>(this.values, this.answers);
}
private void parseAnswer() throws ParserErrorException {
if (null == token)
throw new ParserErrorException("expected ATOM but EOF found");
// if (FOUND.equals(token) || OPTIMIZATION.equals(token) || OPTIMUM.equals(token) || SATISFIABLE.equals(token) || UNKNOWN.equals(token)
// || UNSATISFIABLE.equals(token))
// throw new ParserErrorException(String.format("expected ATOM but '%s' found", token));
this.atoms = new HashSet<>();
while (null != token && !FOUND.equals(token) && !OPTIMIZATION.equals(token) && !OPTIMUM.equals(token) && !SATISFIABLE.equals(token)
&& !UNKNOWN.equals(token) && !UNSATISFIABLE.equals(token)) {
atoms.add(token);
token = tokeniser.next();
}
if (SATISFIABLE.equals(token)) {
parseSATISFIABLE();
answers.add(atoms);
} else {
parseOPTIMIZATION();
parseValues();
}
}
private void parseEOF() throws ParserErrorException {
if (null != token)
throw new ParserErrorException("expected EOF but '" + token + "' found");
}
private void parseFOUND() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", FOUND));
if (!FOUND.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", FOUND, token));
token = tokeniser.next();
}
private void parseNested() throws ParserErrorException {
if (null == token)
throw new ParserErrorException("expected ATOM but EOF found");
// if (FOUND.equals(token) || OPTIMIZATION.equals(token) || OPTIMUM.equals(token) || SATISFIABLE.equals(token) || UNKNOWN.equals(token)
// || UNSATISFIABLE.equals(token))
// throw new ParserErrorException(String.format("expected ATOM but '%s' found", token));
this.atoms = new HashSet<>();
while (null != token && !FOUND.equals(token) && !OPTIMIZATION.equals(token) && !OPTIMUM.equals(token) && !SATISFIABLE.equals(token)
&& !UNKNOWN.equals(token) && !UNSATISFIABLE.equals(token)) {
atoms.add(token);
token = tokeniser.next();
}
parseOPTIMIZATION();
parseValues();
}
private void parseOPTIMIZATION() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", OPTIMIZATION));
if (!OPTIMIZATION.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", OPTIMIZATION, token));
token = tokeniser.next();
}
private void parseOPTIMUM() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", OPTIMUM));
if (!OPTIMUM.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", OPTIMUM, token));
token = tokeniser.next();
}
private void parseSATISFIABLE() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", SATISFIABLE));
if (!SATISFIABLE.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", SATISFIABLE, token));
token = tokeniser.next();
}
private void parseUNKNOWN() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", UNKNOWN));
if (!UNKNOWN.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", UNKNOWN, token));
token = tokeniser.next();
}
private void parseUNSATISFIABLE() throws ParserErrorException {
if (null == token)
throw new ParserErrorException(String.format("expected '%s' but 'EOF' found", UNSATISFIABLE));
if (!UNSATISFIABLE.equals(token))
throw new ParserErrorException(String.format("expected '%s' but '%s' found", UNSATISFIABLE, token));
token = tokeniser.next();
}
private void parseValues() throws ParserErrorException {
if (null == token)
throw new ParserErrorException("expected NUMBER but EOF found");
if (!isNumber(token))
throw new ParserErrorException(String.format("expected NUMBER but '%s' found", token));
String values = "";
while (null != token && isNumber(token)) {
if (!values.isEmpty())
values += " ";
values += token;
token = tokeniser.next();
}
Values found = new Values(values);
int order = found.compareTo(this.values);
if (order < 0) {
answers.clear();
this.values = found;
}
if (order <= 0)
answers.add(atoms);
if (OPTIMUM.equals(token)) {
parseOPTIMUM();
parseFOUND();
} else {
parseNested();
}
}
}