//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
using System.Text;
using System.Collections;
using Ilog.Language.Util;
namespace Ilog.Language.Syntax
{
/**
* This this the class defining rule paths. It is essentially a sequence of
* rules. NB: The rule paths are constructed backwards; i.e., from
* end to start by the grammar analysis (the ComputePaths method in Grammar).
* Thus, the rule sequence going from Start to End is the
* reverse of the Rules sequence. This allows incrementally
* computing First, which must be done backwards.
*
* @version Last modified on Sat May 21 20:21:15 2005 by hak
* @author Hassan Aït-Kaci
* @copyright © 2000 ILOG, S.A.
*/
internal class RulePath
{
/**
* The grammar this rule path pertains to.
*/
private static Grammar grammar = Grammar.currentGrammar;
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* The nonterminal from which this path starts.
*/
private NonTerminal start;
internal NonTerminal Start
{
get { return start; }
}
/**
* The nonterminal at which this path ends.
*/
private NonTerminal end;
internal NonTerminal End
{
get { return end; }
}
/**
* This is the sequence containing the sequence of rules along
* this path.
*/
private ArrayList rules;
internal ArrayList Rules
{
get { return rules; }
}
/**
* The FIRST set along this path.
*/
private SetOf first = new SetOf(grammar.Terminals);
internal SetOf First
{
get { return first; }
}
/**
* This is true iff this path derives EMPTY.
*/
private bool isNullable = true;
internal bool IsNullable
{
get { return isNullable; }
}
/**
* This is true iff this path is empty.
*/
internal bool IsEmpty
{
get { return (rules == null) || (rules.Count == 0); }
}
/**
* This is the length of this rule path.
*/
internal int Length
{
get { return IsEmpty ? 0 : rules.Count; }
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* Constructs a RulePath which is a copy of the given rule path.
*/
private RulePath (RulePath p)
{
rules = p.rules == null ? null : (ArrayList)p.rules.Clone();
start = p.start;
end = p.end;
first = new SetOf(p.first);
isNullable = p.isNullable;
}
/**
* Constructs an empty RulePath from the given nonterminal to itself.
*/
internal RulePath (NonTerminal n)
{
start = end = n;
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* Adds the given rule at the start of this rule path (and
* therefore at the end of rules).
*/
internal void Add (Rule rule)
{
start = rule.Head;
if (rules == null)
rules = new ArrayList();
rules.Add(rule);
if (isNullable)
{
first.Union(rule.SuffixFirst);
isNullable = rule.SuffixIsNullable;
}
}
/**
* Returns a new rule path constructed by prepending the given
* rule to a copy of this path.
*/
internal RulePath Prepend (Rule rule)
{
RulePath newpath = new RulePath(this);
newpath.Add(rule);
return newpath;
}
//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
/**
* Returns true iff the given Object is
* a RulePath that is equal to this one.
*/
public override bool Equals (object other)
{
if (!(other is RulePath))
return false;
return IsEqualTo((RulePath)other);
}
/**
* Returns true iff the given RulePath
* that is equal to this one.
*/
internal bool IsEqualTo (RulePath other)
{
if (Length != other.Length)
return false;
if ((start.Index != other.start.Index) || (end.Index != other.end.Index))
return false;
if (!first.IsEqualTo(other.first))
return false;
if (rules == null || other.rules == null)
return false;
for (int i=0; i=0; i--)
buff.Append(((Indexed)rules[i]).Index+"-");
buff.Append(end+"]");
buff.Append(" first = "+first);
if (isNullable)
buff.Append(" (nullable)");
return buff.ToString();
}
}
}