(я нуб с Antlr) ... У меня проблемы с получением моей грамматики с помощью StringTemplates. В основном я пытаюсь написать немного DSL. Я могу получить мою грамматику так, как я хочу (она анализируется правильно), но я не могу заставить генерацию целевого кода работать с шаблонами. Итак, вот фрагмент моей грамматики:
grammar Pfig;
options {
output=template;
language=CSharp2;
}
conf
: globalName
;
globalName
: 'GlobalName:' ID
-> localConf(name ={$ID.text})
;
Я немного упростил это, просто чтобы объяснить суть. По сути, когда lex / parse встречается с `GlobalName: Foo ', я хочу, чтобы он выплевывал текст на основе StringTemplate, называемого localConf. Супер просто.
Итак, давайте запустим парсер в тестовом приложении и обработаем входной файл.
// C# processing a file with the lex/parser.
// the 'app.pfig' file just has one line that reads 'GlobalName: Bla'
using (FileStream fs = File.OpenRead("c:\\app.pfig"))
{
PfigParser parser = new PfigParser(new CommonTokenStream(
new PfigLexer(new ANTLRInputStream(fs))));
using (TextReader tr = File.OpenText("./Pfig.stg"))
{
parser.TemplateLib = new StringTemplateGroup(tr);
}
var parseResult = parser.conf();
string code = parseResult.Template.ToString(); // Fail: template is null
}
Я могу просмотреть код синтаксического анализатора и убедиться, что он правильно идентифицирует мой текст и правильно применяет stringTemplate . Проблема в том, что поскольку это правило globalName является подправилом conf, оно не выполняется напрямую - метод просто находит его и возвращает. Но вызывающий метод 'Conf' не сохраняет возвращаемое значение из подчиненного правила - он уходит в воздух. Это означает, что мой результирующий шаблон в последней строке является нулевым.
Если я избавлюсь от правила 'conf' в моей грамматике и сразу вызову 'globalName', оно будет работать (так как это единственное правило в стеке). Но я, очевидно, хочу больше, чем одно правило. Я создал парсер в Java, и он делает то же самое:
// antlr generated parser code
public PfigParser.conf_return conf() // throws RecognitionException [1]
{
PfigParser.conf_return retval = new PfigParser.conf_return();
try
{
{
PushFollow(FOLLOW_globalName_in_conf30);
globalName(); // <- it calls globalName() but doesn't keep the return.
state.followingStackPointer--;
}
retval.Stop = input.LT(-1);
}
// snip
Легко видеть, что у меня нет какой-то базовой концепции о том, как шаблонный подход должен работать с Antlr. Я вполне уверен, что это моя проблема, но я не могу понять, что я делаю неправильно ... примеры, которые я видел, на самом деле не показывают реальную передачу шаблона из кода .