Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/mercurial/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Antlr setText没有按我预期的方式工作_Antlr_Antlr3 - Fatal编程技术网

Antlr setText没有按我预期的方式工作

Antlr setText没有按我预期的方式工作,antlr,antlr3,Antlr,Antlr3,我需要将标识符转换为beanutil字符串,以便从对象检索项。标识符到字符串的转换如下所示: name ==> name attribute.name ==> attributes(name)[0].value attribute.name[2] ==> attributes(name)[2]

我需要将标识符转换为beanutil字符串,以便从对象检索项。标识符到字符串的转换如下所示:

name                                        ==> name
attribute.name                              ==> attributes(name)[0].value
attribute.name[2]                           ==> attributes(name)[2].value
address.attribute.postalcode                ==> contactDetails.addresses[0].attributes(postalcode)[0].value
address[2].attribute.postalcode             ==> contactDetails.addresses[2].attributes(postalcode)[0].value
address[2].attribute.postalcode[3]          ==> contactDetails.addresses[2].attributes(postalcode)[3].value
现在我决定使用antlr来实现这一点,因为我觉得它的速度可能和使用一组“if”语句一样快。别客气,告诉我我错了

现在,我已经使用antlr完成了部分工作,但是一旦我开始执行“地址”部分,setText部分似乎就不再为属性工作了

我这样做是正确的还是有更好的方法使用antlr来获得我想要的结果

grammar AttributeParser;

parse returns [ String result ]
:  Address EOF { $result = $Address.text; }
|  Attribute EOF { $result = $Attribute.text; }
|  Varname EOF { $result = $Varname.text; }
;

Address
: 'address' (Arraypos)* '.' Attribute { setText("contactDetails.addresses" + ($Arraypos == null ? "[0]" : $Arraypos.text ) + "." + $Attribute.text); }
; 

Attribute
:  'attribute.' Varname (Arraypos)* { setText("attributes(" + $Varname.text + ")" + ($Arraypos == null ? "[0]" : $Arraypos.text ) + ".value"); }
;

Arraypos
: '[' Number+ ']'
;


Varname  
:  ('a'..'z'|'A'..'Z')+
;

Number
: '0'..'9'+
;

Spaces
:  (' ' | '\t' | '\r' | '\n')+ { setText(" "); }
;
下面是两个单元测试,第一个返回我期望的结果,第二个没有

@Test
public void testSimpleAttributeWithArrayRef() throws Exception {

    String source = "attribute.name[2]";
    ANTLRStringStream in = new ANTLRStringStream(source);
    AttributeParserLexer lexer = new AttributeParserLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    AttributeParserParser parser = new AttributeParserParser(tokens);
    String result = parser.parse();
    assertEquals("attributes(name)[2].value", result);       
}

@Test
public void testAddress() throws Exception {

    String source = "address.attribute.postalcode";
    ANTLRStringStream in = new ANTLRStringStream(source);
    AttributeParserLexer lexer = new AttributeParserLexer(in);
    CommonTokenStream tokens = new CommonTokenStream(lexer);
    AttributeParserParser parser = new AttributeParserParser(tokens);
    String result = parser.parse();
    System.out.println("Result: " + result);
    assertEquals("contactDetails.addresses[0].attributes(postalcode)[0].value", result);       
}
不,您不能执行
(Arraypos)*
,然后将内容引用为:
$Arraypos.text

我不会去更改令牌的内部文本,而是创建一些解析器规则,让它们返回适当的文本

一个小演示:

语法属性分析器;
解析返回[String s]
:input EOF{$s=$input.s;}
;
输入返回[String s]
:地址{$s=$address.s;}
|属性{$s=$attribute.s;}
|Varname{$s=$Varname.text;}
;
地址返回[String s]
:地址arrayPos'.'属性
{$s=“contactDetails.addresses”+$arrayPos.s+“+$attribute.s;}
;
属性返回[String s]
:属性“.”Varname arrayPos
{$s=“attributes(“+$Varname.text+”)+$arrayPos.s+.value”;}
;
arrayPos返回[String s]
:Arraypos{$s=$Arraypos.text;}
|/*无*/{$s=“[0]”;}
;
属性:'属性';
地址:‘地址’;
Arraypos:'['0'..'9'+']';
变量名:('a'..'z'|'a'..'z')+;
可通过以下方式进行测试:

import org.antlr.runtime.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
字符串[][]测试={
{“name”,“name”},
{“attribute.name”,“attributes(name)[0].value”},
{“attribute.name[2],“attributes(name)[2].value”},
{“address.attribute.postalcode”,“contactDetails.addresses[0]。属性(postalcode)[0]。值”},
{“地址[2].属性.postalcode”,“联系人详细信息.地址[2].属性(postalcode)[0].值”},
{“地址[2].属性.postalcode[3],“联系人详细信息.地址[2].属性(postalcode)[3].值”}
};
for(字符串[]测试:测试){
字符串输入=测试[0];
预期字符串=测试[1];
AttributeParserLexer lexer=新的AttributeParserLexer(新的AntlStringStream(输入));
AttributeParserParser=new AttributeParserParser(new CommonTokenStream(lexer));
字符串输出=parser.parse();
如果(!output.equals(预期)){
抛出新的运行时异常(预期输出+“!=”+);
}
System.out.printf(“in=%s\nout=%s\n\n”,输入、输出,应为);
}
}
}
要运行演示,请执行以下操作:

java-cp antlr-3.3.jar org.antlr.Tool AttributeParser.g
javac-cp antlr-3.3.jar*.java
java-cp.:antlr-3.3.jar Main
将在控制台上打印以下内容:

in=name
out=名称
in=attribute.name
out=属性(名称)[0]。值
in=attribute.name[2]
out=属性(名称)[2]。值
in=address.attribute.postalcode
out=contactDetails.addresses[0]。属性(postalcode)[0]。值
in=地址[2]。属性.postalcode
out=contactDetails.addresses[2]。属性(postalcode)[0]。值
in=地址[2]。属性。后代码[3]
out=contactDetails.addresses[2]。属性(postalcode)[3]。值
编辑 请注意,您还可以让解析器规则返回多个对象,如下所示:

条
:foo{System.out.println($foo.text+“,“+$foo.number);}
;
foo返回[字符串文本,整数]
:'FOO'{$text=“a”;$number=1;}
|'foo'{$text=“b”;$number=2;}
;
不,您不能执行
(Arraypos)*
然后将内容引用为:
$Arraypos.text

我不会去更改令牌的内部文本,而是创建一些解析器规则,让它们返回适当的文本

一个小演示:

语法属性分析器;
解析返回[String s]
:input EOF{$s=$input.s;}
;
输入返回[String s]
:地址{$s=$address.s;}
|属性{$s=$attribute.s;}
|Varname{$s=$Varname.text;}
;
地址返回[String s]
:地址arrayPos'.'属性
{$s=“contactDetails.addresses”+$arrayPos.s+“+$attribute.s;}
;
属性返回[String s]
:属性“.”Varname arrayPos
{$s=“attributes(“+$Varname.text+”)+$arrayPos.s+.value”;}
;
arrayPos返回[String s]
:Arraypos{$s=$Arraypos.text;}
|/*无*/{$s=“[0]”;}
;
属性:'属性';
地址:‘地址’;
Arraypos:'['0'..'9'+']';
变量名:('a'..'z'|'a'..'z')+;
可通过以下方式进行测试:

import org.antlr.runtime.*;
公共班机{
公共静态void main(字符串[]args)引发异常{
字符串[][]测试={
{“name”,“name”},
{“attribute.name”,“attributes(name)[0].value”},
{“attribute.name[2],“attributes(name)[2].value”},
{“address.attribute.postalcode”,“contactDetails.addresses[0]。属性(postalcode)[0]。值”},
{“地址[2].属性.postalcode”,“联系人详细信息.地址[2].属性(postalcode)[0].值”},
{“地址[2].属性.postalcode[3],“联系人详细信息.地址[2].属性(postalcode)[3].值”}
};
for(字符串[]测试:测试){
字符串输入=测试[0];
预期字符串=测试[1];
AttributeParserLexer lexer=新的AttributeParserLexer(新的AntlStringStream(输入));
AttributeParserParser=new AttributeParserParser(new CommonTokenStream(lexer));
s