public virtual string Text(GrammarAST t)
{
if (t == null)
return "";
int tokenStartIndex = t.TokenStartIndex;
int tokenStopIndex = t.TokenStopIndex;
// ignore tokens from existing option subtrees like:
// (ELEMENT_OPTIONS (= assoc right))
//
// element options are added back according to the values in the map
// returned by getOptions().
IntervalSet ignore = new IntervalSet();
IList<GrammarAST> optionsSubTrees = t.GetNodesWithType(ELEMENT_OPTIONS);
foreach (GrammarAST sub in optionsSubTrees)
{
ignore.Add(sub.TokenStartIndex, sub.TokenStopIndex);
}
// Individual labels appear as RULE_REF or TOKEN_REF tokens in the tree,
// but do not support the ELEMENT_OPTIONS syntax. Make sure to not try
// and add the tokenIndex option when writing these tokens.
IntervalSet noOptions = new IntervalSet();
IList<GrammarAST> labeledSubTrees = t.GetNodesWithType(new IntervalSet(ASSIGN, PLUS_ASSIGN));
foreach (GrammarAST sub in labeledSubTrees)
{
noOptions.Add(sub.GetChild(0).TokenStartIndex);
}
StringBuilder buf = new StringBuilder();
int i = tokenStartIndex;
while (i <= tokenStopIndex)
{
if (ignore.Contains(i))
{
i++;
continue;
}
IToken tok = tokenStream.Get(i);
// Compute/hold any element options
StringBuilder elementOptions = new StringBuilder();
if (!noOptions.Contains(i))
{
GrammarAST node = t.GetNodeWithTokenIndex(tok.TokenIndex);
if (node != null &&
(tok.Type == TOKEN_REF ||
tok.Type == STRING_LITERAL ||
tok.Type == RULE_REF))
{
elementOptions.Append("tokenIndex=").Append(tok.TokenIndex);
}
if (node is GrammarASTWithOptions)
{
GrammarASTWithOptions o = (GrammarASTWithOptions)node;
foreach (KeyValuePair<string, GrammarAST> entry in o.GetOptions())
{
if (elementOptions.Length > 0)
{
elementOptions.Append(',');
}
elementOptions.Append(entry.Key);
elementOptions.Append('=');
elementOptions.Append(entry.Value.Text);
}
}
}
buf.Append(tok.Text); // add actual text of the current token to the rewritten alternative
i++; // move to the next token
// Are there args on a rule?
if (tok.Type == RULE_REF && i <= tokenStopIndex && tokenStream.Get(i).Type == ARG_ACTION)
{
buf.Append('[' + tokenStream.Get(i).Text + ']');
i++;
}
// now that we have the actual element, we can add the options.
if (elementOptions.Length > 0)
{
buf.Append('<').Append(elementOptions).Append('>');
}
}
return buf.ToString();
}