Antlr中StringTemplate的使用

发布于 2024-11-08 15:33:22 字数 426 浏览 0 评论 0原文

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

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

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

   type: 'Number'|'String' ;

   SEP : '\n'|';' ;

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

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

我的问题是在 Kleene 的 * 中,即如何做我编写模板是为了根据“*”执行上面描述的操作?

感谢您!!!

I would have this problem :
Given this rules

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

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

   type: 'Number'|'String' ;

   SEP : '\n'|';' ;

where I have to do is to associate a template with a rule "defField", that returns the string that represents the xml-schema for the field, that is:

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

my problem is in * of Kleene, that is, how do I write the template to do what I described above in the light of the '*' ??

Thanks you!!!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

睡美人的小仙女 2024-11-15 15:33:22

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

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

现在 v ( List) 包含所有 VAR

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

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

其中必须在 StringTemplateGroup 中声明 defFieldSchema(...),可能看起来像(文件: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">

编辑

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

  • Tg(组合语法文件)
  • 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)         

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

Collect all VAR tokens in a java.util.List by using the += operator:

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

Now v (a List) contains all VAR's.

Then pass t and v as a parameter to a method in your StringTemplateGroup:

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

where defFieldSchema(...) must be declared in your StringTemplateGroup, which might look like (file: T.stg):

group T;

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

The syntax for iterating over a collection is as follows:

<COLLECTION:{ EACH_ITEM_IN_COLLECTION | TEXT_TO_EMIT }>

Ans since vars is a List containing CommonTokens's, I grabbed its .text attribute instead of relying on its toString() method.

Demo

Take the following grammar (file T.g):

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();}
  ;

which can be tested with the following class (file: 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());
  }
}

As you will see when you run this class, it parses the input "Number a,b,c;" and produces the following output:

<xs:element name="a" type="xs:Number">
<xs:element name="b" type="xs:Number">
<xs:element name="c" type="xs:Number">

EDIT

To run the demo, make sure you have all of the following files in the same directory:

  • T.g (the combined grammar file)
  • T.stg (the StringTemplateGroup file)
  • antlr-3.3.jar (the latest stable ANTLR build as of this writing)
  • Main.java (the test class)

then execute to following commands from your OS's shell/prompt (from the same directory all the files are in):

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)         

Probably not necessary to mention, but the # including the text after it should not be a part of the commands: these are only comments to indicate what these commands are for.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文