forked from jasder/antlr
updated [...] parser so it handles < > and [ ] properly. no escapes now.
This commit is contained in:
parent
bc236a6e0b
commit
cd82465830
|
@ -243,7 +243,14 @@ COMMENT
|
|||
ARG_OR_CHARSET
|
||||
options {k=1;}
|
||||
: {isLexerRule}?=> LEXER_CHAR_SET {$type=LEXER_CHAR_SET;}
|
||||
| {!isLexerRule}?=> ARG_ACTION {$type=ARG_ACTION;}
|
||||
| {!isLexerRule}?=> ARG_ACTION
|
||||
{
|
||||
$type=ARG_ACTION;
|
||||
// Set the token text to our gathered string minus outer [ ]
|
||||
String t = $text;
|
||||
t = t.substring(1,t.length()-1);
|
||||
setText(t);
|
||||
}
|
||||
;
|
||||
|
||||
fragment
|
||||
|
@ -261,57 +268,18 @@ LEXER_CHAR_SET
|
|||
//
|
||||
fragment
|
||||
ARG_ACTION
|
||||
@init
|
||||
{
|
||||
StringBuffer theText = new StringBuffer();
|
||||
}
|
||||
: '['
|
||||
: '['
|
||||
(
|
||||
('\\')=>'\\'
|
||||
(
|
||||
(']')=>']'
|
||||
{
|
||||
// We do not include the \ character itself when picking up an escaped ]
|
||||
//
|
||||
theText.append(']');
|
||||
}
|
||||
| c=.
|
||||
{
|
||||
// We DO include the \ character when finding any other escape
|
||||
//
|
||||
theText.append('\\');
|
||||
theText.append((char)$c);
|
||||
}
|
||||
)
|
||||
ARG_ACTION
|
||||
|
||||
| ('"')=>as=ACTION_STRING_LITERAL
|
||||
{
|
||||
// Append the embedded string literal test
|
||||
//
|
||||
theText.append($as.text);
|
||||
}
|
||||
| ('"')=>ACTION_STRING_LITERAL
|
||||
|
||||
| ('\'')=>ac=ACTION_CHAR_LITERAL
|
||||
{
|
||||
// Append the embedded chracter literal text
|
||||
//
|
||||
theText.append($ac.text);
|
||||
}
|
||||
| ('\'')=>ACTION_CHAR_LITERAL
|
||||
|
||||
| c=~']'
|
||||
{
|
||||
// Whatever else we found in the scan
|
||||
//
|
||||
theText.append((char)$c);
|
||||
}
|
||||
| ~('['|']')
|
||||
)*
|
||||
|
||||
']'
|
||||
{
|
||||
// Set the token text to our gathered string
|
||||
//
|
||||
setText(theText.toString());
|
||||
}
|
||||
;
|
||||
|
||||
// -------
|
||||
|
|
|
@ -29,19 +29,19 @@
|
|||
|
||||
package org.antlr.v4.parse;
|
||||
|
||||
import org.antlr.v4.tool.*;
|
||||
import org.antlr.v4.tool.Attribute;
|
||||
import org.antlr.v4.tool.AttributeDict;
|
||||
import org.antlr.v4.tool.ErrorManager;
|
||||
import org.antlr.v4.tool.ErrorType;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/** Parse args, return values, and dynamic scopes.
|
||||
/** Parse args, return values, locals
|
||||
*
|
||||
* rule[arg1, arg2, ..., argN] returns [ret1, ..., retN]
|
||||
* scope { decl1; decl2; ... declN; }
|
||||
*
|
||||
* The ',' and ';' are significant. Use \, and \; to use within
|
||||
* types if necessary like [Map<String\,String> foo, int y].
|
||||
*
|
||||
* arg, ret, and decl are 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".
|
||||
*/
|
||||
public class ScopeParser {
|
||||
|
@ -58,32 +58,15 @@ public class ScopeParser {
|
|||
public static AttributeDict parseTypedArgList(String s, ErrorManager errMgr) { return parse(s, ',', errMgr); }
|
||||
|
||||
public static AttributeDict parse(String s, char separator, ErrorManager errMgr) {
|
||||
int i = 0;
|
||||
int n = s.length();
|
||||
AttributeDict dict = new AttributeDict();
|
||||
while ( i<n ) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
while ( i<n && s.charAt(i)!=separator ) {
|
||||
if ( s.charAt(i)=='\\' ) {
|
||||
i++;
|
||||
if ( i<n && s.charAt(i)==separator ) {
|
||||
buf.append(s.charAt(i));
|
||||
i++;
|
||||
continue;
|
||||
}
|
||||
buf.append('\\');
|
||||
}
|
||||
buf.append(s.charAt(i));
|
||||
i++;
|
||||
}
|
||||
i++; // skip separator
|
||||
String def = buf.toString();
|
||||
//System.out.println("def="+ def);
|
||||
if ( def.trim().length()>0 ) {
|
||||
Attribute a = parseAttributeDef(def, errMgr);
|
||||
List<String> decls = splitDecls(s, separator);
|
||||
for (String decl : decls) {
|
||||
// System.out.println("decl="+decl);
|
||||
if ( decl.trim().length()>0 ) {
|
||||
Attribute a = parseAttributeDef(decl, errMgr);
|
||||
dict.add(a);
|
||||
}
|
||||
}
|
||||
}
|
||||
return dict;
|
||||
}
|
||||
|
||||
|
@ -163,13 +146,12 @@ public class ScopeParser {
|
|||
* convert to a list of attributes. Allow nested square brackets etc...
|
||||
* Set separatorChar to ';' or ',' or whatever you want.
|
||||
*/
|
||||
public static List<String> splitArgumentList(String s, int separatorChar) {
|
||||
public static List<String> splitDecls(String s, int separatorChar) {
|
||||
List<String> args = new ArrayList<String>();
|
||||
_splitArgumentList(s, 0, -1, separatorChar, args);
|
||||
return args;
|
||||
}
|
||||
|
||||
|
||||
public static int _splitArgumentList(String actionText,
|
||||
int start,
|
||||
int targetChar,
|
||||
|
|
|
@ -7,13 +7,15 @@ import org.junit.Test;
|
|||
public class TestScopeParsing extends BaseTest {
|
||||
String[] argPairs = {
|
||||
"", "{}",
|
||||
" ", "{}",
|
||||
" ", "{}",
|
||||
"int i", "{i=int i}",
|
||||
"int[] i, int j[]", "{i=int[] i, j=int [] j}",
|
||||
"Map<A\\,B>[] i, int j[]", "{i=Map<A,B>[] i, j=int [] j}",
|
||||
"Map<A,B>[] i, int j[]", "{i=Map<A,B>[] i, j=int [] j}",
|
||||
"Map<A,List<B>>[] i", "{i=Map<A,List<B>>[] i}",
|
||||
"int i = 34+a[3], int j[] = new int[34]",
|
||||
"{i=int i= 34+a[3], j=int [] j= new int[34]}",
|
||||
"char *foo32[3] = {1\\,2\\,3}", "{3=char *foo32[] 3= {1,2,3}}",
|
||||
"char *foo32[3] = {1,2,3}", "{3=char *foo32[] 3= {1,2,3}}",
|
||||
"String[] headers", "{headers=String[] headers}",
|
||||
|
||||
// python/ruby style
|
||||
"i", "{i=null i}",
|
||||
|
|
Loading…
Reference in New Issue