Мне удалось это выяснить, адаптировав пример в конце Статья Мануэля Абадии .
Вот моя версия, которую я использую для преобразования разобранного кода в C #.
Это шаги:
- Создание ANTLRStringStream или подкласса с вводом (это может быть файл или строка).
- Создайте экземпляр вашего сгенерированного лексера, передавая этот поток строк.
- Создание потока токенов с помощью лексера.
- Создайте свой синтаксический анализатор с этим потоком токенов.
- Получите значение верхнего уровня из вашего анализатора и превратите его в
CommonTree
.
- Пройдите по дереву:
Чтобы получить буквенный текст узла, используйте node.Text
.
Чтобы получить имя токена узла, используйте node.Token.Text
.
Обратите внимание, что node.Token.Text
даст вам действительное имя вашего токена, только если это воображаемый токен без соответствующей строки. Если это настоящий токен, node.Token.Text
вернет его строку.
Например, если в вашей грамматике было следующее:
tokens { PROGRAM, FUNCDEC }
EQUALS : '==';
ASSIGN : '=';
Тогда вы получите "PROGRAM"
, "FUNCDEC"
, "=="
и "="
от соответствующих обращений node.Token.Text
.
Вы можете увидеть часть моего примера ниже, или вы можете просмотреть полную версию .
public static string Convert(string input)
{
ANTLRStringStream sStream = new ANTLRStringStream(input);
MyGrammarLexer lexer = new MyGrammarLexer(sStream);
CommonTokenStream tStream = new CommonTokenStream(lexer);
MyGrammarParser parser = new MyGrammarParser (tStream);
MyGrammarParser.program_return parserResult = parser.program();
CommonTree ast = (CommonTree)parserResult.Tree;
Print(ast);
string output = header + body + footer;
return output;
}
public static void PrintChildren(CT ast)
{
PrintChildren(ast, " ", true);
}
public static void PrintChildren(CT ast, string delim, bool final)
{
if (ast.Children == null)
{
return;
}
int num = ast.Children.Count;
for (int i = 0; i < num; ++i)
{
CT d = (CT)(ast.Children[i]);
Print(d);
if (final || i < num - 1)
{
body += delim;
}
}
}
public static void Print(CommonTree ast)
{
switch (ast.Token.Text)
{
case "PROGRAM":
//body += header;
PrintChildren(ast);
//body += footer;
break;
case "GLOBALS":
body += "\r\n\r\n// GLOBALS\r\n";
PrintChildren(ast);
break;
case "GLOBAL":
body += "public static ";
PrintChildren(ast);
body += ";\r\n";
break;
....
}
}