%{

#include <iostream>

struct ZeroDefault {
    int val;
    ZeroDefault(): val(0) {}
    ZeroDefault(int v): val(v) {}
    ZeroDefault &operator=(int v) { val = v; return *this; }
};

#include "vb.tab.h"

int yylex(yy::parser::semantic_type *val, void *);

%}


%defines
%locations
%token-table
%error-verbose

%skeleton "lalr1.cc"

%define api.value.type variant

%start	explodes

%token<int> 'a' 'b' 'e'

%type<ZeroDefault> explodes recursion_1 reduction_by_2

%printer { yyoutput << "<|" << $$.val << "|>"; } explodes recursion_1 reduction_by_2

%%

explodes: recursion_1 { std::cout << "Top " << $1.val << std::endl; }
    ;

recursion_1: reduction_by_2 // should have default $$ = $1
        // { $$ = $1; }
    | recursion_1 reduction_by_2 { $$ = $2; }
    ;

reduction_by_2: optional something_not_optional { $$ = ZeroDefault(7); std::cout << "Set to " << $$.val << std::endl; }
    ;

optional:
    | 'a'
    | 'b'
    ;

something_not_optional: 'e'
    ;

%%

int yylex(yy::parser::semantic_type *val, void *) {
    static const int rv[3] = { 'a', 'e', 0 };
    static int index = 0;
    val->build(rv[index]);
    std::cout << "yylex called " << index << " times" << std::endl;
    return rv[index++];
}

void yy::parser::error(yy::location const&, std::string const&) {}

int main(int argc, const char *argv[]) {
    yy::parser parser;
    parser.parse();
    return 0;
}


