reading signs in an equation

Viewed 42

Using this https://github.com/antlr/grammars-v4/tree/master/cpp antlr grammar Im trying to parse C++ code. Below is the same visitor class I'm using, I don't have much visitor function implemented,

#include <iostream>
#include <antlr4-runtime.h>

#include "parser/CPP14Lexer.h"
#include "parser/CPP14BaseVisitor.h"
#include "parser/CPP14Parser.h"
#include "parser/CPP14Visitor.h"


class TREEVisitor : public CPP14BaseVisitor {
    public:
        virtual antlrcpp::Any TREEVisitor::visitAdditiveExpression(
            CPP14Parser::AdditiveExpressionContext *ctx) override
        {
            std::cout << "AddExpr : " << ctx->getText() << std::endl;

            std::vector<CPP14Parser::MultiplicativeExpressionContext *> mulpExprCtx = 
                ctx->multiplicativeExpression();

            for (CPP14Parser::MultiplicativeExpressionContext *mulpExprLp : mulpExprCtx)
            {
                std::vector<CPP14Parser::PointerMemberExpressionContext *> ptrMbrExprCtx =
                    mulpExprLp->pointerMemberExpression();

                // ptrMbrExprCtx->pointerMemberExpression()->castExpression()->unaryExpression();

                // Different parts of an expression
                for (CPP14Parser::PointerMemberExpressionContext *ptrMbrExprLp : ptrMbrExprCtx)
                {
                    std::cout << "=> " << ptrMbrExprLp->getText() << std::endl;
                }
            }
            return visitChildren(ctx);
        }
};


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

    std::ifstream stream;
    stream.open(argv[1]);
    antlr4::ANTLRInputStream input(stream);
    CPP14Lexer lexer(&input);
    antlr4::CommonTokenStream tokens(&lexer);
    CPP14Parser parser(&tokens);
    antlr4::tree::ParseTree *tree = parser.translationunit();

    // Visitor
    auto *visitor = new TREEVisitor();
    visitor->visit(tree);

    return 0;
}

Im trying to parse the following C++ code,

int ii = a + b - getLength() * 10 / 1;

What I'm trying to achieve here is to get all of the variables that are used to initilize the variable i and their signs. Something like below, where i can relate each sign to the values/variables(for example to know that + as after a.

a
+
b
-
getLength()
*
10
/
1;

So far I can only get an output as follow,

AddExpr : a+b-c*10/1
=> a
=> b
=> getLength()
=> 10
=> 1

I don't seem to be able to get the signs between each operation. I seem to have something related to the signs in that equation, I had only Star and Mod.

tree::TerminalNode* startTn = mulpExprLp->Star();

So I tried to change the grammar file to get other signs as well. While that gave me the signs in that equation but again... I wasn't ablel to know the position of each sign in the equation.

multiplicativeExpression:
    pointerMemberExpression (
        (Star | Div | Mod | Plus | Minus) pointerMemberExpression
    )*;

I hope I could describe the problem clearly. I basically want to read the each part of an equation and know what is the position of each sign.

Thanks, Alex

1 Answers

It looks like you need a better understanding of the structure of your parse tree.

I would suggest going back to the original grammar (there are many problems with your multiplcativeExpression, mostly around it not building a proper parse tree.

Viewing the graphical version of your parse tree should be quite useful. This page gives a brief intro to setting up a grun alias to use TestRig. It’s usually a good idea to “play around” a bit with grun and various input to gain a better understanding of what ANTLR produces (token streams, parse trees, etc.) for your grammar.

Take a look at the documentation and how to run the TestRig utility with the -gui command line option. This will give you a graphical representation of your parse tree. Your immediate issue is that, since you only have a visitor for additiveExpression, it won’t include the sub tree for the mutiplicativeExpression that will hold the structure for multiplication and division.

Also, since you’re not finding the operations you need to take a closer look at the cpp14parser::AdditiveExpressionContext generated for your additiveExpression. The operator(s) should be available at one of the indices of your children nodes (the rule is written to allow multiple addition/subtraction in a single context, so they’ll probably be available in some list/array structure (sorry, not intimately familiar with what ANTLR generates for C++)

BTW, you may find that, for your purposes, a listener is easier to use than a visitor. With Listeners a ParseTreeWalker takes care of walking the tree and calling back to your code as nodes are encountered. With Visitors, it’s up to you to navigate the parse Tree (they can be useful when you need more flexibility, and a bit easier to handle things if you want a value returned from visiting a node, but I find Listeners much simpler for most use cases)

Related