//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ // PLEASE DO NOT EDIT WITHOUT THE EXPLICIT CONSENT OF THE AUTHOR! \\ //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ using System.Text; using Ilog.Language.Util; using Ilog.Language.Tools; namespace Ilog.Language.Syntax { /** * This is the class of grammar rules used at parser construction time. * * @version Last modified on Sat May 21 20:20:41 2005 by hak * @author Hassan Aït-Kaci * @copyright © 2000 ILOG, S.A. */ internal class Rule : ArrayListIndexed { /** * The grammar this rule belongs to. */ private static Grammar grammar = Grammar.currentGrammar; //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * The symbol sequence (head is at 0). */ private GrammarSymbol[] sequence; internal GrammarSymbol[] Sequence { get { return sequence; } } /** * This rule's forward semantic action. */ private string action; internal string Action { get { return action; } } /** * This rule's backward (undo) semantic action. */ private string undoAction; internal string UndoAction { get { return undoAction; } } /** * A flag to indicate whether it is mandated to generate * a parse node type cast in this rule's semantic actions. */ private bool nodeCast = false; internal bool NodeCast { get { return nodeCast; } } /** * This rule's disambiguator tag symbol. */ private Taggable tag = Grammar.EMPTY; internal Taggable Tag { get { return tag; } set { tag = value; } } /** * This rule's tag's index in the rule's sequence. If -1, the tag does * not correspond to any symbol in the rule (i.e, either the rule's tag * is Grammar.EMPTY or it was set by %prec). */ private int tagPosition = -1; internal int TagPosition { get { return tagPosition; } set { tagPosition = value; } } /** * The indices for this rule's items in Grammar.Items. */ private int[] items; internal int[] Items { get { return items; } } /** * This is the value of the least index in the rule sequence * such that all symbols before it derive the EMPTY symbol. * The head of the rule will be determined to derive EMPTY * whenever this index is equal to the sequence length. It * is initialized to 1 and possibly increased when computing * the FIRST sets. */ private int nullableIndex = 1; internal int NullableIndex { get { return nullableIndex; } set { nullableIndex = value; } } /** * A buffer for this rule's documentation (used when generating * a grammar documentation). */ private StringBuilder doc; internal StringBuilder Doc { get { return doc; } set { doc = value; } } /** * A coded reference name for this rule (used when generating * a grammar documentation). */ private string refName; internal string RefName { get { if (refName == null) refName = Options.GrammarPrefix + "_GR_"+Misc.ZeroPaddedString(Index, Misc.NumWidth(grammar.RCount)); return refName; } } /** * The name of the HTML documentation file for this rule (used * when generating a grammar documentation). */ internal string HtmlFileName { get { return RefName + ".html"; } } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * The nonterminal symbol that is the head of this rule. */ internal NonTerminal Head { get { return (NonTerminal)sequence[0]; } } /** * This rule's precedence */ internal int Precedence { get { return tag.Precedence; } } /** * This rule's associativity */ internal int Associativity { get { return tag.Associativity; } } /** * This rule's isOperator */ internal bool IsOperator { get { return tag.IsOperator; } } /** * This is the FIRST set of the first suffix of this rule. * That is, if this is A -> X S, for some symbol * X, this returns FIRST(S). */ internal SetOf SuffixFirst { get { return grammar.GetItem(this,1).SuffixFirst; } } /** * This is true whenever this is A -> X S, * for some symbol X and S derives EMPTY. */ internal bool SuffixIsNullable { get { return grammar.GetItem(this,1).IsNullable; } } /** * This this rule's RHS's leftmost symbol, or EMPTY if * this is an empty production. */ internal GrammarSymbol LeftMost { get { if (sequence.Length == 1) return Grammar.EMPTY; return sequence[1]; } } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * Constructs a grammar rule with the specified sequence of grammar * symbols. */ internal Rule (GrammarSymbol[] sequence) : base(grammar.Rules,grammar.RCount++) { SetupRule(sequence,"$empty$","$empty$"); } /** * Constructs a grammar rule with the specified sequence of grammar * symbols and forward semantic action. */ internal Rule (GrammarSymbol[] sequence, string action) : base(grammar.Rules,grammar.RCount++) { SetupRule(sequence,action,"$empty$"); } /** * Constructs a grammar rule with the specified sequence of grammar * symbols, and forward and backward semantic actions. */ internal Rule (GrammarSymbol[] sequence, string action, string undo) : base(grammar.Rules,grammar.RCount++) { SetupRule(sequence,action,undo); } /** * Constructs a grammar rule with the specified sequence of grammar * symbols, forward semantic action, and type cast flag. */ internal Rule (GrammarSymbol[] sequence, string action, bool nodeCast) : base(grammar.Rules,grammar.RCount++) { SetupRule(sequence,action,"$empty$"); this.nodeCast = nodeCast; } /** * Constructs a grammar rule with the specified sequence of grammar * symbols, forward and backward semantic actions, and type cast flag. */ internal Rule (GrammarSymbol[] sequence, string action, string undo, bool nodeCast) : base(grammar.Rules,grammar.RCount++) { SetupRule(sequence,action,undo); this.nodeCast = nodeCast; } //\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\ /** * Initilizes this rule with the sequence of symbols comprising it * and its forward-up and backward actions, and adds this rule to the * set of rules of its head nonterminal. It also sets the rule's tag * to the last terminal symbol in its RHS (if any), and records its * position. Finally, it generates all the LR items for this rule. */ private void SetupRule (GrammarSymbol[] sequence, string action, string undo) { this.sequence = sequence; this.action = action; this.undoAction = undo; ((NonTerminal)(sequence[0])).Rules.Add(this); for (int i=sequence.Length-1; i>0; i--) if (sequence[i] is Terminal) { this.tag = (Terminal)sequence[i]; tagPosition = i; break; } GenerateItems(); } /** * Generates all the LR items for this rule. */ internal void GenerateItems () { items = new int[sequence.Length]; for (int i=0; i"; for (int i=1; i