public static Attribute ParseAttributeDef([Nullable] ActionAST action, [NotNull] System.Tuple<string, int> decl, Grammar g)
{
if (decl.Item1 == null)
return null;
Attribute attr = new Attribute();
int rightEdgeOfDeclarator = decl.Item1.Length - 1;
int equalsIndex = decl.Item1.IndexOf('=');
if (equalsIndex > 0)
{
// everything after the '=' is the init value
attr.initValue = decl.Item1.Substring(equalsIndex + 1).Trim();
rightEdgeOfDeclarator = equalsIndex - 1;
}
string declarator = decl.Item1.Substring(0, rightEdgeOfDeclarator + 1);
System.Tuple<int, int> p;
string text = decl.Item1;
text = text.Replace("::", "");
if (text.Contains(":"))
{
// declarator has type appearing after the name like "x:T"
p = _ParsePostfixDecl(attr, declarator, action, g);
}
else
{
// declarator has type appearing before the name like "T x"
p = _ParsePrefixDecl(attr, declarator, action, g);
}
int idStart = p.Item1;
int idStop = p.Item2;
attr.decl = decl.Item1;
if (action != null)
{
string actionText = action.Text;
int[] lines = new int[actionText.Length];
int[] charPositionInLines = new int[actionText.Length];
for (int i = 0, line1 = 0, col = 0; i < actionText.Length; i++, col++)
{
lines[i] = line1;
charPositionInLines[i] = col;
if (actionText[i] == '\n')
{
line1++;
col = -1;
}
}
int[] charIndexes = new int[actionText.Length];
for (int i = 0, j = 0; i < actionText.Length; i++, j++)
{
charIndexes[j] = i;
// skip comments
if (i < actionText.Length - 1 && actionText[i] == '/' && actionText[i + 1] == '/')
{
while (i < actionText.Length && actionText[i] != '\n')
{
i++;
}
}
}
int declOffset = charIndexes[decl.Item2];
int declLine = lines[declOffset + idStart];
int line = action.Token.Line + declLine;
int charPositionInLine = charPositionInLines[declOffset + idStart];
if (declLine == 0)
{
/* offset for the start position of the ARG_ACTION token, plus 1
* since the ARG_ACTION text had the leading '[' stripped before
* reaching the scope parser.
*/
charPositionInLine += action.Token.CharPositionInLine + 1;
}
int offset = ((CommonToken)action.Token).StartIndex;
attr.token = new CommonToken(action.Token.InputStream, ANTLRParser.ID, BaseRecognizer.DefaultTokenChannel, offset + declOffset + idStart + 1, offset + declOffset + idStop);
attr.token.Line = line;
attr.token.CharPositionInLine = charPositionInLine;
Debug.Assert(attr.name.Equals(attr.token.Text), "Attribute text should match the pseudo-token text at this point.");
}
return attr;
}