2

我会遇到这个问题:鉴于此规则

   defField: type VAR ( ',' VAR)* SEP ;  

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

   type: 'Number'|'String' ;

   SEP : '\n'|';' ;

我要做的是将模板与规则“defField”相关联,该规则返回表示该字段的 xml-schema 的字符串,即:

   Number a,b,c ;-> "<xs:element name="a" type = "xs:Number"\>" ,also for b and c.

我的问题出在 Kleene 的 * 中,也就是说,我如何编写模板来根据 '*' 执行我上面描述的操作?

谢谢!!!

4

1 回答 1

6

使用运算符收集VARa 中的所有令牌:java.util.List+=

defField
  :  t=type v+=VAR (',' v+=VAR)* SEP 
  ;  

现在v(一个列表)包含所有VAR的。

然后将tv作为参数传递给您的 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 因为varsList包含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)         

可能没有必要提及,但是#在它之后包含的文本不应该是命令的一部分:这些只是说明这些命令的用途的注释。

于 2011-05-22T20:15:52.707 回答