我正在尝试使用 ANTLR3 C 目标来理解 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 token ) 如果有人能给我任何指导来理解 Antlr 返回的树,我将非常感激。
有用信息: AntlrWorks 1.4.2, Antlr C 目标 3.3, MSVC 10
最佳答案
将 output=AST;
放在选项部分不会产生实际的 AST,它只会导致 ANTLR 创建 CommonTree
token 而不是 CommonToken
s(或者,在您的情况下,等效的 C 结构)。
如果您使用 output=AST;
,下一步是放置树运算符,或在解析器规则中重写规则,以形成 AST。
查看此previous Q&A了解如何创建正确的 AST。
例如,以下语法(带有重写规则):
options {
output=AST;
// ...
}
sql // make VERB the root
: VERB fields -> ^(VERB fields)
;
fields // omit the comma's from the AST
: FIELD (',' FIELD)* -> FIELD+
;
VERB : 'SELECT' | 'UPDATE' | 'INSERT';
FIELD : CHAR+;
SPACE : ' ' {$channel=HIDDEN;};
fragment CHAR : 'a'..'z';
将解析以下输入:
UPDATE field, foo , bar
进入以下 AST:
关于c - ANTLR3 C 目标 - 解析器返回 'misses' 根元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5441810/