/* Parser to convert "C" assignments to lisp using Bison in C++. */
/* Demonstrates bison pure parser with parameters passed to yyparse and to yylex */
/* Compile: bison -d flexexample5.yxx */

%{
#include <iostream>
#include "lex.yy.h"  /* Generated by reflex --header-file */
/* %pure-parser requires us to pass the argument 'params->scanner' from yyparse through to yylex. */
#define YYLEX_PARAM params->scanner
/* Pass argument `struct pass_through *param` with scanner object and other data */
struct pass_through {
  yyscanner_t *scanner;
  int count;
};
void yyerror(struct pass_through *param, const char *msg); /* yyerror accepts `params` */
%}

/* pure-parser adds yylval parameter to yylex() */
%pure-parser
/* Add params->scanner parameter to yylex() using YYLEX_PARAM */
%lex-param { void *YYLEX_PARAM }
/* Add pass-through parameter to yyparse() */
%parse-param { struct pass_through *params }

%union {
    int   num;
    char *str;
}

%token <str> STRING
%token <num> NUMBER

%%

assignments : assignment
            | assignment assignments
            ;
assignment  : STRING '=' NUMBER ';' { std::cout << "(setf " << $1 << " " << $3 << ")\n"; ++params->count; }
            ;

%%

int main()
{
  struct pass_through params;
  yyscanner_t scanner;	// new way in C++ using reflex-generated yyscanner_t
  params.scanner = &scanner;
  params.count = 0;
  yyparse(&params);	// %parse-param, we pass params->scanner on to yylex()
  std::cout << "# assignments = " << params.count << std::endl;
  return 0;
}

void yyerror(struct pass_through *params, const char *msg)
{
  std::cerr << msg << " at " << params->scanner->matcher().lineno() << std::endl;
}
