public class ExprResolver extends HashMap<Integer, PatternExpr>
{
	private static final long serialVersionUID = 1L;
	
	private int entrypoint;

	public ExprResolver(GraphString phr, TypeReduction red)
	{
		super();
		
		for(TypeLink link : red)
		{
			this.put(link.start, phr.getPattern(link.end));
			this.put(link.end, phr.getPattern(link.start));
			if(link.end == phr.size()-1)
				entrypoint = link.start;
		}
	}
	
	public int getEntryPoint()
	{
		return entrypoint;
	}
} public abstract class GraphExpr implements Cloneable
{
	public boolean isProducer() { return (this instanceof ProducerExpr); }
	public boolean isConsumer() { return (this instanceof ConsumerExpr); }
	
	public abstract SimpleType getType();
	
	public abstract Object clone();
} public class MorphExpr extends NodeExpr
{
	public boolean isReify;
	public StmtExpr triple;
	
	public MorphExpr(boolean reify, StmtExpr t)
	{
		isReify = reify;
		triple = t;
	}
	
	public String toString()
	{
		if(isReify)
			return "reify("+triple.toString()+")";
		else
			return "qlify("+triple.toString()+")";
	}

	public Object clone()
	{
		return new MorphExpr(isReify, (StmtExpr) triple.clone());
	}

	public void shift(HashMap<Integer, Integer> map, String name)
			throws NotFoundException
	{
		triple.shift(map,name);
	}

} public class NamedNodeExpr extends NodeExpr
{
	public String name;
	public NamedNodeExpr(String s) { name = new String(s); } 
	
	public void shift(HashMap<Integer,Integer> map, String n)
	{
		name = name.replace("NAME",n);
	}
	
	public String toString()
	{
		return "node(\""+name+"\")";
	}

	public Object clone()
	{
		return new NamedNodeExpr(name);
	}
} public abstract class NodeExpr extends PatternExpr implements Cloneable
{
	public boolean isVar() { return (this instanceof NodeVarExpr); }
	public boolean isFresh() { return (this instanceof FreshExpr); }
	public boolean isNamedNode() { return (this instanceof NamedNodeExpr); }
	public boolean isMorph() { return (this instanceof MorphExpr); }
	public boolean isLiteral() { return (this instanceof LiteralExpr); }
	
	public abstract String toString();
	public abstract Object clone();
} public class NodeVarExpr extends NodeExpr implements Cloneable
{
	public int id;
	public NodeVarExpr(int i) { id = i; }

	public void shift(HashMap<Integer, Integer> map, String name) throws NotFoundException
	{
		if(map.get(id) == null)
			throw new NotFoundException(id);
		id = map.get(id);
	}

	public String toString()
	{
		return ""+id;
	}

	public Object clone()
	{
		return new NodeVarExpr(id);
	}
} public abstract class PatternExpr implements Cloneable
{
	public boolean isNode() { return (this instanceof NodeExpr); }
	public boolean isStmt() { return (this instanceof StmtExpr); }
	
	public abstract void shift(HashMap<Integer,Integer> map, String name) throws NotFoundException;
	
	public abstract Object clone();
	
	public abstract String toString();
} public abstract class StmtExpr extends PatternExpr
{
	public boolean isTriple() { return (this instanceof TripleExpr); }
	public boolean isVar() { return (this instanceof TripleVarExpr); }

} public class TripleExpr extends StmtExpr implements Cloneable
{
	public NodeExpr subj;
	public NodeExpr prop;
	public NodeExpr obj;
	public TripleExpr(NodeExpr s, NodeExpr p, NodeExpr o)
	{
		subj = s;
		prop = p;
		obj = o;
	}
	
	public void shift(HashMap<Integer,Integer> map, String name) throws NotFoundException
	{
		subj.shift(map, name);
		prop.shift(map, name);
		obj.shift(map, name);
	}

	public String toString()
	{
		return "("+subj.toString()+","+prop.toString()+","+obj.toString()+")";
	}

	public Object clone()
	{
		return new TripleExpr((NodeExpr)subj.clone(), (NodeExpr) prop.clone(), (NodeExpr) obj.clone());
	}
} public class TripleVarExpr extends StmtExpr
{
	public int id;

	public TripleVarExpr(int i) { id = i; }

	public void shift(HashMap<Integer, Integer> map, String name)
			throws NotFoundException
	{
		if(map.get(id) == null)
			throw new NotFoundException(id);
		id = map.get(id);	
	}


	public Object clone()
	{
		return new TripleVarExpr(id);
	}

	public String toString()
	{
		return new Integer(id).toString();
	}
} public class TypeLink
{
	public int start;
	public int end;
	
	public TypeLink(int s, int e)
	{
		start = s;
		end = e;
	}
	
	public String toString()
	{
		return "("+start+","+end+")";
	}
} public class TypeReduction extends ArrayList<TypeLink>
{
	private static final long serialVersionUID = 1L;
	
	//! Create an empty type reduction
	public static TypeReduction empty()
	{
		return new TypeReduction();
	}

	//! Add a new link to an existing reduction
	public TypeReduction link(int s, int e)
	{
		TypeReduction res = new TypeReduction();
		for(TypeLink l : this)
			res.add(l);
		res.add(new TypeLink(s,e));
		return res;
	}
	
	//! Makes the union of two type reductions (supposed disjoint)
	public static TypeReduction union(TypeReduction lhs, TypeReduction rhs)
	{
		TypeReduction res = new TypeReduction();
		for(TypeLink l : lhs)
			res.add(l);
		for(TypeLink l : rhs)
			res.add(l);
		return res;
	}
	
	public String toString()
	{
		String res = "";
		for(TypeLink l : this)
			res += l.toString() + " ";
		return res;
	}
} public class GraphString extends PhraseString
{
	private static final long serialVersionUID = 1L;
	
	private HashMap<Integer, PatternExpr> patterns;

	public GraphString(SemanticLexicon lex, List<Pair<String,String>> sen, TypeString target) throws UnknownTagException, TypeException
	{
		this(lex.graphExprs(sen), sen, target);
	}
	
	public GraphString(SemanticLexicon lex, List<Pair<String,String>> sen, SimpleType target) throws UnknownTagException, TypeException
	{
		this(lex.graphExprs(sen), sen, new TypeString(target));
	}
	
	public PatternExpr getPattern(int index)
	{
		return patterns.get(index);
	}
	
	public void shiftPattern(HashMap<Integer, Integer> map, int idx, String name) throws NotFoundException
	{
		PatternExpr p = getPattern(idx);
		p.shift(map, name);
		patterns.put(idx, p);
	}
	
	public GraphString(List<List<List<GraphExpr>>> lst, List<Pair<String,String>> sen, TypeString target) throws TypeException
	{
		//! TODO Redesign this method : separate HashMap generation and type string generation
		patterns = new HashMap<Integer, PatternExpr>();
		int widx = 0;
		for(List<List<GraphExpr>> candidates : lst)
		{
			HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
			
			if(candidates.size() == 1 && candidates.get(0).size() == 1 && candidates.get(0).get(0).getType().isUnit())
				continue;
			
			addLB();
			addStar();
			for(List<GraphExpr> type : candidates)
			{
				int idx = this.size();
				
				TypeString str = new TypeString();
				for(GraphExpr ge : type)
				{
					if(ge.isConsumer())
					{
						ConsumerExpr c = (ConsumerExpr)ge;
						map.put(c.var, idx);
					}
					idx++;
				}
				
				idx = this.size();
				for(GraphExpr ge : type)
				{
					if(ge.isProducer())
					{
						ProducerExpr p = (ProducerExpr) ge;
						try {
							p.pattern.shift(map, sen.get(widx).getLeft());
						} catch(NotFoundException e)
						{
							throw new TypeException("Invalid pattern \""+p.pattern.toString()+
									"\": variable "+e.i+" is undefined.");
						}
						patterns.put(idx,p.pattern);
					}
					str.add(ge.getType());
					idx++;
				}
				
				addType(str);
				addStar();
			}
			
			addRB();
			widx++;
		}
		
		//! Add the candidate
		addLB();
		addStar();
		addType(target.right());
	}

} public class SemanticLexicon
	implements Lexicon
{
	private HashMap<String, List<List<GraphExpr>>> mFromTag =
			new HashMap<String, List<List<GraphExpr>>>();
	private HashMap<String, List<List<GraphExpr>>> mFromForm =
			new HashMap<String, List<List<GraphExpr>>>();

	private TypeRelations rels;

	private static TypeString stringOfList(List<GraphExpr> l)
	{
		TypeString res = new TypeString();
		for(GraphExpr g : l)
			res.add(g.getType());
		return res;
	}
	
	public HashMap<String, List<List<GraphExpr>>> getTagDict()
	{
		return mFromTag;
	}
	
	public HashMap<String, List<List<GraphExpr>>> getFormDict()
	{
		return mFromForm;
	}
	
	public List<List<GraphExpr>> get(Pair<String,String> taggedWord)
	{
		List<List<GraphExpr>> res = mFromForm.get(taggedWord.getLeft());
		if(res == null)
			return mFromTag.get(taggedWord.getRight());
		return res;
	}
	
	public List<List<List<GraphExpr>>> graphExprs(List<Pair<String,String>> sentence) throws UnknownTagException
	{
		List<List<List<GraphExpr>>> res = new ArrayList<List<List<GraphExpr>>>();
		
		for(Pair<String,String> taggedWord : sentence)
		{
			List<List<GraphExpr>> l = get(taggedWord);

			if(l != null && !l.isEmpty())
			{
				List<List<GraphExpr>> cloned = new ArrayList<List<GraphExpr>>();
				for(List<GraphExpr> l1 :l)
				{
					List<GraphExpr> l2 = new ArrayList<GraphExpr>();
					for(GraphExpr ge : l1)
						l2.add((GraphExpr)ge.clone());
					cloned.add(l2);
				}
				res.add(cloned);
			}
			else
				throw new UnknownTagException(taggedWord.getRight());
		}
		
		return res;
	}
	
	public List<List<TypeString>> types(List<Pair<String,String>> sentence)
	{
		List<List<TypeString>> res = new ArrayList<List<TypeString>>();
		for(Pair<String,String> taggedWord : sentence)
		{
			List<List<GraphExpr>> o = get(taggedWord);
			List<TypeString> l = new ArrayList<TypeString>();
			if(o == null)
				res.add(new ArrayList<TypeString>());
			else
			{
				for(List<GraphExpr> g : o)
					l.add(stringOfList(g));
				res.add(l);
			}
		}
		return res;
	}
	
	public void load(String filename) throws InternalException
	{
		try {
		JAXBContext jaxbContext;
			jaxbContext = JAXBContext
					.newInstance("xmllexicon");
		Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
		JAXBElement<?> lexicon = (JAXBElement<?>)unmarshaller
				.unmarshal(new FileInputStream(filename));
		
		RawLexicon rl = (RawLexicon)lexicon.getValue();
		Entries entries = rl.getEntries();
		rels = rl.getRelations();
		if(rels == null)
			rels = new TypeRelations();
		
		if(entries.getEntry() != null)
		{
			for(EntryType ent : entries.getEntry()) {
				String form = ent.getForm();
				String tag = ent.getTag();
				List<String> rawTypes = ent.getType();
				List<List<GraphExpr>> res = new ArrayList<List<GraphExpr>>();
				
				for(String rt : rawTypes)
				{
					GraphExprLexer lexer = new GraphExprLexer(rt);
					GraphExprParser parser = new GraphExprParser(lexer);
					
					java_cup.runtime.Symbol s;
					try {
						s = parser.parse();
						if(s.value != null)
							res.add((List<GraphExpr>)(s.value));
					}
					catch (Exception e) {
						throw new InternalException("Unable to parse the following type: "+rt);
					}
					catch(Error e) {
						throw new InternalException("Unable to parse the following type: "+rt);
					}
				}
				
				if(form != null && form != "")
					mFromForm.put(form, res);
				else if(tag != null)
					mFromTag.put(tag, res);
				else
					System.err.println("Undefined tag or form.");
			}
		}
		else System.err.println("Warning, the lexicon loaded has no <entries> section.");
		
		} catch (JAXBException je) {
			je.printStackTrace();
		} catch (IOException ioe) {
			ioe.printStackTrace();
		}
		
	}

	public PartialComparator<String> getComparator() {
		return rels;
	}
}
import graphexpr.ExprResolver;
import graphexpr.GraphExpr;
import graphexpr.MorphExpr;
import graphexpr.NamedNodeExpr;
import graphexpr.NodeExpr;
import graphexpr.NodeVarExpr;
import graphexpr.PatternExpr;
import graphexpr.StmtExpr;
import graphexpr.TripleExpr;
import graphexpr.TripleVarExpr;
import java.io.IOException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import pregroup.TypeLink;
import pregroup.TypeReduction;
import rdf.GraphString;
import util.FileUtils;
import xmllexicon.SemanticLexicon;
package latex;




//! Creates a TikZ output from a graph string
public class TikzGraphExpr {
	
	public TikzGraphExpr()
	{
		try {
			tikzHeader = FileUtils.readFile("latex/header.tex");
		} catch (IOException e) {
			System.err.println("Warning: failed to load the tikz header in latex/header.tex");
			tikzHeader = "\begin{tikzpicture}\n% Generated by http://github.com/wetneb/MorozParser\n% Header missing\n\n";
			e.printStackTrace();
		}
	}
	
	private String tikzHeader = "";
	
	private static final String tikzFooter = "\n\\end{tikzpicture}\n";
	
	//! Vertical space between the types and the links below them
	private static final double distToTypes = 0.25;
	//! Horizontal space between two simple types in the same word
	private static final double typeSpacing = 0.4;
	//! Horizontal space between the types of two words
	private static final double wordSpacing = 1.1;
	//! Vertical space between the original words and their types
	private static final double textDistance = 3;
	//! Vertical space between the graph expressions and their types
	private static final double graphExprDist = 0.25;
	
	//! Vertical spacing of fresh nodes
	private static final double freshNodeDist = 0.5;
	//! Vertical spacing of morph nodes (alpha & beta)
	private static final double morphDist = 1;
	//! Vertical spacing of literal nodes
	private static final double literalDist= 0.2;
	//! Horizontal spacing of links in a S link
	private static final double distanceStatement = 0.15;
	
	public String drawLexicon(SemanticLexicon lex)
	{
		String output = "% Lexicon generated by http://github.com/wetneb/MorozParser\n"+
						"\\paragraph{Assignments from Penn Treebank tags}\n\n";
		
		output += drawHashMap(lex.getTagDict());
		
		output += "\n\n\\paragraph{Assignments from surface form}\n\n";
		
		output += drawHashMap(lex.getFormDict());
		
		return output;
	}
	
	public String drawHashMap(HashMap<String, List<List<GraphExpr>>> lex)