Udało mi się to rozwiązać, dostosowując przykład pod koniec Manuel Abadia's article.
Oto moja wersja, której używam do konwersji parsowanego kodu na C#. Są to kroki:
- instancję ANTLRStringStream lub podklasy z wejścia (może to być plik lub ciąg znaków).
- Wywołaj wygenerowany lexer, przekazując ten strumień.
- Wywołaj strumień tokenów z lexerem.
- Wywołaj swój analizator składni tym strumieniem tokenów.
- Uzyskaj najwyższy poziom wartości z analizatora składni i przekształć go w
CommonTree
.
- Traverse drzewa:
Aby uzyskać dosłownego tekstu węzła, użyj node.Text
. Aby uzyskać nazwę tokena węzła, należy użyć node.Token.Text
.
Należy pamiętać, że node.Token.Text
poda tylko rzeczywistą nazwę tokenu, jeśli jest to wyimaginowany token bez odpowiedniego ciągu. Jeśli jest to prawdziwy token, to node.Token.Text
zwróci ciąg znaków.
Na przykład, jeśli miał następujące w gramatyce:
tokens { PROGRAM, FUNCDEC }
EQUALS : '==';
ASSIGN : '=';
Wtedy dostaniesz "PROGRAM"
, "FUNCDEC"
, "=="
i "="
z odpowiednich dostępów z node.Token.Text
.
Możesz zobaczyć część mojego przykładu poniżej lub możesz przeglądać full version.
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;
....
}
}
dowolny kod przykładowy drzewa gramatyki dla C#? – Kiquenet