public static Attribute parseAttributeDef(ActionAST action, Pair<String, Integer> decl, Grammar g) {
		if (decl.a == null) return null;

		Attribute attr = new Attribute();
		int rightEdgeOfDeclarator = decl.a.length() - 1;
		int equalsIndex = decl.a.indexOf('=');
		if (equalsIndex > 0) {
			// everything after the '=' is the init value
			attr.initValue = decl.a.substring(equalsIndex + 1, decl.a.length()).trim();
			rightEdgeOfDeclarator = equalsIndex - 1;
		}

		String declarator = decl.a.substring(0, rightEdgeOfDeclarator + 1);
		Pair<Integer, Integer> p;
		String text = decl.a;
		text = text.replaceAll("::","");
		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.a;
		int idStop = p.b;

		attr.decl = decl.a;

		if (action != null) {
			String actionText = action.getText();
			int[] lines = new int[actionText.length()];
			int[] charPositionInLines = new int[actionText.length()];
			for (int i = 0, line = 0, col = 0; i < actionText.length(); i++, col++) {
				lines[i] = line;
				charPositionInLines[i] = col;
				if (actionText.charAt(i) == '\n') {
					line++;
					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.charAt(i) == '/' && actionText.charAt(i + 1) == '/') {
					while (i < actionText.length() && actionText.charAt(i) != '\n') {
						i++;
					}
				}
			}

			int declOffset = charIndexes[decl.b];
			int declLine = lines[declOffset + idStart];

			int line = action.getToken().getLine() + 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.getToken().getCharPositionInLine() + 1;
			}

			int offset = ((CommonToken) action.getToken()).getStartIndex();
			attr.token = new CommonToken(action.getToken().getInputStream(), ANTLRParser.ID, BaseRecognizer.DEFAULT_TOKEN_CHANNEL, offset + declOffset + idStart + 1, offset + declOffset + idStop);
			attr.token.setLine(line);
			attr.token.setCharPositionInLine(charPositionInLine);
			assert attr.name.equals(attr.token.getText()) : "Attribute text should match the pseudo-token text at this point.";
		}

		return attr;
	}
For decls like "String foo" or "char *foo32[]" compute the ID
and type declarations.  Also handle "int x=3" and 'T t = new T("foo")'
but if the separator is ',' you cannot use ',' in the initvalue
unless you escape use "\," escape.
tool/src/org/antlr/v4/parse/ScopeParser.java