Search code examples
c++antlr4

In antrl4, how to call listeners in C++? And do they have to be declared on the heap?


The following code generates no output, so presumably I am doing something wrong with the listener. The code that is ifdefed out displays all the tokens, so they are definitely there.

First, here is the input file:

struct vec3d {
  x : f32,
  y : f32,
  z : f32
}

Here is the grammar:

grammar xbf;

prog: ( struct_def )* ;

type:  type_uint | type_float | type_string ;

type_uint: U8 | U16 | U32 | U64 ;
type_float: F32 | F64 ;
type_string: '"' STRLIT? '"' ;

struct_def: 'struct' '{' ( IDENT ':' type ','  )* '}' ;

IDENT: [a-zA-Zα-ωΑ-ΩА-Яа-я][a-zA-Z0-9_α-ωΑ-ΩА-Яа-я]* ;

U8: 'u8' ;
U16: 'u16' ;
U32: 'u32' ;
U64: 'u64' ;

F32: 'f32' ;
F64: 'f64' ;

STRLIT: '"' (~[\r\n"] | '\\"')* '"' ;
WS: [ \t\n]+ -> skip;

Here is the output showing the tokens, so the parser does work:

[@0,0:5='struct',<2>,1:0]
[@1,7:11='vec3d',<7>,1:7]
[@2,13:13='{',<3>,1:13]
[@3,17:17='x',<7>,2:2]
[@4,19:19=':',<4>,2:4]
[@5,21:23='f32',<7>,2:6]
[@6,24:24=',',<5>,2:9]
[@7,28:28='y',<7>,3:2]
[@8,30:30=':',<4>,3:4]
[@9,32:34='f32',<7>,3:6]
[@10,35:35=',',<5>,3:9]
[@11,39:39='z',<7>,4:2]
[@12,41:41=':',<4>,4:4]
[@13,43:45='f32',<7>,4:6]
[@14,47:47='}',<6>,5:0]
[@15,50:49='<EOF>',<-1>,7:0]

Here is the main. I am probably missing a call but I did not see one.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

#include "xbfBaseListener.h"
#include "xbfParser.h"
#include "xbfLexer.h"
using namespace std;
using namespace antlr4;

class XBFListener : public xbfBaseListener {
 void enterProg(xbfParser::ProgContext* ctx) override {
     cout << ctx << '\n';
 }

 void enterStruct_def(xbfParser::Struct_defContext* ctx) override {
     cout << ctx << '\n';
 }
};

int main(int argc, char* argv[]) {
    const string filename = argc > 2 ? argv[1] : "test.xbf";
    ifstream file(filename.c_str());
    
    ANTLRInputStream input(file);
    xbfLexer lexer(&input);
    CommonTokenStream tokens(&lexer);
        tokens.fill();
    #if 0
        for (auto token : tokens.getTokens()) {
            std::cout << token->toString() << std::endl;
        }
    #endif
        XBFListener* L = new XBFListener();
        xbfParser parser(&tokens);
        parser.addParseListener(L);
    return 0;
}

Also, the example that I saw had the instantiations using new, but can the objects be allocated on the stack, or as part of an object? Or does the C++ runtime of antlr4 call delete on these pointers?


Solution

  • There's no output because you don't produce any. What you printed above are the tokens from the token stream, which is not the parser output. You have to run the parser to do anything useful. As you did not post your grammar here I can only guess what your start rule is, so add something like:

        parser.start();
    

    after your parser.addParseListener(L); line.