differentiate prefix/postfix type decl.
This commit is contained in:
parent
3abb193257
commit
03fa75efba
|
@ -32,6 +32,7 @@ package org.antlr.v4.parse;
|
||||||
|
|
||||||
import org.antlr.runtime.BaseRecognizer;
|
import org.antlr.runtime.BaseRecognizer;
|
||||||
import org.antlr.runtime.CommonToken;
|
import org.antlr.runtime.CommonToken;
|
||||||
|
import org.antlr.v4.runtime.misc.IntegerList;
|
||||||
import org.antlr.v4.runtime.misc.Pair;
|
import org.antlr.v4.runtime.misc.Pair;
|
||||||
import org.antlr.v4.tool.Attribute;
|
import org.antlr.v4.tool.Attribute;
|
||||||
import org.antlr.v4.tool.AttributeDict;
|
import org.antlr.v4.tool.AttributeDict;
|
||||||
|
@ -42,26 +43,28 @@ import org.antlr.v4.tool.ast.ActionAST;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
/** Parse args, return values, locals
|
/**
|
||||||
*
|
* Parse args, return values, locals
|
||||||
|
* <p>
|
||||||
* rule[arg1, arg2, ..., argN] returns [ret1, ..., retN]
|
* rule[arg1, arg2, ..., argN] returns [ret1, ..., retN]
|
||||||
*
|
* <p>
|
||||||
* text is target language dependent. Java/C#/C/C++ would
|
* text is target language dependent. Java/C#/C/C++ would
|
||||||
* use "int i" but ruby/python would use "i".
|
* use "int i" but ruby/python would use "i".
|
||||||
*/
|
*/
|
||||||
public class ScopeParser {
|
public class ScopeParser {
|
||||||
/** Given an arg or retval scope definition list like
|
/**
|
||||||
*
|
* Given an arg or retval scope definition list like
|
||||||
|
* <p>
|
||||||
* <code>
|
* <code>
|
||||||
* Map<String, String>, int[] j3, char *foo32[3]
|
* Map<String, String>, int[] j3, char *foo32[3]
|
||||||
* </code>
|
* </code>
|
||||||
*
|
* <p>
|
||||||
* or
|
* or
|
||||||
*
|
* <p>
|
||||||
* <code>
|
* <code>
|
||||||
* int i=3, j=a[34]+20
|
* int i=3, j=a[34]+20
|
||||||
* </code>
|
* </code>
|
||||||
*
|
* <p>
|
||||||
* convert to an attribute scope.
|
* convert to an attribute scope.
|
||||||
*/
|
*/
|
||||||
public static AttributeDict parseTypedArgList(ActionAST action, String s, Grammar g) {
|
public static AttributeDict parseTypedArgList(ActionAST action, String s, Grammar g) {
|
||||||
|
@ -72,8 +75,7 @@ public class ScopeParser {
|
||||||
AttributeDict dict = new AttributeDict();
|
AttributeDict dict = new AttributeDict();
|
||||||
List<Pair<String, Integer>> decls = splitDecls(s, separator);
|
List<Pair<String, Integer>> decls = splitDecls(s, separator);
|
||||||
for (Pair<String, Integer> decl : decls) {
|
for (Pair<String, Integer> decl : decls) {
|
||||||
// System.out.println("decl="+decl);
|
if (decl.a.trim().length() > 0) {
|
||||||
if ( decl.a.trim().length()>0 ) {
|
|
||||||
Attribute a = parseAttributeDef(action, decl, g);
|
Attribute a = parseAttributeDef(action, decl, g);
|
||||||
dict.add(a);
|
dict.add(a);
|
||||||
}
|
}
|
||||||
|
@ -81,69 +83,36 @@ public class ScopeParser {
|
||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** For decls like "String foo" or "char *foo32[]" compute the ID
|
/**
|
||||||
|
* 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")'
|
* 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
|
* but if the separator is ',' you cannot use ',' in the initvalue
|
||||||
* unless you escape use "\," escape.
|
* unless you escape use "\," escape.
|
||||||
*/
|
*/
|
||||||
public static Attribute parseAttributeDef(ActionAST action, Pair<String, Integer> decl, Grammar g) {
|
public static Attribute parseAttributeDef(ActionAST action, Pair<String, Integer> decl, Grammar g) {
|
||||||
if ( decl.a==null ) return null;
|
if (decl.a == null) return null;
|
||||||
|
|
||||||
Attribute attr = new Attribute();
|
Attribute attr = new Attribute();
|
||||||
boolean inID = false;
|
int rightEdgeOfDeclarator = decl.a.length() - 1;
|
||||||
int start = -1;
|
|
||||||
int rightEdgeOfDeclarator = decl.a.length()-1;
|
|
||||||
int equalsIndex = decl.a.indexOf('=');
|
int equalsIndex = decl.a.indexOf('=');
|
||||||
if ( equalsIndex>0 ) {
|
if (equalsIndex > 0) {
|
||||||
// everything after the '=' is the init value
|
// everything after the '=' is the init value
|
||||||
attr.initValue = decl.a.substring(equalsIndex+1,decl.a.length());
|
attr.initValue = decl.a.substring(equalsIndex + 1, decl.a.length());
|
||||||
rightEdgeOfDeclarator = equalsIndex-1;
|
rightEdgeOfDeclarator = equalsIndex - 1;
|
||||||
}
|
|
||||||
// walk backwards looking for start of an ID
|
|
||||||
for (int i=rightEdgeOfDeclarator; i>=0; i--) {
|
|
||||||
// if we haven't found the end yet, keep going
|
|
||||||
if ( !inID && Character.isLetterOrDigit(decl.a.charAt(i)) ) {
|
|
||||||
inID = true;
|
|
||||||
}
|
|
||||||
else if ( inID &&
|
|
||||||
!(Character.isLetterOrDigit(decl.a.charAt(i))||
|
|
||||||
decl.a.charAt(i)=='_') ) {
|
|
||||||
start = i+1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if ( start<0 && inID ) {
|
|
||||||
start = 0;
|
|
||||||
}
|
|
||||||
if ( start<0 ) {
|
|
||||||
g.tool.errMgr.grammarError(ErrorType.CANNOT_FIND_ATTRIBUTE_NAME_IN_DECL, g.fileName, action.token, decl);
|
|
||||||
}
|
|
||||||
// walk forwards looking for end of an ID
|
|
||||||
int stop=-1;
|
|
||||||
for (int i=start; i<=rightEdgeOfDeclarator; i++) {
|
|
||||||
// if we haven't found the end yet, keep going
|
|
||||||
if ( !(Character.isLetterOrDigit(decl.a.charAt(i))||
|
|
||||||
decl.a.charAt(i)=='_') )
|
|
||||||
{
|
|
||||||
stop = i;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if ( i==rightEdgeOfDeclarator ) {
|
|
||||||
stop = i+1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// the name is the last ID
|
String declarator = decl.a.substring(0, rightEdgeOfDeclarator + 1);
|
||||||
attr.name = decl.a.substring(start,stop);
|
Pair<Integer, Integer> p;
|
||||||
|
if (decl.a.indexOf(':') != -1) {
|
||||||
// the type is the decl minus the ID (could be empty)
|
// declarator has type appear after the name
|
||||||
attr.type = decl.a.substring(0,start);
|
p = _parsePostfixDecl(attr, declarator, action, g);
|
||||||
if ( stop<=rightEdgeOfDeclarator ) {
|
|
||||||
attr.type += decl.a.substring(stop,rightEdgeOfDeclarator+1);
|
|
||||||
}
|
}
|
||||||
attr.type = attr.type.trim();
|
else {
|
||||||
if ( attr.type.length()==0 ) {
|
// declarator has type appear before the name
|
||||||
attr.type = null;
|
p = _parsePrefixDecl(attr, declarator, action, g);
|
||||||
}
|
}
|
||||||
|
int idStart = p.a;
|
||||||
|
int idStop = p.b;
|
||||||
|
|
||||||
attr.decl = decl.a;
|
attr.decl = decl.a;
|
||||||
|
|
||||||
|
@ -163,6 +132,7 @@ public class ScopeParser {
|
||||||
int[] charIndexes = new int[actionText.length()];
|
int[] charIndexes = new int[actionText.length()];
|
||||||
for (int i = 0, j = 0; i < actionText.length(); i++, j++) {
|
for (int i = 0, j = 0; i < actionText.length(); i++, j++) {
|
||||||
charIndexes[j] = i;
|
charIndexes[j] = i;
|
||||||
|
// skip comments
|
||||||
if (i < actionText.length() - 1 && actionText.charAt(i) == '/' && actionText.charAt(i + 1) == '/') {
|
if (i < actionText.length() - 1 && actionText.charAt(i) == '/' && actionText.charAt(i + 1) == '/') {
|
||||||
while (i < actionText.length() && actionText.charAt(i) != '\n') {
|
while (i < actionText.length() && actionText.charAt(i) != '\n') {
|
||||||
i++;
|
i++;
|
||||||
|
@ -171,10 +141,10 @@ public class ScopeParser {
|
||||||
}
|
}
|
||||||
|
|
||||||
int declOffset = charIndexes[decl.b];
|
int declOffset = charIndexes[decl.b];
|
||||||
int declLine = lines[declOffset + start];
|
int declLine = lines[declOffset + idStart];
|
||||||
|
|
||||||
int line = action.getToken().getLine() + declLine;
|
int line = action.getToken().getLine() + declLine;
|
||||||
int charPositionInLine = charPositionInLines[declOffset + start];
|
int charPositionInLine = charPositionInLines[declOffset + idStart];
|
||||||
if (declLine == 0) {
|
if (declLine == 0) {
|
||||||
/* offset for the start position of the ARG_ACTION token, plus 1
|
/* offset for the start position of the ARG_ACTION token, plus 1
|
||||||
* since the ARG_ACTION text had the leading '[' stripped before
|
* since the ARG_ACTION text had the leading '[' stripped before
|
||||||
|
@ -183,8 +153,8 @@ public class ScopeParser {
|
||||||
charPositionInLine += action.getToken().getCharPositionInLine() + 1;
|
charPositionInLine += action.getToken().getCharPositionInLine() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = ((CommonToken)action.getToken()).getStartIndex();
|
int offset = ((CommonToken) action.getToken()).getStartIndex();
|
||||||
attr.token = new CommonToken(action.getToken().getInputStream(), ANTLRParser.ID, BaseRecognizer.DEFAULT_TOKEN_CHANNEL, offset + declOffset + start + 1, offset + declOffset + stop);
|
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.setLine(line);
|
||||||
attr.token.setCharPositionInLine(charPositionInLine);
|
attr.token.setCharPositionInLine(charPositionInLine);
|
||||||
assert attr.name.equals(attr.token.getText()) : "Attribute text should match the pseudo-token text at this point.";
|
assert attr.name.equals(attr.token.getText()) : "Attribute text should match the pseudo-token text at this point.";
|
||||||
|
@ -193,11 +163,118 @@ public class ScopeParser {
|
||||||
return attr;
|
return attr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Given an argument list like
|
public static Pair<Integer, Integer> _parsePrefixDecl(Attribute attr, String decl, ActionAST a, Grammar g) {
|
||||||
*
|
// walk backwards looking for start of an ID
|
||||||
|
boolean inID = false;
|
||||||
|
int start = -1;
|
||||||
|
for (int i = decl.length() - 1; i >= 0; i--) {
|
||||||
|
char ch = decl.charAt(i);
|
||||||
|
// if we haven't found the end yet, keep going
|
||||||
|
if (!inID && Character.isLetterOrDigit(ch)) {
|
||||||
|
inID = true;
|
||||||
|
}
|
||||||
|
else if (inID && !(Character.isLetterOrDigit(ch) || ch == '_')) {
|
||||||
|
start = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (start < 0 && inID) {
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
if (start < 0) {
|
||||||
|
g.tool.errMgr.grammarError(ErrorType.CANNOT_FIND_ATTRIBUTE_NAME_IN_DECL, g.fileName, a.token, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// walk forward looking for end of an ID
|
||||||
|
int stop = -1;
|
||||||
|
for (int i = start; i < decl.length(); i++) {
|
||||||
|
char ch = decl.charAt(i);
|
||||||
|
// if we haven't found the end yet, keep going
|
||||||
|
if (!(Character.isLetterOrDigit(ch) || ch == '_')) {
|
||||||
|
stop = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == decl.length() - 1) {
|
||||||
|
stop = i + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the name is the last ID
|
||||||
|
attr.name = decl.substring(start, stop);
|
||||||
|
|
||||||
|
// the type is the decl minus the ID (could be empty)
|
||||||
|
attr.type = decl.substring(0, start);
|
||||||
|
if (stop <= decl.length() - 1) {
|
||||||
|
attr.type += decl.substring(stop, decl.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.type = attr.type.trim();
|
||||||
|
if (attr.type.length() == 0) {
|
||||||
|
attr.type = null;
|
||||||
|
}
|
||||||
|
return new Pair<Integer, Integer>(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Pair<Integer, Integer> _parsePostfixDecl(Attribute attr, String decl, ActionAST a, Grammar g) {
|
||||||
|
int start = -1;
|
||||||
|
int stop = -1;
|
||||||
|
int colon = decl.indexOf(':');
|
||||||
|
int namePartEnd = colon == -1 ? decl.length() : colon;
|
||||||
|
|
||||||
|
// look for start of name
|
||||||
|
for (int i = 0; i < namePartEnd; ++i) {
|
||||||
|
char ch = decl.charAt(i);
|
||||||
|
if (Character.isLetterOrDigit(ch) || ch == '_') {
|
||||||
|
start = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (start == -1) {
|
||||||
|
start = 0;
|
||||||
|
g.tool.errMgr.grammarError(ErrorType.CANNOT_FIND_ATTRIBUTE_NAME_IN_DECL, g.fileName, a.token, decl);
|
||||||
|
}
|
||||||
|
|
||||||
|
// look for stop of name
|
||||||
|
for (int i = start; i < namePartEnd; ++i) {
|
||||||
|
char ch = decl.charAt(i);
|
||||||
|
if (!(Character.isLetterOrDigit(ch) || ch == '_')) {
|
||||||
|
stop = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (i == namePartEnd - 1) {
|
||||||
|
stop = namePartEnd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stop == -1) {
|
||||||
|
stop = start;
|
||||||
|
}
|
||||||
|
|
||||||
|
// extract name from decl
|
||||||
|
attr.name = decl.substring(start, stop);
|
||||||
|
|
||||||
|
// extract type from decl (could be empty)
|
||||||
|
if (colon == -1) {
|
||||||
|
attr.type = "";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
attr.type = decl.substring(colon + 1, decl.length());
|
||||||
|
}
|
||||||
|
attr.type = attr.type.trim();
|
||||||
|
|
||||||
|
if (attr.type.length() == 0) {
|
||||||
|
attr.type = null;
|
||||||
|
}
|
||||||
|
return new Pair<Integer, Integer>(start, stop);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given an argument list like
|
||||||
|
* <p>
|
||||||
* x, (*a).foo(21,33), 3.2+1, '\n',
|
* x, (*a).foo(21,33), 3.2+1, '\n',
|
||||||
* "a,oo\nick", {bl, "fdkj"eck}, ["cat\n,", x, 43]
|
* "a,oo\nick", {bl, "fdkj"eck}, ["cat\n,", x, 43]
|
||||||
*
|
* <p>
|
||||||
* convert to a list of attributes. Allow nested square brackets etc...
|
* convert to a list of attributes. Allow nested square brackets etc...
|
||||||
* Set separatorChar to ';' or ',' or whatever you want.
|
* Set separatorChar to ';' or ',' or whatever you want.
|
||||||
*/
|
*/
|
||||||
|
@ -211,9 +288,8 @@ public class ScopeParser {
|
||||||
int start,
|
int start,
|
||||||
int targetChar,
|
int targetChar,
|
||||||
int separatorChar,
|
int separatorChar,
|
||||||
List<Pair<String, Integer>> args)
|
List<Pair<String, Integer>> args) {
|
||||||
{
|
if (actionText == null) {
|
||||||
if ( actionText==null ) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -222,54 +298,51 @@ public class ScopeParser {
|
||||||
//System.out.println("actionText@"+start+"->"+(char)targetChar+"="+actionText.substring(start,n));
|
//System.out.println("actionText@"+start+"->"+(char)targetChar+"="+actionText.substring(start,n));
|
||||||
int p = start;
|
int p = start;
|
||||||
int last = p;
|
int last = p;
|
||||||
while ( p<n && actionText.charAt(p)!=targetChar ) {
|
while (p < n && actionText.charAt(p) != targetChar) {
|
||||||
int c = actionText.charAt(p);
|
int c = actionText.charAt(p);
|
||||||
switch ( c ) {
|
switch (c) {
|
||||||
case '\'' :
|
case '\'':
|
||||||
p++;
|
p++;
|
||||||
while ( p<n && actionText.charAt(p)!='\'' ) {
|
while (p < n && actionText.charAt(p) != '\'') {
|
||||||
if ( actionText.charAt(p)=='\\' && (p+1)<n &&
|
if (actionText.charAt(p) == '\\' && (p + 1) < n &&
|
||||||
actionText.charAt(p+1)=='\'' )
|
actionText.charAt(p + 1) == '\'') {
|
||||||
{
|
|
||||||
p++; // skip escaped quote
|
p++; // skip escaped quote
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
break;
|
break;
|
||||||
case '"' :
|
case '"':
|
||||||
p++;
|
p++;
|
||||||
while ( p<n && actionText.charAt(p)!='\"' ) {
|
while (p < n && actionText.charAt(p) != '\"') {
|
||||||
if ( actionText.charAt(p)=='\\' && (p+1)<n &&
|
if (actionText.charAt(p) == '\\' && (p + 1) < n &&
|
||||||
actionText.charAt(p+1)=='\"' )
|
actionText.charAt(p + 1) == '\"') {
|
||||||
{
|
|
||||||
p++; // skip escaped quote
|
p++; // skip escaped quote
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
break;
|
break;
|
||||||
case '(' :
|
case '(':
|
||||||
p = _splitArgumentList(actionText,p+1,')',separatorChar,args);
|
p = _splitArgumentList(actionText, p + 1, ')', separatorChar, args);
|
||||||
break;
|
break;
|
||||||
case '{' :
|
case '{':
|
||||||
p = _splitArgumentList(actionText,p+1,'}',separatorChar,args);
|
p = _splitArgumentList(actionText, p + 1, '}', separatorChar, args);
|
||||||
break;
|
break;
|
||||||
case '<' :
|
case '<':
|
||||||
if ( actionText.indexOf('>',p+1)>=p ) {
|
if (actionText.indexOf('>', p + 1) >= p) {
|
||||||
// do we see a matching '>' ahead? if so, hope it's a generic
|
// do we see a matching '>' ahead? if so, hope it's a generic
|
||||||
// and not less followed by expr with greater than
|
// and not less followed by expr with greater than
|
||||||
p = _splitArgumentList(actionText,p+1,'>',separatorChar,args);
|
p = _splitArgumentList(actionText, p + 1, '>', separatorChar, args);
|
||||||
}
|
} else {
|
||||||
else {
|
|
||||||
p++; // treat as normal char
|
p++; // treat as normal char
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '[' :
|
case '[':
|
||||||
p = _splitArgumentList(actionText,p+1,']',separatorChar,args);
|
p = _splitArgumentList(actionText, p + 1, ']', separatorChar, args);
|
||||||
break;
|
break;
|
||||||
default :
|
default:
|
||||||
if ( c==separatorChar && targetChar==-1 ) {
|
if (c == separatorChar && targetChar == -1) {
|
||||||
String arg = actionText.substring(last, p);
|
String arg = actionText.substring(last, p);
|
||||||
int index = last;
|
int index = last;
|
||||||
while (index < p && Character.isWhitespace(actionText.charAt(index))) {
|
while (index < p && Character.isWhitespace(actionText.charAt(index))) {
|
||||||
|
@ -277,20 +350,20 @@ public class ScopeParser {
|
||||||
}
|
}
|
||||||
//System.out.println("arg="+arg);
|
//System.out.println("arg="+arg);
|
||||||
args.add(new Pair<String, Integer>(arg.trim(), index));
|
args.add(new Pair<String, Integer>(arg.trim(), index));
|
||||||
last = p+1;
|
last = p + 1;
|
||||||
}
|
}
|
||||||
p++;
|
p++;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ( targetChar==-1 && p<=n ) {
|
if (targetChar == -1 && p <= n) {
|
||||||
String arg = actionText.substring(last, p).trim();
|
String arg = actionText.substring(last, p).trim();
|
||||||
int index = last;
|
int index = last;
|
||||||
while (index < p && Character.isWhitespace(actionText.charAt(index))) {
|
while (index < p && Character.isWhitespace(actionText.charAt(index))) {
|
||||||
index++;
|
index++;
|
||||||
}
|
}
|
||||||
//System.out.println("arg="+arg);
|
//System.out.println("arg="+arg);
|
||||||
if ( arg.length()>0 ) {
|
if (arg.length() > 0) {
|
||||||
args.add(new Pair<String, Integer>(arg.trim(), index));
|
args.add(new Pair<String, Integer>(arg.trim(), index));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue