开发者

Use of StringTemplate in Antlr

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 p开发者_开发知识库roblem 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!!!


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜