如何使用ANTLR生成的语法文件? [英] How to use the grammar files generated by ANTLR?

查看:324
本文介绍了如何使用ANTLR生成的语法文件?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我认为这是一个愚蠢的问题,但我刚开始学习ANTLR。我放在一起SimpleCalc语法从他们的教程,并用C生成它作为目标语言。我SimpleCalcParser.c / h和SimpleCalcLexer.c / .H作为输出,我是能够编译这些和构建successfuly。但现在,实际上,我怎么使用的产生code?我无法在这是有帮助的文档发现任何东西。

I think this is a stupid question, but I'm just starting out with ANTLR. I put together the "SimpleCalc" grammar from their tutorials, and generated it with C as the target language. I got SimpleCalcParser.c/.h and SimpleCalcLexer.c/.h as the output, and I was able to compile these and build successfuly. But now, how do I actually use the code that's generated? I'm having trouble finding anything in the docs that's helpful.

下面是我的main()函数。这也是本教程。

Below is my main() function. This is also from the tutorial.

 #include "SimpleCalcLexer.h"

 int main(int argc, char * argv[])
 {

    pANTLR3_INPUT_STREAM           input;
    pSimpleCalcLexer               lex;
    pANTLR3_COMMON_TOKEN_STREAM    tokens;
    pSimpleCalcParser              parser;

    input  = antlr3AsciiFileStreamNew          ((pANTLR3_UINT8)argv[1]);
    lex    = SimpleCalcLexerNew                (input);
    tokens = antlr3CommonTokenStreamSourceNew  (ANTLR3_SIZE_HINT, TOKENSOURCE(lex));
    parser = SimpleCalcParserNew               (tokens);

    parser  ->expr(parser);

    // Must manually clean up
    //
    parser ->free(parser);
    tokens ->free(tokens);
    lex    ->free(lex);
    input  ->close(input);

    return 0;
 }

编辑:每第一个反应,我应该说,我跑这样的程序:./testantlr的test.txt,其中的test.txt载4 + 1。有没有输出。

Per the first response, I should say that I ran the program like this: "./testantlr test.txt", where test.txt contained "4+1". There was no output.

从这里,我将如何,例如,​​访问在生成语法树4,或打印出整个语法树?基本上,我怎么在语法树ANTLR生成?

From here, how would I, for example, access the "4" in the generated syntax tree, or print out the entire syntax tree? Basically, how do I access stuff in the syntax tree that ANTLR generates?

推荐答案

我面临同样的perplexment当我第一次拍了裂纹它。这是一个pretty明显的问题/问题,这使得它更奇怪的是它似乎并没有被明确而直截了当的教程处理。

I faced the same perplexment when I first took a crack at it. It's a pretty obvious question/issue, which makes it more weird that it doesn't seem to be explicitly and straightforwardly addressed in tutorials.

指出,我发现perplexment的方式是'回报'关键字:

The way out of the perplexment that I found is the 'returns' keyword:

token returns [TreeNode value]
    :    WORD { $value = new TreeNode( "word", $WORD.Text ); }
    |    INT { $value = new TreeNode( "int", $INT.Text ); }
    ;

WORD:    ('a'..'z'|'A'..'Z')+;
INT :    ('0'..'9')+;

TreeNode的是,我做了一个类。凡有棘手的是如何处理的说,多个令牌序列做到这一点。我想出了递归是解决的办法:

TreeNode is a class that I made. Where it got tricky was how to do this with a sequence of say, multiple tokens. The solution I came up with was recursion:

expr returns [Accumulator value]
    :   a=token  (WS+ b=expr)?
    {
        if( b != null )
        {
            $value = new Accumulator( "expr", a.value, b.value );
        } else
        {
            $value = new Accumulator( "expr", a.value );
        }
    }
    ;

累加器是我做的,有两个不同的构造函数的类。一个构造函数封装单个令牌,其他封装了一个记号,另一累加器实例。注意本身是递归定义的规则,而 b.value 是一个累加器实例。为什么?由于B是一个EXPR,以及expr的定义有返回[累加器值]

Accumulator is a class that I made that has two different constructors. One constructor encapsulates a single token, and the other encapsulates a single token and another Accumulator instance. Notice the rule itself is defined recursively, and that b.value is an Accumulator instance. Why? Because b is an expr, and the definition of expr has returns [Accumulator value].

最后的结果树是已划分了所有的记号一个累加器实例。实际使用那棵树,你做一些设置,然后调用具有相同的名称,并对此你解析你的内容规则的方法:

The final resulting tree is a single Accumulator instance that has grouped up all the tokens. To actually use that tree, you do some setup and then call the method that has the same name as the rule with respect to which you're parsing your content:

Antlr.Runtime.ANTLRStringStream stringstream =  new Antlr.Runtime.ANTLRStringStream( script );
TokenLexer lexer = new TokenLexer( stringstream );
Antlr.Runtime.CommonTokenStream tokenstream = new Antlr.Runtime.CommonTokenStream( lexer );
TokenParser parser = new TokenParser( tokenstream );

Accumulator grandtree = parser.expr().value;

希望这有助于谁遇到这种perplexion的人。

Hope this helps people who encounter this perplexion.

有收集物品进入名单一个更简单的方法,由于该系统是如何允许你在什么似乎是任意的图案位置点缀目标语言code。成语是:

There's a more straightforward way to collect items into lists, due to how the system allows you to intersperse target-language code at what appears to be arbitrary pattern locations. The idiom is:

sequence returns [String k]
    :   (e=atom { $k = $e.k; })
        (e=atom { $k += ", " + $e.k; })*
        { $k = "sequence (" + $k + ")"; } ;

一个字符串 K 初始化为第一个原子的k值,以及随后的原子获得 + = K 。该段 $ e.k 是指[字符串K] 规则别处定义的原子的回报。如果没有这样的规则,你可以使用文本属性(即 $ e.text ,其中令牌有我不知道,如果非标记具有这种属性如果没有,你可以这样做:

A string k gets initialized to the k value of the first atom, and subsequent atoms get += to k. The snippet $e.k is referring to a atom returns [String k] rule defined elsewhere. If there isn't such a rule, you can use the text property (i.e. $e.text, which tokens have. I'm not sure if non-tokens have this property. If not, you can just do:

nonToken returns [String whatever] : e=TOKEN { $whatever = $e.text; } ;

,你会更高规则,例如再使用。

Which you would then use in higher rules by e.g.

e=nonToken { System.out.println($e.whatever); }

这篇关于如何使用ANTLR生成的语法文件?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆