package org.archstudio.prolog.parser;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.List;
import org.archstudio.prolog.engine.ProofContext;
import org.archstudio.prolog.term.ComplexTerm;
import org.archstudio.prolog.term.ConstantTerm;
import org.archstudio.prolog.term.ListTerm;
import org.archstudio.prolog.term.StringTerm;
import org.archstudio.prolog.term.Term;
import org.archstudio.prolog.term.VariableTerm;
import org.archstudio.prolog.xtext.PrologStandaloneSetupGenerated;
import org.archstudio.prolog.xtext.prolog.AtomExpression;
import org.archstudio.prolog.xtext.prolog.Expression;
import org.archstudio.prolog.xtext.prolog.ListExpression;
import org.archstudio.prolog.xtext.prolog.Model;
import org.archstudio.prolog.xtext.prolog.NumberExpression;
import org.archstudio.prolog.xtext.prolog.StringExpression;
import org.archstudio.prolog.xtext.prolog.UnaryExpression;
import org.archstudio.prolog.xtext.prolog.VariableExpression;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.Resource.Diagnostic;
import org.eclipse.xtext.diagnostics.AbstractDiagnostic;
import org.eclipse.xtext.resource.XtextResource;
import org.eclipse.xtext.resource.XtextResourceSet;
import com.google.common.collect.Lists;
import com.google.inject.Injector;
public class PrologParser {
private static Injector injector = null;
private static Model parse(String input) throws ParseException {
try {
if (injector == null) {
injector = new PrologStandaloneSetupGenerated().createInjectorAndDoEMFRegistration();
}
XtextResourceSet resourceSet = injector.getInstance(XtextResourceSet.class);
resourceSet.addLoadOption(XtextResource.OPTION_RESOLVE_ALL, Boolean.TRUE);
Resource resource = resourceSet.createResource(URI.createURI("null:/prolog.pl"));
InputStream in = new ByteArrayInputStream(input.getBytes());
resource.load(in, resourceSet.getLoadOptions());
if (resource.getErrors().size() > 0) {
Diagnostic d = resource.getErrors().get(0);
String l = d.getLocation();
if (l == null) {
try {
l = "line and column: " + d.getLine() + "," + d.getColumn();
}
catch (UnsupportedOperationException e) {
if (d instanceof AbstractDiagnostic) {
int offset = ((AbstractDiagnostic) d).getOffset();
input = input.substring(0, offset) + "<<<HERE>>>" + input.substring(offset);
l = "offset: " + offset;
}
}
}
throw new ParseException(resource.getErrors().get(0).getMessage() + " at " + l + " for: " + input);
}
return (Model) resource.getContents().get(0);
}
catch (Throwable e) {
throw new ParseException("Parse exception for: " + input, e);
}
}
public static synchronized List<Term> parseTerms(ProofContext proofContext, String input) throws ParseException {
List<Term> terms = Lists.newArrayList();
for (Expression exp : parse(input).getExps()) {
terms.add(parseExpression(proofContext, exp));
}
return terms;
}
private static Term parseExpression(ProofContext proofContext, Expression e) throws ParseException {
if (e == null) {
return null;
}
if (e instanceof UnaryExpression) {
UnaryExpression c = (UnaryExpression) e;
Term right = parseExpression(proofContext, c.getRight());
if (c.getOp() != null) {
right = proofContext.create(c.getOp(), Lists.newArrayList(right));
}
return right;
}
if (e instanceof AtomExpression) {
AtomExpression c = (AtomExpression) e;
String op = c.getAtom();
List<Term> terms = toList(parseExpression(proofContext, c.getTerms()));
return proofContext.create(op, terms);
}
if (e instanceof VariableExpression) {
VariableExpression c = (VariableExpression) e;
return new VariableTerm(c.getName());
}
if (e instanceof StringExpression) {
StringExpression c = (StringExpression) e;
return new StringTerm(c.getValue());
}
if (e instanceof NumberExpression) {
NumberExpression c = (NumberExpression) e;
String value = c.getValue().toLowerCase();
Number n;
if (value.indexOf('.') >= 0 || value.indexOf('e') >= 0) {
n = new BigDecimal(value);
}
else {
n = new BigInteger(value);
}
return new ConstantTerm(n);
}
if (e instanceof ListExpression) {
ListExpression c = (ListExpression) e;
Term list = new ListTerm();
if (c.getTail() != null) {
list = parseExpression(proofContext, c.getTail());
}
for (Term head : Lists.reverse(toList(parseExpression(proofContext, c.getHead())))) {
list = new ListTerm(head, list);
}
return list;
}
Term left = parseExpression(proofContext, e.getLeft());
Term right = parseExpression(proofContext, e.getRight());
return proofContext.create(e.getOp(), Lists.newArrayList(left, right));
}
private static List<Term> toList(Term t) {
if (t instanceof ComplexTerm) {
ComplexTerm c = (ComplexTerm) t;
if (",".equals(c.getFunctor())) {
List<Term> list = Lists.newArrayList(c.getTerm(0));
list.addAll(toList(c.getTerm(1)));
return list;
}
}
if (t != null) {
return Lists.newArrayList(t);
}
return Lists.newArrayList();
}
}