Tutorial for walking ANTLR ASTs in C#?

后端 未结 4 1338
一生所求
一生所求 2021-01-31 10:06

Is anyone aware of tutorials for walking ANTLR-generated ASTs in C#? The closest I was able to find is this, but it\'s not terribly helpful.

My goal is to walk through t

4条回答
  •  悲&欢浪女
    2021-01-31 10:41

    Normally you walk ASTs with recursion, and perform different actions based on the kind of the node. If you're using polymorphic tree nodes (i.e. different subclasses for different nodes in the tree), then double-dispatch in the Visitor pattern may be appropriate; however, that's usually not very convenient with Antlr.

    In pseudocode, walking usually looks somewhat like this:

    func processTree(t)
        case t.Type of
            FOO: processFoo t
            BAR: processBar t
        end
    
    // a post-order process
    func processFoo(foo)
        // visit children
        for (i = 0; i < foo.ChildCount; ++i)
            processTree(foo.GetChild(i))
        // visit node
        do_stuff(foo.getText())
    
    // a pre-order process
    func processBoo(bar)
        // visit node
        do_stuff(bar.getText())
        // visit children
        for (i = 0; i < foo.ChildCount; ++i)
            processTree(foo.GetChild(i))
    

    The kinds of processing are highly dependent on the semantics of the language. For example, handling an IF statement, with structure (IF []), when generating code for a stack machine like the JVM or CLR, might look somewhat like this:

    func processIf(n)
        predicate = n.GetChild(0)
        processExpr(predicate) // get predicate value on stack
        falseLabel = createLabel()
        genCode(JUMP_IF_FALSE, falseLabel) // JUMP_IF_FALSE is called brfalse in CLR,
                                           // ifeq in JVM
        if_true = n.GetChild(1)
        processStmt(if_true)
        if_false = n.ChildCount > 2 ? n.GetChild(2) : null
        if (if_false != null)
            doneLabel = createLabel()
            genCode(JUMP, doneLabel)
        markLabel(falseLabel)
        if (if_false != null)
            processStmt(if_false) // if-false branch
            markLabel(doneLabel)
    

    Generally everything is done recursively depending on the type of the current node, etc.

提交回复
热议问题