antlr / antlr3

antlr v3 repository (pulled from p4 with history from //depot/code/antlr/antlr3-main
http://www.antlr.org
244 stars 170 forks source link

ANTLR C target follow set generates reference to undeclared identifier #99

Open sharwell opened 11 years ago

sharwell commented 11 years ago

Copied from Stack Overflow:

ANTLRWorks 1.5rc1 successfully generated the C target code for this grammar with no warnings or errors but the C target code would not compile.

ANTLRWorks 1.5 generated the same bad C target code but the console listed many template errors.

ANTLRWorks 1.4.3 generated valid C target code that compiles without error.

error C2065: 'FOLLOW_set_in_sqlCOMP_OP2185' : undeclared identifier

Rule sqlCOMP_OP is referenced from multiple boolean expression rules

All of the rules that generated references to undefined identifiers were of the form:

fule: (Tokena | Tokenb | Tokenc)? Tokend;

or there were multiple references to a common rule that was of the form:

fule: (Tokena | Tokenb | Tokenc);

In the first case I was able to transform the rule to a logically equivalent form that did not generate a reference to an undefined identifier:

fule: (Tokena Tokend | Tokenb Tokend | Tokenc Tokend | Tokend);

In the second case, no transformation is possible. Instead the only fix is to back-substitute the body of the failing rule into every reference.

sqlCONDITION    :  
    sqlLOGICAL_EXPRESSION
    ;

sqlLOGICAL_EXPRESSION    :  
    sqlLOGICAL_TERM (STOK_OP_OR sqlLOGICAL_TERM)*
    ;

sqlLOGICAL_TERM        :
    sqlLOGICAL_FACTOR (STOK_OP_AND sqlLOGICAL_FACTOR)*
    ;

sqlLOGICAL_FACTOR        :
    (STOK_NOT) => STOK_NOT
    (    sqlUNTYPED_BOOLEAN_PRIMARY
    |    sqlNUMERIC_BOOLEAN_PRIMARY
    |    sqlSTRING_BOOLEAN_PRIMARY
    |    sqlCLOB_BOOLEAN_PRIMARY
    |    sqlDATE_BOOLEAN_PRIMARY
    |    sqlDATETIME_BOOLEAN_PRIMARY
    |    STOK_OPEN_PAREN    
        sqlCONDITION    
        STOK_CLOSE_PAREN
    )
    ;

sqlUNTYPED_BOOLEAN_PRIMARY    :
    (    STOK_EXISTS             sqlSUB_QUERY
    |    STOK_NOT STOK_EXISTS     sqlSUB_QUERY
    |    sqlIS_OR_ISNOT_CLAUSE    
        STOK_IN STOK_ROWSET     STOK_IDENTIFIER
    )
    ;

sqlCOMP_OP    :
    (    STOK_OP_EQ
    |    STOK_OP_NE
    |    STOK_OP_GE
    |    STOK_OP_GT
    |    STOK_OP_LE
    |    STOK_OP_LT
    )
    ;

sqlIS_OR_ISNOT_CLAUSE        :
    (    STOK_IS            STOK_NOT?
    |    STOK_NOT
    )
    ;

sqlNUMERIC_BOOLEAN_PRIMARY    :
    (    sqlNUMERIC_EXPRESSION        
        (    sqlCOMP_OP        
            sqlNUMERIC_EXPRESSION

        |    sqlNUMERIC_BOOLEAN_PREDICATE
        )

    |    sqlNUMERIC_COLUMN_LIST 
        sqlNUMERIC_BOOLEAN_PREDICATE
    )
    ;

sqlNUMERIC_BOOLEAN_PREDICATE:
    (    sqlIS_OR_ISNOT_CLAUSE?
        (    STOK_IN            sqlNUMERIC_SET
        |    STOK_BETWEEN    sqlNUMERIC_EXPRESSION STOK_OP_AND sqlNUMERIC_EXPRESSION
        )
    |    sqlIS_OR_ISNOT_CLAUSE
        STOK_SQL_NULL
    )
    ;    

sqlSTRING_BOOLEAN_PRIMARY    :
    (    sqlSTRING_EXPRESSION
        (    sqlCOMP_OP        
            sqlSTRING_EXPRESSION

        |    sqlSTRING_BOOLEAN_PREDICATE
        )

    |    sqlSTRING_COLUMN_LIST
        sqlSTRING_BOOLEAN_PREDICATE
    )    
    ;

sqlSTRING_BOOLEAN_PREDICATE    :
    (    sqlIS_OR_ISNOT_CLAUSE?
        (    STOK_IN            sqlSTRING_SET
        |    STOK_LIKE        sqlSTRING
        |    STOK_BETWEEN    sqlSTRING_EXPRESSION STOK_OP_AND sqlSTRING_EXPRESSION
        )
    |    sqlIS_OR_ISNOT_CLAUSE
        STOK_SQL_NULL
    )
    ;

sqlCLOB_BOOLEAN_PRIMARY    :
    (    STOK_NOT?
        STOK_CONTAINS
        STOK_OPEN_PAREN
        sqlCLOB_COLUMN_VALUE
        STOK_COMMA
        sqlSTRING
        STOK_CLOSE_PAREN

    |    sqlCLOB_COLUMN_VALUE
        sqlIS_OR_ISNOT_CLAUSE
        STOK_SQL_NULL
    )    
    ;

sqlDATE_BOOLEAN_PRIMARY    :
    (    sqlDATE_EXPRESSION        
        (    sqlCOMP_OP        
            sqlDATE_EXPRESSION

        |    sqlDATE_BOOLEAN_PREDICATE
        )

    |    sqlDATE_COLUMN_LIST
        sqlDATE_BOOLEAN_PREDICATE
    )    
    ;

sqlDATE_BOOLEAN_PREDICATE    :
    (    sqlIS_OR_ISNOT_CLAUSE?
        (    STOK_IN            sqlDATE_SET
        |    STOK_BETWEEN    sqlDATE_EXPRESSION STOK_OP_AND sqlDATE_EXPRESSION
        )
    |    sqlIS_OR_ISNOT_CLAUSE
        STOK_SQL_NULL
    )
    ;

sqlDATETIME_BOOLEAN_PRIMARY    :
    (    sqlDATETIME_EXPRESSION        
        (    sqlCOMP_OP        
            sqlDATETIME_EXPRESSION

        |    sqlDATETIME_BOOLEAN_PREDICATE
        )

    |    sqlDATETIME_COLUMN_LIST
        sqlDATETIME_BOOLEAN_PREDICATE
    )    
    ;

sqlDATETIME_BOOLEAN_PREDICATE    :
    (    sqlIS_OR_ISNOT_CLAUSE?
        (    STOK_IN            sqlDATETIME_SET
        |    STOK_BETWEEN    sqlDATETIME_EXPRESSION STOK_OP_AND sqlDATETIME_EXPRESSION
        )
    |    sqlIS_OR_ISNOT_CLAUSE
        STOK_SQL_NULL
    )
    ;
CBSears commented 9 years ago

I had a similar problem with antlr-3.5.2. The substitution workaround works. I don't know why it works. The grammar is 'weakened' as a side effect but at least it works.