Я пытаюсь использовать цель C ANTLR3 для определения AST, но сталкиваюсь с некоторыми трудностями.
У меня есть простой SQL-подобный файл грамматики:
grammar sql;
options
{
language = C;
output=AST;
ASTLabelType=pANTLR3_BASE_TREE;
}
sql : VERB fields;
fields : FIELD (',' FIELD)*;
VERB : 'SELECT' | 'UPDATE' | 'INSERT';
FIELD : CHAR+;
fragment
CHAR : 'a'..'z';
и это работает как ожидалось в ANTLRWorks.
В моем коде C есть:
const char pInput[] = "SELECT one,two,three";
pANTLR3_INPUT_STREAM pNewStrm = antlr3NewAsciiStringInPlaceStream((pANTLR3_UINT8) pInput,sizeof(pInput),NULL);
psqlLexer lex = sqlLexerNew (pNewStrm);
pANTLR3_COMMON_TOKEN_STREAM tstream = antlr3CommonTokenStreamSourceNew(ANTLR3_SIZE_HINT,
TOKENSOURCE(lex));
psqlParser ps = sqlParserNew( tstream );
sqlParser_sql_return ret = ps->sql(ps);
pANTLR3_BASE_TREE pTree = ret.tree;
cout << "Tree: " << pTree->toStringTree(pTree)->chars << endl;
ParseSubTree(0,pTree);
Это выводит плоскую древовидную структуру, когда вы используете ->getChildCount
и ->children->get
для прохода по дереву.
void ParseSubTree(int level,pANTLR3_BASE_TREE pTree)
{
ANTLR3_UINT32 childcount = pTree->getChildCount(pTree);
for (int i=0;i<childcount;i++)
{
pANTLR3_BASE_TREE pChild = (pANTLR3_BASE_TREE) pTree->children->get(pTree->children,i);
for (int j=0;j<level;j++)
{
std::cout << " - ";
}
std::cout <<
pChild->getText(pChild)->chars <<
std::endl;
int f=pChild->getChildCount(pChild);
if (f>0)
{
ParseSubTree(level+1,pChild);
}
}
}
Вывод программы:
Дерево: ВЫБЕРИТЕ один, два, три
ВЫБРАТЬ
один
,
два
,
три
Теперь, если я изменю файл грамматики:
sql : VERB ^fields;
.. вызов ParseSubTree отображает только дочерние узлы полей.
Вывод программы:
Дерево: (ВЫБЕРИТЕ один, два, три)
один
,
два
,
три
Мой вопрос: почему во втором случае Antlr просто дает дочерние узлы? (фактически отсутствует токен SELECT)
Я был бы очень признателен, если кто-нибудь может дать мне какие-либо указатели для понимания дерева, возвращенного Antlr.
Полезная информация:
AntlrWorks 1.4.2,
Antlr C Target 3.3,
MSVC 10