help-bison
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

About %destructor is c++ mode


From: Min Wang
Subject: About %destructor is c++ mode
Date: Wed, 17 Aug 2016 19:20:34 -0400

HI

I guess I have some confusions/misunderstanding on  how to use %destructor
 in bision 3.0.4

(1)
https://www.gnu.org/software/bison/manual/html_node/Calc_002b_002b-Parser.html#Calc_002b_002b-Parser
said:

No %destructor is needed to enable memory deallocation during error
recovery; the memory, for strings for instance, will be reclaimed by the
regular destructor.


so if I have something like that ( pointer) in as token type:


%type <PROG*> PROG

%type <ListExp*> ListExp

My thinking about using PROG* instead of PROG is because I do not want to
copy constructor a big PROG, is it correct?

In this case of pointer, do I need to have a %destructor?

%destructor { delete $$; } PROG
%destructor {  delete $$; } ListExp


(2) when %destructor  is called?

Assuming I need those %destructor, it seems that %destructor was called
even for a every  successful parse. I thought it should only called during
During error recovery.



e.g:
some C++ code:

using Exp_PTR = std::unique_ptr<Exp>;



class Elor : public Exp

{

public:

  Exp_PTR exp_1;

  Exp_PTR exp_2;


  // use unique_ptr to take the ownership of the raw pointer from bison
  Elor(Exp *p1, Exp *p2): exp_1( p1 ), exp_2 ( p2 ) {}

  ~Elor() {}
}

// real one here

using ListExp_PTR = std::unique_ptr<ListExp>;



class Json_Filter : public PROG

{

public:

  ListExp_PTR listexp_;

  Json_Filter(ListExp *p1) : listexp_( p1 ) {}

  ~Json_Filter() {}
}
class ListExp : public Visitable, public std::vector<Exp_PTR>

{


};


bison.yy file:

%define api.value.type variant
%define api.token.constructor
...
%type <PROG*> PROG

%type <ListExp*> ListExp

%type <Exp*> Exp

%type <Exp*> Exp1

...

%destructor { std::cout << " I am PROG \n " << $$; /*delete $$;*/ } PROG

%destructor { std::cout << " I am listexp \n" << $$; /* delete $$; */ }
ListExp


%start PROG;



PROG : ListExp                    {
                                              std::reverse( $1->begin(),
$1->end() );
                                              // store the result to
filter_driver.prog
                                              driver.store_ast( new
Json_Filter($1) );
                                            }

;

ListExp : Exp                        {  $$ = new ListExp();
                                              $$->push_back(
std::move(Exp_PTR($1)) );
                                            }

  | Exp _SYMB_SEMICOLON ListExp             { $3->push_back(
std::move(Exp_PTR($1)) );
                                              $$ = $3 ;

                                            }

  | /* empty */                             {  $$ = new ListExp();
 }
;

Exp : Exp _SYMB_OR Exp1                     {  $$ = new Elor($1, $3)  ;
}
  | Exp1                                    {  $$ = $1;           }

;

 ...



so if I comment out the destrcutor: /* delete $$ */, I can ran the parser
OK, and it can been seen that even for a successful paring, theose
%destrcutor are called.

If I uncomment out the delete $$, I will get the segment fault, why?  I
thought it should only called during During error recovery not for
the successful parsing.



Thanks



min


reply via email to

[Prev in Thread] Current Thread [Next in Thread]