//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // 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(); } } }