ANTLR - Написание древовидной грамматики для AST
У меня есть AST, выведенный для некоторого кода Lua моим файлом грамматики, который в настоящее время выполняет синтаксический анализ и лексирование для меня. Я хочу добавить к этому древовидную грамматику, но так как я использую C#, я не уверен, как это сделать. Каков основной процесс генерации древовидного грамматического кода, когда у вас уже есть парсер и лексер?
ОБНОВЛЕНИЕ: у меня есть следующий файл грамматики:
tree grammar LuaGrammar;
options {
backtrack=true;
language=CSharp2;
//output=AST;
tokenVocab=Lua;
filter=true;
ASTLabelType=CommonTree;
}
@lexer::namespace{/*my namespace*/}
@parser::namespace{/*my namespace*/}
dummyRule
: ^('=' x=. y=.) {};
находится в том же каталоге, что и мой основной файл грамматики, который генерирует нормально. Тем не менее, при попытке скомпилировать это я получаю следующие ошибки:
[02:54:06] error(143): C:\Users\RCIX\Desktop\AguaLua\Project\trunk\AguaLua\AguaLua\ANTLR Data\LuaGrammar.g:12:18: unknown or invalid action scope for tree grammar: lexer
[02:54:06] error(143): C:\Users\RCIX\Desktop\AguaLua\Project\trunk\AguaLua\AguaLua\ANTLR Data\LuaGrammar.g:13:19: unknown or invalid action scope for tree grammar: parser
Я на правильном пути или полностью выключен?
2 ответа
Я не сталкивался с этой ошибкой, но есть две вещи, которые я бы попробовал.
1) удалить строки пространства имен @lexer и @parser.
2) Если они необходимы, перемещайте их до раздела "Жетоны" {...} вашей грамматики, то есть непосредственно перед правилами.
Хорошо возвращаясь к моему обычному примеру грамматики калькулятора:)
Вот как бы вы объявили свой класс Tree Walker
class CalcTreeShaker extends TreeParser;
expr returns [float r]
{
float a,b;
r=0;
}
: #(PLUS a=expr b=expr) {r = a+b;}
| #(STAR a=expr b=expr) {r = a*b;}
| i:INT {r = Convert.ToSingle(i.getText());}
;
Здесь у нас есть правило дерева под названием expr
, Ходоки деревьев очень похожи на грамматики синтаксического анализатора.
Большая разница в том, что хотя грамматика синтаксического анализатора должна точно соответствовать грамматике дерева, она должна соответствовать только части дерева.
в expr
Правило, которое мы можем видеть, соответствует любому дереву, имеющему токены PLUS
или же STAR
или же INT
,
Мы можем видеть, что мы сопоставляем деревья, потому что мы используем синтаксис Antlr Tree #(...)
,
PLUS
а также STAR
дерево также соответствует 2 правилам expr. Каждому правилу expr присваивается имя, поэтому мы можем использовать его для оценки выражения. Подобно грамматикам парсера, мы можем поместить код C# в блоки, определяемые {...}
,
Также обратите внимание, что в этом примере мы показываем, как вернуть значение из правила TreeWalker, мы используем синтаксис return [...]
,
Чтобы вызвать дерево, вы создаете его, а затем называете его правилом верхнего уровня. Я скопирую это из примера Antlr:)
// Get the ast from your parser.
CommonAST t = (CommonAST)parser.getAST();
// Create the Tree Shaker
CalcTreeWalker walker = new CalcTreeWalker();
CalcParser.initializeASTFactory(walker.getASTFactory());
// pass the ast to the walker and call the top level rule.
float r = walker.expr(t);