regresion: Antlr C target follow set generates reference to undeclared identifier

馋奶兔 提交于 2019-12-07 20:18:20

问题


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
    )
    ;

回答1:


I had the same problem with rules of this type:

prio14Operator: '=' | '+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^=' | 'is';
prio14Expression: prio13Expression (prio14Operator prio13Expression)*;  

Rewriting the rules to this format fixed the issue:

prio14Expression: prio13Expression (('=' | '+=' | '-=' | '*=' | '/=' | '%=' | '<<=' | '>>=' | '&=' | '|=' | '^=' | 'is') prio13Expression)*;    


来源:https://stackoverflow.com/questions/14892689/regresion-antlr-c-target-follow-set-generates-reference-to-undeclared-identifie

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!