package eu.dnetlib.dlms.view;




public class Parser {
	public static final int _EOF = 0;
	public static final int _ident = 1;
	public static final int _number = 2;
	public static final int _viewToken = 3;
	public static final int _entrypointToken = 4;
	public static final int _visitToken = 5;
	public static final int _relationToken = 6;
	public static final int _nodeToken = 7;
	public static final int maxT = 11;

	static final boolean T = true;
	static final boolean x = false;
	static final int minErrDist = 2;

	public Token t;    // last recognized token
	public Token la;   // lookahead token
	int errDist = minErrDist;
	
	public Scanner scanner;
	public Errors errors;

	private ParserView parserView;

/*--------------------------------------------------------------------*/



	public Parser(Scanner scanner) {
		this.scanner = scanner;
		errors = new Errors();
	}

	void SynErr (int n) {
		if (errDist >= minErrDist) errors.SynErr(la.line, la.col, n);
		errDist = 0;
	}

	public void SemErr (String msg) {
		if (errDist >= minErrDist) errors.SemErr(t.line, t.col, msg);
		errDist = 0;
	}
	
	void Get () {
		for (;;) {
			t = la;
			la = scanner.Scan();
			if (la.kind <= maxT) {
				++errDist;
				break;
			}

			la = t;
		}
	}
	
	void Expect (int n) {
		if (la.kind==n) Get(); else { SynErr(n); }
	}
	
	boolean StartOf (int s) {
		return set[s][la.kind];
	}
	
	void ExpectWeak (int n, int follow) {
		if (la.kind == n) Get();
		else {
			SynErr(n);
			while (!StartOf(follow)) Get();
		}
	}
	
	boolean WeakSeparator (int n, int syFol, int repFol) {
		int kind = la.kind;
		if (kind == n) { Get(); return true; }
		else if (StartOf(repFol)) return false;
		else {
			SynErr(n);
			while (!(set[syFol][kind] || set[repFol][kind] || set[0][kind])) {
				Get();
				kind = la.kind;
			}
			return StartOf(syFol);
		}
	}
	
	public ParserView getParserView() {
		return parserView;
	}

	

	void View() {
		String name= null;
		parserView= new ParserView();
		
		Expect(1);
		name=t.val;
		Expect(8);
		Expect(3);
		if(name!=null)
		{
		//System.out.println("e' stata dichiarata una vista di nome "+name+"  "+t.val); 
		parserView.setViewName(name);
		}
		
		Expect(4);
		Expect(8);
		Expect(1);
		//System.out.println("e' stato dichiarato il set entrypoint "+ t.val);
		parserView.addEntryPoint(t.val);   
		
		while (la.kind == 9) {
			Get();
			B();
			Expect(10);
		}
		//System.out.println("Fine file la vista corretta = "+ parserView.isCorrectStructView()); 
		
	}

	void B() {
		if (la.kind == 5) {
			Get();
			//System.out.println("Sono entrato in visit di B"+t.val);
			
			if (la.kind == 1) {
				Get();
				//System.out.println("una relazione diretta "+t.val);
				parserView.AddRelationToCurrent(t.val);
				
			} else if (la.kind == 6) {
				Get();
				parserView.AddRelationToCurrent(null);
				//System.out.println("una relazione indiretta"+t.val);
				
				
			} else SynErr(12);
			while (la.kind == 9) {
				Get();
				N();
				Expect(10);
				try
				{
					parserView.relationsClose();
				}
				catch(Exception e)
				{
					System.out.println("ERROR");
				} 
				
			}
			B();
		} else if (la.kind == 10) {
		} else SynErr(13);
	}

	void N() {
		Expect(7);
		//System.out.println("Sono entrato in Node di N"+t.val);
		
		Expect(1);
		parserView.reachNode(t.val);
		//System.out.println(t.val);
		
		while (la.kind == 9) {
			Get();
			B();
			Expect(10);
		}
	}



	public void Parse() {
		la = new Token();
		la.val = "";		
		Get();
		View();

		Expect(0);
	}

	private static final boolean[][] set = {
		{T,x,x,x, x,x,x,x, x,x,x,x, x}

	};
} // end Parser


class Errors {
	public int count = 0;                                    // number of errors detected
	public java.io.PrintStream errorStream = System.err;     // error messages go to this stream
	public String errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
	
	protected void printMsg(int line, int column, String msg) {
		StringBuffer b = new StringBuffer(errMsgFormat);
		int pos = b.indexOf("{0}");
		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, line); }
		pos = b.indexOf("{1}");
		if (pos >= 0) { b.delete(pos, pos+3); b.insert(pos, column); }
		pos = b.indexOf("{2}");
		if (pos >= 0) b.replace(pos, pos+3, msg);
		errorStream.println(b.toString());
	}
	
	public void SynErr (int line, int col, int n) {
		String s;
		switch (n) {
			case 0: s = "EOF expected"; break;
			case 1: s = "ident expected"; break;
			case 2: s = "number expected"; break;
			case 3: s = "viewToken expected"; break;
			case 4: s = "entrypointToken expected"; break;
			case 5: s = "visitToken expected"; break;
			case 6: s = "relationToken expected"; break;
			case 7: s = "nodeToken expected"; break;
			case 8: s = "\"=\" expected"; break;
			case 9: s = "\"{\" expected"; break;
			case 10: s = "\"}\" expected"; break;
			case 11: s = "??? expected"; break;
			case 12: s = "invalid B"; break;
			case 13: s = "invalid B"; break;
			default: s = "error " + n; break;
		}
		printMsg(line, col, s);
		count++;
	}

	public void SemErr (int line, int col, String s) {	
		printMsg(line, col, s);
		count++;
	}
	
	public void SemErr (String s) {
		errorStream.println(s);
		count++;
	}
	
	public void Warning (int line, int col, String s) {	
		printMsg(line, col, s);
	}
	
	public void Warning (String s) {
		errorStream.println(s);
	}
} // Errors


class FatalError extends RuntimeException {
	public static final long serialVersionUID = 1L;
	public FatalError(String s) { super(s); }
}

