如果您的令牌匹配的输入是"Hello",那么令牌的image 字段的值将是一个7 个字符的字符串,其首尾字符是双引号字符。它们并不是真正额外的,它们是输入中的。说你写
void foo() : {
Token t ; }
{
t = <STRING>
{ System.out.println( t.image ) ; }
}
这将打印 7 个字符,然后是一个换行符。
现在,如果您不想要这些字符,那么,@Bryan 的回答会做到。
void foo() : {
Token t ; }
{
t = <STRING>
{ { String nakedImage = t.image.substring(1,t.image.length()-1) ;
System.out.println( nakedImage ) ; } }
}
需要注意的是没有引号被删除。 String Java 中的对象是不可变的,这意味着它们无法更改。真正发生的是创建了一个新的String 对象,并将对它的引用分配给nakedImage 变量。 t.image 引用的 String 对象保持不变。
现在你仍然有处理反斜杠的问题。如果输入是“Hello\tWorld”,则t.image 的长度为 14 个字符,nakedImage 的长度为 12 个字符。我此时要做的是通过一个函数运行字符串,构建一个新字符串,该字符串具有单个字符,其中 nakedImage 具有转义序列。因此,本例中该函数的结果将是 11 个字符长。
void foo() : {
Token t ; }
{
t = <STRING>
{ { String nakedImage = t.image.substring(1,t.image.length()-1) ;
String unescapedImage = unescape( nakedImage ) ;
System.out.println( unescapedImage ) ; } }
}
这是一个基于我为 Java 编译器编写的函数。
private static String unescape( String str ) {
StringBuffer result = new StringBuffer() ;
for( int i=0, len = str.length() ; i<len ; ) {
char ch = str.charAt(i) ;
// Set ch and increment i ;
if( ch == '\\' ) {
ch = str.charAt(i+1) ;
switch( ch ) {
case 'b' : ch = '\b' ; i += 2 ; break ;
case 't' : ch = '\t' ; i += 2 ; break ;
case 'n' : ch = '\n' ; i += 2 ; break ;
case 'f' : ch = '\f' ; i += 2 ; break ;
case 'r' : ch = '\r' ; i += 2 ; break ;
case '"' : case '\'' : case '\\' : i+= 2 ; break ;
default:
/*TODO Deal with errors. */ } }
else {
i += 1 ; }
result.append( ch ) ; }
return result.toString() ;
}