使用ANTLR构建自己的C#编译器:编译单元

yee*_*een 9 c# compiler-construction antlr visitor abstract-syntax-tree

// Create a scanner that reads from the input stream passed to us
 CSLexer lexer = new CSLexer(new ANTLRFileStream(f));
tokens.TokenSource = lexer;

// Create a parser that reads from the scanner
CSParser parser = new CSParser(tokens);

// start parsing at the compilationUnit rule
CSParser.compilation_unit_return x = parser.compilation_unit();
object ast = x.Tree;
Run Code Online (Sandbox Code Playgroud)

我怎么能用compilation_unit_return类型的x来提取它的根,它的类,它的方法等?我必须提取其适配器吗?我怎么做?请注意,compilation_unit_return在我的CSParser中定义(由ANTLR自动生成):

public class compilation_unit_return : ParserRuleReturnScope
    {
        private object tree;
        override public object Tree
        {
            get { return tree; }
            set { tree = (object) value; }
        }
    };
Run Code Online (Sandbox Code Playgroud)

然而,我得到的树是类型对象.我使用调试器运行,似乎看到它是BaseTree类型.但是BaseTree是一个界面!我不知道它与BaseTree的关系,也不知道如何从这棵树中提取细节.

我需要编写一个访问其类,方法,变量等的访问者.ParserRuleReturn类从RuleReturnScope扩展并具有一个start和stop对象,我不知道它是什么.

此外,ANTLR提供的这个TreeVisitor类看起来令人困惑.它需要一个Adapter作为参数传递给它的构造函数(如果不是它将使用默认的CommonTreeAdaptor),这就是我询问如何获取Adapter eariler的原因.还有其他问题.对于API,您可以参考http://www.antlr.org/api/CSharp/annotated.html

Ted*_*ott 6

您可以在文件顶部的语法选项中设置AST树类型,如下所示:

tree grammar CSharpTree;
options { 
    ASTLabelType = CommonTree
}
Run Code Online (Sandbox Code Playgroud)

我将构建第3个语法或将其用于现有的解析器语法,将树转换为您创建的类.例如,假设您有一个与plus运算符匹配的规则,它是2个参数.您可以定义匹配该树的规则,该树创建您已编写的类,我们将其称为PlusExpression,如下所示:

plusExpr returns [PlusExpression value]
   : ^(PLUS left=expr right=expr) { $value = new PlusExpression($left.value, $right.value); }
Run Code Online (Sandbox Code Playgroud)

expr将是语法匹配表达式中的另一个规则.left和right只是给树值的别名.除了替换变量引用之外,{}之间的部分几乎逐字转换为C#代码.$ left和$ right的.value属性来自它们创建的规则指定的返回值.


Pav*_*aev 3

我从未使用过 C# 中的 ANTLR,但是按照您对 API 的链接,BaseTree显然不是一个接口 - 它是一个,并且它具有公共属性:Type获取节点的类型,Text获取(我假设)对应的源文本到它,并Children获取子节点。走路还需要什么?