成为ANTLR的新手我试图找出stringtemplates是如何工作的。我想基于一个非常简单的输入文件生成一段Java代码。由于其灵活的概念,我想使用(字符串)模板。 在Java中,通常必须生成成员声明,在其他地方初始化它们,并在其他地方使用它们。标识符名称应匹配,因此重复。这意味着在这里和那里需要很少的模板实例化。当然可以做到,但我似乎无法弄清楚,也许我错过了一些重要的“线索”?
我写了一个测试程序来研究这个概念。它需要一个简单的输入文件:
red = #FF0000
green = #00FF00
blue = #0000FF
并且应该产生类似以下输出的内容:
class MyColors {
// Class members
public java.awt.Color red;
public java.awt.Color green;
public java.awt.Color blue;
// Constructor
/* Question: How to access the right initializer value here?!? The values are not accessible at this level of the grammar*/
public MyColors() {
red = java.awt.Color.getColor("#FF0000");
green = java.awt.Color.getColor("#00FF00");
blue = java.awt.Color.getColor("#0000FF");
}
};
...根据输入填写构造函数中变量和初始值设定项的名称。
我定义的语法如下:
grammar Test;
options {
output=template;
}
colors: (a+=def)+ -> colorClassDef(name={$a});
def: ident '=' name -> colorDef(id={$ident.text}, name={$name.text});
ident: ID;
name: ID;
ID: ('a'..'z'|'A'..'Z'|'#'|'0'..'9')+;
WS: (' '|'\t'|'\r'|'\n')+ { skip(); };
模板定义如下:
group Test;
colorClassDef(name, id) ::= <<
class MyColors {
// Class members
<name:{ v | public java.awt.Color <v>;
}>
// Constructor
/* Question: How to access the initializer value here?!? */
public MyColors() {
<name:{ v | <v> = java.awt.Color.getColor("<id>");
}>
}
};
>>
/* How to return both id and name here seperately, as ID should go into the declaration and name should to into the init? */
colorDef(id, name) ::= <<
<id>
>>
任何人都可以建议我如何获得&lt; id&gt;和&lt; name&gt;超出规则'def'以便将它们包含在生成代码的右侧部分?
我发现了多个有关多个返回值的问题,例如Returning multiple values in ANTLR rule和antlr2 return multiple values,但没有一个包含字符模板。 我甚至买了“书”并按照我的方式编写了java字节码生成器,但没有找到我的答案。所有示例似乎都为一位输入生成一位输出。 (不过没有遗憾,这本书可以很好地读床; - )
有人能指出我错过了什么线索吗?解决这个问题最合适的方法是什么?一些示例代码和指向文档的指针将非常感激。
谢谢,
马腾
答案 0 :(得分:1)
有人可以建议我如何进出规则'def'以便将它们包含在生成代码的右侧部分中吗?
这是一种直接以Java为中心的方法来获得您想要的东西。它并不像我想的那么优雅(我认为还有改进的余地),但我认为它解决了这个问题而没有太多的麻烦。我重命名了一些东西,但我认为我保持了你的方法的精神。
首先是模板。请注意,模板colorClassDef
需要由语法确定的每一位信息:每个id,每个名称以及每个id与其对应名称之间的关联。这是从模板访问所有这些内容之一:
group Colors;
colorClassDef(ids, colors) ::= <<
class MyColors {
// Class members
<ids:{ id | public java.awt.Color <id>;
}>
// Constructor
public MyColors() {
<ids:{ id | <id> = java.awt.Color.getColor("<colors.(id)>");
}>
}
};
>>
这里我使用参数ids
来存储所有传入ID和参数colors
的列表,以存储将id(密钥)与名称(值)相关联的映射。对于构造函数部分,ST使用“间接属性查找”语法colors
从<colors.(id)>
访问id的名称。colors
。由于id
是地图,因此colorClassDef
用作地图的关键字,并将值写入模板。
模板colorDef
处理所有内容,因此我删除了模板grammar Colors;
options {
output=template;
}
colors
@init {
java.util.LinkedList<String> ids = new java.util.LinkedList<String>();
java.util.HashMap<String, String> colors = new java.util.HashMap<String, String>();
}
: (ident '=' name
{ids.add($ident.text); colors.put($ident.text, $name.text);}
)+ EOF
-> colorClassDef(ids={ids}, colors={colors})
;
ident: ID;
name: ID;
ID: ('a'..'z'|'A'..'Z'|'#'|'0'..'9')+;
WS: (' '|'\t'|'\r'|'\n')+ { skip(); };
。
colors
(为了保持语法相对简单,我将规则def
和colors
合并到ident
。)
每个ids
都会添加到列表name
中,并且每个colors
都会添加到映射ident
作为相应public class ColorsTest {
public static void main(String[] args) throws Exception {
final String code = "red = #FF0000\ngreen = #00FF00\nblue = #0000FF";
process(code, "Colors.stg");
}
private static void process(final String code, String templateResourceName)
throws IOException, RecognitionException, Exception {
CharStream input = new ANTLRStringStream(code);
ColorsLexer lexer = new ColorsLexer(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
ColorsParser parser = new ColorsParser(tokens);
InputStream stream = ColorsTest.class.getResourceAsStream(templateResourceName);
Reader reader = new InputStreamReader(stream);
parser.setTemplateLib(new StringTemplateGroup(reader));
reader.close();
stream.close();
ColorsParser.colors_return result = parser.colors();
if (parser.getNumberOfSyntaxErrors() > 0){
throw new Exception("Syntax Errors encountered!");
}
System.out.println(result.toString());
}
}
键的值。然后关闭他们去模板。
这是测试作品的测试类:
red = #FF0000
green = #00FF00
blue = #0000FF
以下是基于您问题中输入的测试用例。
class MyColors {
// Class members
public java.awt.Color red;
public java.awt.Color green;
public java.awt.Color blue;
// Constructor
public MyColors() {
red = java.awt.Color.getColor("#FF0000");
green = java.awt.Color.getColor("#00FF00");
blue = java.awt.Color.getColor("#0000FF");
}
};
{{1}}