/*
 * Bernoulli Compiler
 * Copyright (c) Cornell University
 * Department of Computer Science
 * 
 * Kamen Yotov (kamen@yotov.org)
 * 
 * $Source: C:/CVS/kyotov/kyotov/Research/BC/Core/Automatas/Item.cs,v $
 * $Revision: 1.5 $
 * $Date: 2002/10/22 19:50:41 $
 */

using System;
using System.Collections;

using XTensions.Collections;

namespace BC.Core
{
	using Grammars;
	using Grammars.Symbols;

	namespace Automatas
	{
		[Serializable]
		public class Item
		{
			protected Production p;
			protected int dot;
			protected Set la;
			protected IList c;
		
			public Item (Production p, int dot, Set la, IList c)
			{
				this.p = p;
				this.dot = dot;
				this.la = la;
				this.c = c;
			}

			public Item (Production p, int dot, Set f):
				this(p, dot, f, null)
			{
			}

			public Item (Production p, int dot):
				this(p, dot, new Set())
			{
			}

			public Item (NonTerminal n):
				this(new Production(n, new Alternative(null)), 0)
			{
			}

			public Production P
			{
				get
				{
					return p;
				}
			}

			public int Dot
			{
				get
				{
					return dot;
				}
			}

			public Set LA
			{
				get
				{
					return la;
				}
				set
				{
					la = value;
				}
			}

			public bool IsReduction
			{
				get
				{
					return Dot == P.RHS.Sequence.Count;
				}
			}

			public bool IsStation
			{
				get
				{
					return P.RHS.Sequence == null;
				}
			}

			public bool IsLastNonTerminal
			{
				get
				{
					return !IsStation && Dot == P.RHS.Sequence.Count - 1 && P.RHS.Sequence[Dot] is NonTerminal;
				}
			}

			public bool LookAhead (Sequence s)
			{
				foreach (Sequence la in LA)
					if (Sequence.Match(s, la))
						return true;

				return false;
			}

			public override string ToString ()
			{
				Sequence s = P.RHS.Sequence;

				string r;

				if (s != null)
				{
					r = string.Format("{0} ->", P.LHS);


					for (int i = 0; i <= s.Count; i++)
					{
						if (i == Dot)
							r += " .";

						if (i < s.Count)
							r += string.Format(" {0:\"}", s[i]);
					}

					r += " ";
				}
				else
					r = string.Format(". {0} ", P.LHS);

				foreach (Sequence a in LA)
					r += string.Format("[{0}]", a);

				return r;
			}
		}
	}
}