/*---------------------------------------------------------------------------*\
    Compiler Generator Coco/R,
    Copyright (c) 1990, 2004 Hanspeter Moessenboeck, University of Linz
    extended by M. Loeberbauer & A. Woess, Univ. of Linz
    with improvements by Pat Terry, Rhodes University
-------------------------------------------------------------------------------
License
    This file is part of Compiler Generator Coco/R
    This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU General Public License as published by the
    Free Software Foundation; either version 2, or (at your option) any
    later version.
    This program is distributed in the hope that it will be useful, but
    WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    for more details.
    You should have received a copy of the GNU General Public License along
    with this program; if not, write to the Free Software Foundation, Inc.,
    59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
    As an exception, it is allowed to write an extension of Coco/R that is
    used as a plugin in non-free software.
    If not otherwise stated, any source code generated by Coco/R (other than
    Coco/R itself) does not fall under the GNU General Public License.
\*---------------------------------------------------------------------------*/
// This file was generated with Coco/R C#, version: 20101106
using System.IO;
using System;
namespace at.jku.ssw.Coco {
// ----------------------------------------------------------------------------
// Parser
// ----------------------------------------------------------------------------
//! A Coco/R Parser
public class Parser
{
	public const int _EOF = 0;
	public const int _ident = 1;
	public const int _number = 2;
	public const int _string = 3;
	public const int _badString = 4;
	public const int _char = 5;
	public const int maxT = 43;  //<! max term (w/o pragmas)
	public const int _ddtSym = 44;
	public const int _directive = 45;
	const bool T = true;
	const bool x = false;
	const int minErrDist = 2;
	public Scanner scanner;
	public Errors  errors;
	public Token t;    //!< last recognized token
	public Token la;   //!< lookahead token
	int errDist = minErrDist;
const int isIdent   = 0;
	const int isLiteral = 1;
	public Tab tab;             // other Coco objects referenced in this ATG
	public DFA dfa;
	public ParserGen pgen;
	bool   genScanner = false;
	string tokenString;         // used in declarations of literal tokens
	string noString = "-none-"; // used in declarations of literal tokens
/*-------------------------------------------------------------------------*/
	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; }
				if (la.kind == 44) {
				tab.SetDDT(la.val);
				}
				if (la.kind == 45) {
				tab.DispatchDirective(la.val);
				}
			la = t;
		}
	}
	void Expect (int n) {
		if (la.kind==n) Get(); else { SynErr(n); }
	}
	bool 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();
		}
	}
	bool 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);
		}
	}
	void Coco() {
		Symbol sym; Graph g; string grammarName; CharSet s;
		if (la.kind == 6) {
			Get();
			int beg = t.pos + t.val.Length;
			while (StartOf(1)) {
				Get();
			}
			tab.copyPos = new Position(beg, la.pos, 0);
			Expect(7);
		}
		if (StartOf(2)) {
			Get();
			int beg = t.pos;
			while (StartOf(3)) {
				Get();
			}
			pgen.preamblePos = new Position(beg, la.pos, 0);
		}
		Expect(8);
		genScanner = true;
		Expect(1);
		grammarName = t.val;
		if (StartOf(4)) {
			Get();
			int beg = t.pos;
			while (StartOf(4)) {
				Get();
			}
			pgen.semDeclPos = new Position(beg, la.pos, 0);
		}
		if (la.kind == 9) {
			Get();
			dfa.ignoreCase = true;
		}
		if (la.kind == 10) {
			Get();
			while (la.kind == 1) {
				SetDecl();
			}
		}
		if (la.kind == 11) {
			Get();
			while (la.kind == 1 || la.kind == 3 || la.kind == 5) {
				TokenDecl(Node.t);
			}
		}
		if (la.kind == 12) {
			Get();
			while (la.kind == 1 || la.kind == 3 || la.kind == 5) {
				TokenDecl(Node.pr);
			}
		}
		while (la.kind == 13) {
			Get();
			Graph g1, g2; bool nested = false;
			Expect(14);
			TokenExpr(out g1);
			Expect(15);
			TokenExpr(out g2);
			if (la.kind == 16) {
				Get();
				nested = true;
			}
			dfa.NewComment(g1.l, g2.l, nested);
		}
		while (la.kind == 17) {
			Get();
			Set(out s);
			tab.ignored.Or(s);
		}
		while (!(la.kind == 0 || la.kind == 18)) {SynErr(44); Get();}
		Expect(18);
		if (genScanner) dfa.MakeDeterministic();
		tab.DeleteNodes();
		while (la.kind == 1) {
			Get();
			sym = tab.FindSym(t.val);
			bool undef = (sym == null);
			if (undef) sym = tab.NewSym(Node.nt, t.val, t.line);
			else {
			  if (sym.typ == Node.nt) {
			    if (sym.graph != null)
			      SemErr("name declared twice");
			  } else SemErr("this symbol kind not allowed on left side of production");
			  sym.line = t.line;
			}
			bool noAttrs = (sym.attrPos == null);
			sym.attrPos = null;
			if (la.kind == 26 || la.kind == 28) {
				AttrDecl(sym);
			}
			if (!undef && noAttrs != (sym.attrPos == null))
			 SemErr("attribute mismatch between declaration and use of this symbol");
			if (la.kind == 41) {
				SemText(out sym.semPos);
			}
			ExpectWeak(19, 5);
			Expression(out g);
			sym.graph = g.l;
			tab.Finish(g);
			ExpectWeak(20, 6);
		}
		Expect(21);
		Expect(1);
		if (grammarName != t.val)
		 SemErr("name does not match grammar name");
		tab.gramSy = tab.FindSym(grammarName);
		if (tab.gramSy == null)
		  SemErr("missing production for grammar name");
		else {
		  sym = tab.gramSy;
		  if (sym.attrPos != null)
		    SemErr("grammar symbol must not have attributes");
		}
		tab.noSym = tab.NewSym(Node.t, "???", 0); // noSym gets highest number
		tab.SetupAnys();
		tab.RenumberPragmas();
		if (tab.ddt[2]) tab.PrintNodes();
		if (errors.count == 0) {
		  Console.WriteLine("checking");
		  tab.CompSymbolSets();
		  if (tab.ddt[7]) tab.XRef();
		  if (tab.GrammarOk()) {
		    Console.Write("parser");
		    pgen.WriteParser();
		    if (genScanner) {
		      Console.Write(" + scanner");
		      dfa.WriteScanner();
		      if (tab.ddt[0]) dfa.PrintStates();
		    }
		    Console.WriteLine(" generated");
		    if (tab.ddt[8]) {
		      tab.PrintStatistics();
		      pgen.PrintStatistics();
		    }
		  }
		}
		if (tab.ddt[6]) tab.PrintSymbolTable();
		Expect(20);
	}
	void SetDecl() {
		CharSet s;
		Expect(1);
		string name = t.val;
		CharClass c = tab.FindCharClass(name);
		if (c != null) SemErr("name declared twice");
		Expect(19);
		Set(out s);
		if (s.Elements() == 0) SemErr("character set must not be empty");
		tab.NewCharClass(name, s);
		Expect(20);
	}
	void TokenDecl(int typ) {
		string name; int kind; Symbol sym; Graph g;
		Sym(out name, out kind);
		sym = tab.FindSym(name);
		if (sym != null) SemErr("name declared twice");
		else {
		  sym = tab.NewSym(typ, name, t.line);
		  sym.tokenKind = Symbol.fixedToken;
		}
		tokenString = null;
		while (!(StartOf(7))) {SynErr(45); Get();}
		if (la.kind == 19) {
			Get();
			TokenExpr(out g);
			Expect(20);
			if (kind == isLiteral) SemErr("a literal must not be declared with a structure");
			tab.Finish(g);
			if (tokenString == null || tokenString.Equals(noString))
			  dfa.ConvertToStates(g.l, sym);
			else { // TokenExpr is a single string
			  if (tab.literals[tokenString] != null)
			    SemErr("token string declared twice");
			  tab.literals[tokenString] = sym;
			  dfa.MatchLiteral(tokenString, sym);
			}
		} else if (StartOf(8)) {
			if (kind == isIdent) genScanner = false;
			else dfa.MatchLiteral(sym.name, sym);
		} else SynErr(46);
		if (la.kind == 41) {
			SemText(out sym.semPos);
			if (typ != Node.pr) SemErr("semantic action not allowed here");
		}
	}
	void TokenExpr(out Graph g) {
		Graph g2;
		TokenTerm(out g);
		bool first = true;
		while (WeakSeparator(30,9,10) ) {
			TokenTerm(out g2);
			if (first) { tab.MakeFirstAlt(g); first = false; }
			tab.MakeAlternative(g, g2);
		}
	}
	void Set(out CharSet s) {
		CharSet s2;
		SimSet(out s);
		while (la.kind == 22 || la.kind == 23) {
			if (la.kind == 22) {
				Get();
				SimSet(out s2);
				s.Or(s2);
			} else {
				Get();
				SimSet(out s2);
				s.Subtract(s2);
			}
		}
	}
	void AttrDecl(Symbol sym) {
		if (la.kind == 26) {
			Get();
			int beg = la.pos; int col = la.col;
			while (StartOf(11)) {
				if (StartOf(12)) {
					Get();
				} else {
					Get();
					SemErr("bad string in attributes");
				}
			}
			Expect(27);
			if (t.pos > beg)
			 sym.attrPos = new Position(beg, t.pos, col);
		} else if (la.kind == 28) {
			Get();


Answer: 			int beg = la.pos; int col = la.col;