Copyright © 1998-2002, Compiler Resources, Inc.
Frequently Asked Questions

Yacc++ and the Language Objects Library

Frequently Asked Questions

  1. Known Problems and Workarounds in Software

  2. Known Problems in Documentation

  3. Software Installation

  4. Keyword Syntax Error

  5. Parser Stack Overflow

  6. Disabling and Enabling Assertions

  7. Reporting Line Numbers for Syntax Errors

  8. Reporting Line Numbers for Semantic Errors

  9. Memory Leaks When Using AST's

  10. Fixing Action Code Conflicts

  11. Changing Token Types

  12. Parser Stack Reference Assertion


  1. List of Known Problems and Workarounds in Software

    Is there a list of known bugs in the table generators and library?

    Yes, please see Software Problems and Workarounds.

  2. List of Known Problems in Documentation

    Is there a documentation corrections page?

    Yes, please see Corrections to Documentation.

    What is the latest version of the documentation?

    The latest version of the documentation is Revision 2.x, January 1999. It contains the Installation Guide, Reference Guide, Tutorial Guide, and Index all in one 3 Ring D binder with the Yacc++ logo on blue.

    Much of the documentation is also available on the CD as .html files. See the doc_html sub-directory of your installation.

    The Revision 1.x documentation is outdated. The old documentation was in separate books for Installation, Reference and Tutorials each with its own index. The old Reference Guide has the Yacc++ logo on pink.

    The cost of a new Revision 2.x documentation set is $100. US dollars + shipping for 8 lbs.

  3. Software Installation

    I am getting a link error on the prog "Hello World!" installation test case. Any ideas?

    You may be using a different C++ compiler or a different revision of the C++ compiler than we used to pre-compile the Language Objects Library. This can result in link errors due to binary incompatibilities.

    Please read Sections 2.4 and 2.5 in the Installation Guide. Re-compile the Language Objects Library with your C++ compiler and try prog again.

  4. Keyword Syntax Error

    I used the KEYWORD declaration in the lexer section of my grammar. When I build my application and give it a valid keyword as input, it gets a syntax error. Why is it not recognizing it?

    Check for problems in your grammar. One common error is that you have not included a valid token definition in your lexer that does a symbol table lookup.

    Please read Section 9.5.7 Keyword Support in the Reference Guide and Tutorial KEYWORDS in the Tutorial Guide.

  5. Parser Stack Overflow

    My application is getting the following assertion at runtime. What does this mean? What should I do?

    Assertion failed: yy_psr_left_area <= yy_psr_left && 
                      yy_psr_left - yy_psr_left_area < yy_psr_left_max

    This means the parser stack overflowed. Please read Tutorial REMOVE in the Tutorial Guide and Overflow FAQ to understand how to avoid parser stack overflows.

    Note: If you do not have assertions enabled, you will not get the assertion message.

  6. Disabling and Enabling Assertions

    How do I know if I have assertions enabled? What do they do?

    If you set the define constant yy_assert_disable_ on your C++ compilation line, runtime assertions are disabled.

    DEFINES= -Dyy_assert_disable_

    To enable assertions, simply delete the explicit define on the compilations.

    DEFINES= 

    Runtime assertions provides periodic internal checks as your application runs. It is advisable to build with assertions enabled during development. If you experience any unexpected behavior, please be sure to recompile with assertions enabled before contacting us. Assertions can sometimes help pinpoint the problem.

  7. Reporting Line Numbers for Syntax Errors

    When there is a syntax error in the input in my application it always reports line number 0. Why am I not getting an accurate line number from calls to yy_err_report()?

    Syntax errors are detected during the first pass over the input, the lexing and parsing pass. yy_err_report() displays the line number from the line number data member in the buffer object.

    Check your lexer in your grammar. The lexer must increment the line number in the buffer object as it lexes newlines. When a syntax error occurs during lexing and parsing on the first pass, the line number in the buffer object will have the accurate value.

    
    WHITE_SPACE  :   (" "             // space
                 |    "\t"            // tab
                 |    "\n"            // newline
                                      {  ++yy_buf_lineno();  }
                      )+
                 ;
    

  8. Reporting Line Numbers for Semantic Errors

    My application uses AST trees. I update the line number in the lexer on the first pass, but when a semantic error is detected on a subsequent pass while walking the AST tree, the last line number is always reported.

    To access the correct line number during a second pass, the line number must be preserved in the leaves of the AST tree at the time of creation. At the time a semantic error is detected, access the appropriate line number from the AST tree. If you are calling yy_err_report() you will want to reset the line number in the buffer object from the AST line number before making the call.

    Note that you may have a need for accurate line numbers for more than semantic error reporting. For example, if you are generating a cross-reference listing of symbols on a second pass.

    Preserving Line Numbers in AST Trees

    One way to preserve the line numbers is to add a line number member to your base AST class and fill in the line number in the base AST class constructor. This will preserve line number information in each leaf of your AST.

    For an example, please see modifications made to Tutorial AST to preserve line numbers in the AST tree.

    If you need to conserve space, you can more selectively save the line number information based on your grammar. Instead of saving the line number in each AST, save it only for certain AST types. Don't add the line number to the base AST class; add it only to specific AST constructs. At the time of a second pass semantic error, tree-walk to locate the AST type containing the line number.

  9. Memory Leaks When Using AST's

    My grammar uses CONSTRUCT declarations for AST object creation. My application has some memory leaks for AST objects. What do I need to do? Why doesn't Yacc++ automatically take care of the deletion of the AST tree?

    Yacc++ can't assume the parser stack entries are pointers. To provide upward compatibility with lex/yacc, the auxiliary data in Yacc++ might be a numeric value. We are considering adding an option that will enable you to tell Yacc++ that your application uses only AST pointers. Opinions?

    In the meantime, follow these instructions to avoid memory leaks in your application when using AST's.

    Lexer and Parser Destructors

    If your application creates AST objects, you must take responsibility for the deletion of the AST tree in the destructors for the lexer and parser object.

    Please see Tutorial AST in the Tutorial Guide for the code for recursive deletion.

    REMOVE Declarations

    If you are using a version of Yacc++ prior to revision 2.3, do not create AST objects for parser non-terminals that are declared REMOVE. This will cause a memory leak.

    At Revision 2.3, Yacc++ now gives a warning for each parser non-terminal that appears in both a REMOVE and a CONSTRUCT declaration. The modifications in the next section will work for non-terminals that are declared either IGNORE and REMOVE, as both use the yy_psr_ign() function in the Language Objects Library.

    IGNORE Declarations

    Avoid creating AST objects for parser non-terminals that are declared IGNORE. This will cause a memory leak.

    If you have an IGNORE parser non-terminal that is usually ignored, but in some specific context is explicitly defined and requires an AST, delete the AST for the ignore cases. You need to make the change to yy_psr_ign() in the Language Objects Library to delete the AST before it is ignored.

    This change is only needed if your grammar has one or more parser non-terminals that are declared both IGNORE and CONSTRUCT.

    This change is specifically for use with applications that have only AST objects as parser stack entries.

    yy_psr_ign() in Revision 2.3

    In Revision 2.3, ignore processing is provided by the yy_psr_ign() member function in yy_psrsk.h.

    Change from:    --yy_psr_stack_rt_ix;
    
    to:             delete (yy_ast_ptr(*yy_psr_stack_rt_ix));
                    --yy_psr_stack_rt_ix;
    

    There are 2 occurrences to change within yy_psr_ign().

    yy_psr_ign() Before Revision 2.3

    In Revision 2.2 and Revision 2.1, yy_psr_ign() is a macro for ignore processing. It is repeated in each of the parser classes by table type. Make the change to yy_psrfa.cpp, yy_psrsm.cpp, and yy_psrrd.cxx.

    Change from:  #define yy_psr_ign() yy_psr_valid_rt_ix(); --yy_psr_rt;
    
    to:           #define yy_psr_ign() yy_psr_valid_rt_ix(); \
                  delete (yy_ast_ptr(*yy_psr_rt));\
                  --yy_psr_rt;
    

    CONSTRUCT Types PREFIX and INFIX

    Delete the unused parser stack entries for PREFIX and INFIX in the AST constructor.

    Syntax Errors

    The change to yy_psr_ign() above, will help clean up after a syntax error. Ignore processing is used while synchronizing to the next valid token.

  10. Fixing Action Code Conflicts

    I'm getting "Error 200 : State xx has an action code conflict". What is this and how do I fix it?

    Please read Tutorial SHIFT in the Tutorial Guide.

    Action code counts as a lookahead just as if it were a symbol. If your grammar puts the parser generator in a position where it has to decide between two actions prematurely, it reports an action code conflict.

        grammar :  RED { cout << "I'm pink first"; }  BLUE   GREEN   ORANGE  PINK   YELLOW
                |  RED { cout << "I'm yellow first"; }  BLUE   GREEN   ORANGE  YELLOW   PINK
                ;

    The parser generator doesn't know whether it needs to execute the first or second action until several symbols later when it sees PINK or YELLOW. To get rid of the conflict, move the action code. The later you can postpone the execution of the action code, the less lookahead is required to determine what action to execute. The following requires no lookahead.

        grammar :  RED  BLUE  GREEN  ORANGE  PINK  { cout << "I'm pink first"; }  YELLOW
                |  RED  BLUE  GREEN  ORANGE  YELLOW  { cout << "I'm yellow first"; }  PINK
                ;

    Decision predicates are a new feature at Yacc++ 2.2. Decision predicates provide the option for you to specify lookahead and backtracking, if it is not possible to move your actions. Do not resort to lookahead and backtracking unless absolutely necessary.

    Also, I continue to get the error even when my input grammar has action code that contains only comments. Why?

    There is a difference between action code that is commented out and action code that contains only comments.

        grammar      :  RED
                        // { .... }
                        BLUE
                     ;
    vs.
        grammar      :  RED
                        { /* .... */ }
                        BLUE
                     ;

    Yacc++ has no way of knowing whether the action code contains comments or executable code. The generator simply copies it to the appropriate part of the class. A commented action like { /* .... */ } could still get an action code conflict. You need to completely comment the action.

  11. Changing Token Types

    I want to lex all identifiers using the same syntactic rule. I want to pass a more specific token type to the parser depending on what type it has in the symbol table, For example, a "float_identifier" or an "integer_identifier" instead of "identifier". What is the method in Yacc++ that I can use in the lexer to change a token's type before it is returned to the parser?

    Use the yy_lex_rdc() lexer method. One possible way of doing this is provided by a dummy token example.

  12. Parser Stack Reference Assertion

    My application gets a parser stack assertion failure at runtime using Revision 2.3. What does this mean? Also, if I disable assertions, my application compiles its input and seems to work correctly.

    Assertion failed: yy_false, file e:\yxx\inc.vc\yy_psrsk.h, line 1379
    
        case(yy_psr_stack_rt_empty_):
            assert(yy_psr_stack_rt_ix == 0);
            assert(yy_false);                 <------- Stopped here
    

    This says there is an illegal reference on the parser stack, in this case an attempted reference to an empty stack. Look at the call stack in your debugger and locate the action code where the problem originates. In this particular case, the developer wrote parser action code that referenced the yy_lex_rdc() interface of the lexer object. (If you do not understand why this is illegal, please see Tutorial LEXCODE in the Tutorial Guide).

    Note: If you do not have assertions enabled, you will not get the assertion message.


Last updated on March 11, 2002. To send email to Compiler Resources, Inc.

Return to Yacc++ Home Page