使用运算符收集VAR
a 中的所有令牌:java.util.List
+=
defField
: t=type v+=VAR (',' v+=VAR)* SEP
;
现在v
(一个列表)包含所有VAR
的。
然后将t
和v
作为参数传递给您的 StringTemplateGroup 中的方法:
defField
: t=type v+=VAR (',' v+=VAR)* SEP -> defFieldSchema(type={$t.text}, vars={$v})
;
wheredefFieldSchema(...)
必须在您的 StringTemplateGroup 中声明,可能类似于(文件:T.stg):
group T;
defFieldSchema(type, vars) ::= <<
<vars:{ v | \<xs:element name="<v.text>" type="xs:<type>"\>
}>
>>
遍历集合的语法如下:
<COLLECTION:{ EACH_ITEM_IN_COLLECTION | TEXT_TO_EMIT }>
Ans 因为vars
是List
包含CommonTokens
的,所以我抓住了它的.text
属性而不是依赖它的toString()
方法。
演示
采用以下语法(文件Tg):
grammar T;
options {
output=template;
}
defField
: t=type v+=VAR (',' v+=VAR)* SEP -> defFieldSchema(type={$t.text}, vars={$v})
;
type
: NUMBER
| STRING
;
NUMBER
: 'Number'
;
STRING
: 'String'
;
VAR
: ('a'..'z'|'A'..'Z')+
;
SEP
: '\n'
| ';'
;
SPACE
: ' ' {skip();}
;
可以使用以下类(文件:Main.java)进行测试:
import org.antlr.runtime.*;
import org.antlr.stringtemplate.*;
import java.io.*;
public class Main {
public static void main(String[] args) throws Exception {
StringTemplateGroup group = new StringTemplateGroup(new FileReader("T.stg"));
ANTLRStringStream in = new ANTLRStringStream("Number a,b,c;");
TLexer lexer = new TLexer(in);
CommonTokenStream tokens = new CommonTokenStream(lexer);
TParser parser = new TParser(tokens);
parser.setTemplateLib(group);
TParser.defField_return returnValue = parser.defField();
StringTemplate st = (StringTemplate)returnValue.getTemplate();
System.out.println(st.toString());
}
}
正如您在运行此类时将看到的,它解析输入"Number a,b,c;"
并产生以下输出:
<xs:element name="a" type="xs:Number">
<xs:element name="b" type="xs:Number">
<xs:element name="c" type="xs:Number">
编辑
要运行演示,请确保您在同一目录中具有以下所有文件:
T.g
(组合语法文件)
T.stg
(字符串模板组文件)
antlr-3.3.jar
(撰写本文时最新的稳定 ANTLR 版本)
Main.java
(测试类)
然后从操作系统的 shell/prompt 执行以下命令(所有文件都在同一目录中):
java -cp antlr-3.3.jar org.antlr.Tool Tg # 生成词法分析器和解析器
javac -cp antlr-3.3.jar *.java # 编译所有.java源文件
java -cp .:antlr-3.3.jar Main # 运行主类 (*nix)
# 或者
java -cp .;antlr-3.3.jar Main # 运行主类(Windows)
可能没有必要提及,但是#
在它之后包含的文本不应该是命令的一部分:这些只是说明这些命令的用途的注释。