c - ANTLR3 C 目标 - 解析器返回 'misses' 根元素

标签 c antlr antlr3 abstract-syntax-tree

我正在尝试使用 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 而不是 CommonTokens(或者,在您的情况下,等效的 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:

enter image description here

关于c - ANTLR3 C 目标 - 解析器返回 'misses' 根元素,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5441810/

相关文章:

c - 使用 FFMPEG 编码的 Wav 文件在使用 VLC 播放器播放时存在编解码器问题

C11 嵌套初始化

antlr - 何时将美元符号 $ 放在 ANTLR 中对符号的引用处?

antlr - 使用 ANTLR3 解析换行符、EOF 作为语句结束标记

c - 使用无限循环避免重复行,是好是坏?

c - strtok() 包装函数上的 Valgrind 错误

java - ANTLR 中的递归处理规则

c - 任何使用 antlr3 的 C 项目?

java - ANTLR - 语法和树语法之间的 token 枚举不匹配

antlr - 在 antlr 中插入符号前缀而不是后缀