Simplify chained expression in ANTLR listener

Viewed 58

I have an ANTLR listener for C++ where I want to get the name of a member declarator. Currently, I'm using this approach:

def enterMemberDeclarator(self, ctx: CPP14Parser.MemberDeclaratorContext):
    id = ctx.declarator().pointerDeclarator().noPointerDeclarator().noPointerDeclarator().declaratorid().idExpression().unqualifiedId()

which is just a horrible expression. I feel like there should be some way of getting the id immediately without having to go down that rabbit hole. Additionally, some of these expressions might be None so I fear that I would have to make even more effort to get to the result...

The grammar is from here

2 Answers

ANTLR4 supports XPath expressions to find specific nodes (see the documentation). That's somewhat easier to read than your expression, especially when you have to check for null:

ids = XPath.findAll(ctx, "/declarator/pointerDeclarator/noPointerDeclarator/noPointerDeclarator/declaratorid/idExpression/unqualifiedId")

(this is just pseudo code, I don't know python well).

This definitely looks very brittle (specific to a particular example).

You might consider a recursive method that checks the type of the context being passed in and chooses the appropriate attribute.

I'm not a Python programmer, so (in pseudoCode) something like the following:

function getMDName(ctx: <appropriate ANTLR base class) -> String 
  if ctx is MemberDeclarationContext 
    return getMDName(ctx.declarator()

  if ctx is DeclaratorContext 
    if ctx.pointerDeclarator() != null 
      return getMDName(ctx.pointerDeclarator())
    else
      return getMDName(ctx.noPointerDeclarator())
 
  if ctx is NoPointerDeclaratorContext 
    if ctx.declaratorid() != null 
      return getMDName(ctx.declaratorid())
    else if ctx.pointerDeclarator() != null 
      return getMDName(ctx.pointerDeclaration())
    else 
      return getMDNAME(ctx.noPointerDeclarator())
   
  if ctx is PointerDeclarationContext
    return getMDName(ctx.noPointerDeclaration())

  if ctx is declaratorIdContext
    return getMDName(ctx.idExpression()..unqualifiedId()
         
}
Related