在不需要的地方识别词法分析规则



尝试使用 ANTLR 4 为 Oracle DB 中的某些 Select 语句创建简单的语法。并面临一个小问题。我有以下语法:

语法和词法学

column
: (tableAlias '.')? IDENT ((AS)? colAlias)?
| expression ((AS)? colAlias)?
| caseWhenClause ((AS)? colAlias)?
| rankAggregate ((AS)? colAlias)?
| rankAnalytic colAlias
;
colAlias
: '"' IDENT '"'
| IDENT
;
rankAnalytic
: RANK '(' ')' OVER '(' queryPartitionClause orderByClause ')'
;
RANK: R A N K;
fragment A:('a'|'A');
fragment N:('n'|'N');
fragment R:('r'|'R');
fragment K:('k'|'K');

最重要的部分是声明分析部分。我声明在 Rank 语句之后应该是 colAlias,但如果这个 colAlias 被称为"rank"(不带引号),它被识别为 RANK 词法分析器规则,而不是 colAlias。

因此,例如,如果我有以下文本:

 SELECT fulfillment_bundle_id, SKU, SKU_ACTIVE, PARENT_SKU, SKU_NAME, LAST_MODIFIED_DATE,
 RANK() over (PARTITION BY fulfillment_bundle_id, SKU, PARENT_SKU 
 order by ACTIVE DESC NULLS LAST,SKU_NAME) rank

"rank"别名将带有下划线并标记为错误,并显示以下错误:
不匹配的输入"rank"期望 {'"', IDENT}
但关键是我不希望它被识别为 RANK 词法分析器单词,而只是将其作为 Column 的别名进行排名。
开放您的建议:)

RANK规则显然出现在IDENT规则的上方,因此词法分析器永远不会将字符串"rank"作为IDENT标记发出。

一个简单的解决方法是更改colAlias规则:

colAlias
    : '"' ( IDENT | RANK ) '"'
    | ( IDENT | RANK ) 
    ;

OP补充说:

好的,但以防万一我不仅将 RANK 作为词法分析器规则,而且整个列表 (>100)这样的关键词...我应该怎么做?

如果colAlias可以是字面上的任何东西,那么让它:

colAlias
    : '"' .+? '"'    // must quote if multiple
    | .              // one token
    ;

如果该定义会产生歧义,则需要一个谓词来限定匹配:

colAlias
    : '"' m+=.+? '"' { check($m) }?  // multiple
    | o=.            { check($o) }?  // one 
    ;

从功能上讲,谓词只是子规则中的另一个元素。

相关内容

  • 没有找到相关文章

最新更新