// This file was generated by Coco/R.
// Do not edit this file directly.
// (see 'misc/parsers' directory in source distribution)
using System;
using Sgry.Azuki.Highlighter.Coco;

namespace Sgry.Azuki.Highlighter.Coco.Latex {



class Parser {
	public const int _EOF = 0;
	public const int _command = 1;
	public const int _heading1 = 2;
	public const int _heading2 = 3;
	public const int _heading3 = 4;
	public const int _equationFlag = 5;
	public const int _bracket = 6;
	public const int _openCurlyBracket = 7;
	public const int _closeCurlyBracket = 8;
	public const int _escaped = 9;
	public const int _comment = 10;
	public const int _other = 11;
	public const int _spaces = 12;
	public const int maxT = 13;

	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;
	
	Document doc;

int sectionLevel = 0;
	int curlyBracketDepth = 0;
	internal Sgry.Azuki.Highlighter.HighlightHook _Hook = null;

	void Highlight( Token t, CharClass klass )
	{
		CharClass k;
		
		// use hook procedure if installed
		if( _Hook != null
			&& _Hook(doc, t.val, t.pos, klass) == true )
		{
			return;
		}

		// no hook was installed or the hook did nothing.
		// highlight this word normally
		k = klass;
		if( 0 < curlyBracketDepth )
		{
			if( sectionLevel == 1 )
				k = CharClass.Heading1;
			else if( sectionLevel == 2 )
				k = CharClass.Heading2;
			else if( sectionLevel == 3 )
				k = CharClass.Heading3;
		}
		for( int i=t.pos; i<t.pos+t.val.Length; i++ )
		{
			doc.SetCharClass( i, k );
		}
	}

/*-------------------------------------------------------
**  Scanner Spec.
**-------------------------------------------------------*/



	public Parser( Document doc, int startIndex ) {
		this.scanner = new Scanner( doc, startIndex );
		errors = new Errors();
		this.doc = doc;
	}

	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); }
	}
	
	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 Tex() {
		texToken();
		while (StartOf(1)) {
			texToken();
		}
	}

	void texToken() {
		switch (la.kind) {
		case 1: {
			Get();
			Highlight( t, CharClass.LatexCommand );
			if( curlyBracketDepth <= 0 )
				sectionLevel = 0;
			
			break;
		}
		case 2: {
			Get();
			Highlight( t, CharClass.LatexCommand );
			sectionLevel = 1;
			
			break;
		}
		case 3: {
			Get();
			Highlight( t, CharClass.LatexCommand );
			sectionLevel = 2;
			
			break;
		}
		case 4: {
			Get();
			Highlight( t, CharClass.LatexCommand );
			sectionLevel = 3;
			
			break;
		}
		case 5: {
			Get();
			Highlight( t, CharClass.LatexEquation );	
			break;
		}
		case 6: {
			Get();
			Highlight( t, CharClass.LatexBracket );	
			break;
		}
		case 7: {
			Get();
			Highlight( t, CharClass.LatexCurlyBracket );
			curlyBracketDepth++;
			
			break;
		}
		case 8: {
			Get();
			curlyBracketDepth--;
			Highlight( t, CharClass.LatexCurlyBracket );
			
			break;
		}
		case 10: {
			Get();
			Highlight( t, CharClass.Comment );	
			break;
		}
		case 9: {
			Get();
			Highlight( t, CharClass.Normal );	
			break;
		}
		case 11: {
			Get();
			Highlight( t, CharClass.Normal );	
			break;
		}
		case 12: {
			Get();
			Highlight( t, CharClass.Normal );	
			break;
		}
		default: SynErr(14); break;
		}
	}



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

		Expect(0);
	}
	
	static readonly bool[,] set = {
		{T,x,x,x, x,x,x,x, x,x,x,x, x,x,x},
		{x,T,T,T, T,T,T,T, T,T,T,T, T,x,x}

	};
} // end Parser


class Errors {
	public int count = 0;                                    // number of errors detected
	public System.IO.TextWriter errorStream = Console.Out;   // error messages go to this stream
  public string errMsgFormat = "-- line {0} col {1}: {2}"; // 0=line, 1=column, 2=text
  
	public void SynErr (int line, int col, int n) {
		string s;
		switch (n) {
			case 0: s = "EOF expected"; break;
			case 1: s = "command expected"; break;
			case 2: s = "heading1 expected"; break;
			case 3: s = "heading2 expected"; break;
			case 4: s = "heading3 expected"; break;
			case 5: s = "equationFlag expected"; break;
			case 6: s = "bracket expected"; break;
			case 7: s = "openCurlyBracket expected"; break;
			case 8: s = "closeCurlyBracket expected"; break;
			case 9: s = "escaped expected"; break;
			case 10: s = "comment expected"; break;
			case 11: s = "other expected"; break;
			case 12: s = "spaces expected"; break;
			case 13: s = "??? expected"; break;
			case 14: s = "invalid texToken"; break;

			default: s = "error " + n; break;
		}
		errorStream.WriteLine(errMsgFormat, line, col, s);
		count++;
	}

	public void SemErr (int line, int col, string s) {
		errorStream.WriteLine(errMsgFormat, line, col, s);
		count++;
	}
	
	public void SemErr (string s) {
		errorStream.WriteLine(s);
		count++;
	}
	
	public void Warning (int line, int col, string s) {
		errorStream.WriteLine(errMsgFormat, line, col, s);
	}
	
	public void Warning(string s) {
		errorStream.WriteLine(s);
	}
} // Errors


class FatalError: Exception {
	public FatalError(string m): base(m) {}
}

}