//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\//\\
// 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