在Antlr中使用StringTemplate

kaf*_*fka 1 templates antlr stringtemplate antlr3

我会遇到这个问题:给出这个规则

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

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

   type: 'Number'|'String' ;

   SEP : '\n'|';' ;
Run Code Online (Sandbox Code Playgroud)

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

   Number a,b,c ;-> "<xs:element name="a" type = "xs:Number"\>" ,also for b and c.
Run Code Online (Sandbox Code Playgroud)

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

谢谢!!!

Bar*_*ers 6

使用运算符收集a中的所有VAR标记:java.util.List+=

defField
  :  t=type v+=VAR (',' v+=VAR)* SEP 
  ;  
Run Code Online (Sandbox Code Playgroud)

现在v(列表)包含所有VAR的.

然后将tv作为参数传递给StringTemplateGroup中的方法:

defField
  :  t=type v+=VAR (',' v+=VAR)* SEP -> defFieldSchema(type={$t.text}, vars={$v})
  ;  
Run Code Online (Sandbox Code Playgroud)

其中,defFieldSchema(...)必须在StringTemplateGroup,这可能看起来像(:文件中声明T.stg):

group T;

defFieldSchema(type, vars) ::= <<
<vars:{ v | \<xs:element name="<v.text>" type="xs:<type>"\>
}>
>>
Run Code Online (Sandbox Code Playgroud)

迭代集合的语法如下:

<COLLECTION:{ EACH_ITEM_IN_COLLECTION | TEXT_TO_EMIT }>
Run Code Online (Sandbox Code Playgroud)

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();}
  ;
Run Code Online (Sandbox Code Playgroud)

可以使用以下类测试(文件: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());
  }
}
Run Code Online (Sandbox Code Playgroud)

正如您将在运行此类时看到的那样,它会解析输入"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">
Run Code Online (Sandbox Code Playgroud)

编辑

要运行演示,请确保在同一目录中包含以下所有文件:

  • T.g (组合语法文件)
  • T.stg (StringTemplateGroup文件)
  • antlr-3.3.jar (撰写本文时最新的稳定ANTLR版本)
  • Main.java (测试类)

然后从操作系统的shell /提示符(从所有文件所在的同一目录)执行以下命令:

java -cp antlr-3.3.jar org.antlr.Tool T.g  # generate the lexer & parser

javac -cp antlr-3.3.jar *.java             # compile all .java source files

java -cp .:antlr-3.3.jar Main              # run the main class (*nix)
                                           # or
java -cp .;antlr-3.3.jar Main              # run the main class (Windows)         

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