updated [...] parser so it handles < > and [ ] properly. no escapes now.

This commit is contained in:
Terence Parr 2012-05-23 12:48:07 -07:00
parent bc236a6e0b
commit cd82465830
3 changed files with 33 additions and 81 deletions

View File

@ -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());
}
;
// -------

View File

@ -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,

View File

@ -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}",