ANTLR4 AST Creation - How to create an AstVistor
Asked Answered
L

1

0

With the help of this SO question How to create AST with ANTLR4? I was able to create the AST Nodes, but I'm stuck at coding the BuildAstVisitor as depicted in the accepted answer's example.

I have a grammar that starts like this:

mini: (constDecl | varDef | funcDecl | funcDef)* ;

And I can neither assign a label to the block (antlr4 says label X assigned to a block which is not a set), and I have no idea how to visit the next node.

public Expr visitMini(MiniCppParser.MiniContext ctx) {
    return visitConstDecl(ctx.constDecl());
}

I have the following problems with the code above: I don't know how to decide whether it's a constDecl, varDef or any other option and ctx.constDecl() returns a List<ConstDeclContext> whereas I only need one element for the visitConstDecl function.

edit:

More grammar rules:

mini: (constDecl | varDef | funcDecl | funcDef)* ;

//--------------------------------------------------

constDecl:   'const' type ident=ID init ';' ;
init:        '=' ( value=BOOLEAN | sign=('+' | '-')? value=NUMBER ) ;
// ...

//--------------------------------------------------

OP_ADD: '+';
OP_SUB: '-';
OP_MUL: '*';
OP_DIV: '/';
OP_MOD: '%';

BOOLEAN        : 'true' | 'false' ;
NUMBER         : '-'? INT ;
fragment INT   : '0' | [1-9] [0-9]* ;
ID             : [a-zA-Z]+ ;
// ...

I'm still not entirely sure on how to implement the BuildAstVisitor. I now have something along the lines of the following, but it certainly doesn't look right to me...

@Override
public Expr visitMini(MiniCppParser.MiniContext ctx) {
  for (MiniCppParser.ConstDeclContext constDeclCtx : ctx.constDecl()) {
    visit(constDeclCtx);
  }
  return null;
}

@Override
public Expr visitConstDecl(MiniCppParser.ConstDeclContext ctx) {
  visit(ctx.type());
  return visit(ctx.init());
}
Listel answered 16/5, 2017 at 14:16 Comment(2)
You've put a Kleene star * around your expression, which means each item can occur any number of times, or never at all. That's why ctx.constDecl() returns a list, which contains all the constDecl child nodes. You can only assign labels to top-level alternative elements (ie rule: foo # labelA | bar # labelB ;), that's why ANTLR refuses that. I don't really know what's the solution here since I don't know what you're trying to do exactly, but you'll either have to remove that star to get exactly one branch to match, or visit each child node instead of just the first one.Meathead
If I were to visit each child node, what would the visitMini function return then? In your example you don't have the problem of having to visit a list of nodes.Listel
M
1

If you want to get the individual subrules then implement the visitXXX functions for them (visitConstDecl(), visitVarDef() etc.) instead of the visitMini() function. They will only be called if there's really a match for them in the input. Hence you don't need to do any checks for occurences.

Minster answered 17/5, 2017 at 7:9 Comment(2)
If I implement the visitor, don't I have to visit the nodes myself? I thought the reason to do this is so that I can traverse the CST myself, building an AST from it. Hence, I do need to implement the visitMini() function, because it would be the first rule that's entered. Sorry if I got this wrong!Listel
I found my mistake: I was implementing the Visitor rather than extending the XBaseVisitor.Listel

© 2022 - 2024 — McMap. All rights reserved.