Copyright © 1998-99, Compiler Resources, Inc.
New Features in Revision 2.3

Yacc++ and the Language Objects Library

New Features in Revision 2.3

Parser Memento Object

The Current Model

Yacc++ parser objects have always been fully re-entrant and thread-safe. You can have multiple parser objects of the same -or- of different classes within an application. Multiple parser objects can be active concurrently within a process and paused and resumed.

New at Revision 2.3

The addition of parser memento objects extends the Yacc++ model further. Now you can save and restore the state of your parser object to and from a file. This enables use across processes -or- across different invocations of the same application.

Sometimes it may be useful to capture the state of a parser and restore that state at a later point in time. The object-oriented pattern for doing this is called the memento pattern. A separate object, the parser memento object, is created when the parser state is to be stored. The parser memento object can then be used to restore the state of the parser object. For more information on the memento pattern:

Design Patterns -- Elements of Reusable Software Gamma, Helm, Johnson, Vlissides, Memento Pattern, page 283

This feature is for use in applications where tokens are fed directly to the parser. A small extract from the tutorial on the memento feature is shown below:

Writing Your Grammar

To use mementos, add the MEMENTO parser class construct to your grammar. This instructs yxx to generate a parser memento class in addition to the parser class. Yacc++ will also write out memento specific member functions to the parser class. See yy_mypsr.h and yy_mypsr.cxx to view the code Yacc++ generates as a result of the inclusion of the MEMENTO clause.

    class mementob;

    . . .

    //  Instruct yxx to generate a parser memento class

    parser :: memento ; 

    . . .

Saving a Parser Memento to a File

Yacc++ parser memento objects provide binary access functions that allow their contents to be saved and restored. Example mementob uses the binary access functions to save the contents of a parser memento object to a file and to restore it from the file.

This example is the same as mementoa except it saves and restores the parser memento object to a file. The code is located in yy_mainb.cxx. The italicized code below is specific to reading and writing the file. Note the use of yy_sizeof_data() and yy_data_ptr(). These are member functions in the base MEMENTO class in the Language Objects Library. See yy_memen.h.

    //  When it is time, save the parser to a file using the memento

    yy_saved_parser = new yy_psr_mementob_memento_obj(*yy_parser);
    sizeof_data = yy_saved_parser->yy_sizeof_data();
    file = fopen("parser.mem", "wb");
    fwrite(&sizeof_data, sizeof(sizeof_data), 1, file);
    fwrite(yy_saved_parser->yy_data_ptr(), sizeof_data, 1, file);
    fclose(file); 
    delete yy_saved_parser;

    //  Later, restore the parser from the memento file using the memento

    yy_saved_parser = new yy_psr_mementob_memento_obj;
    file = fopen("parser.mem", "rb");
    fread(&sizeof_data, sizeof(sizeof_data), 1, file);
    yy_saved_parser->yy_sizeof_data() = sizeof_data;
    fread(yy_saved_parser->yy_data_ptr(), sizeof_data, 1, file);
    fclose(file);

    yy_parser = new yy_psr_dflt_obj(*yy_saved_parser);

Union Redesign

There were several limitations with UNION in Revision 2.x that are now fixed in Revision 2.3. The following are now working as a result of the overhaul:

The reference object that encapsulates the UNION as well as how parser objects interact with it were changed to provide the support.

On-line Documentation

We have had many requests for on-line documentation. It is a big job that is in progress. At Revision 2.3, the following is available in *.html format:

New Warnings

The following new warnings were added to Revision 2.3:

Upgrade Gotchas / Odds and Ends

  1. The internal data members in the parser object have changed at Revision 2.3 and may result in compilation problems in your application when upgrading.

    If you have an existing grammar with action code that used the public parser member functions, you do not need to make changes.

    If you have an existing grammar with action code that accessed the internal data members directly, the code may no longer compile. You need to change the code to use the public interface defined in the base parser object. See yy_psr.h.

         INTERNAL DATA MEMBER (Previously)     PUBLIC MEMBER FUNCTION      
    
         yy_psr_err_value                      yy_psr_error()              
    
         yy_psr_done                           yy_psr_is_done()            
    

  2. If you have an explicit --yy_psr_left; in action code (to manually clean up the stack) it will no longer compile.

    Revision 2.3 has member function interfaces to provide access to the internal parser stack. Change your grammar to:

       yy_psr_left_pop();  // pops last entry : equivalent to --yy_psr_left;
       yy_psr_left_pop(2); // pops last 2 entries
    
           // removes number of entries starting at index
           // thus, if number = 3:  removes index, index+1, index+2
    
       yy_psr_last_remove(index, number); 
    

    See yy_psr.h and yy_psrsk.h.

  3. Two bug fixes for parser syntactic predicates.

Last updated on January 25, 1999. To send email to Compiler Resources, Inc.

Return to Yacc++ Home Page