Lexer 规则在不需要的地方被识别
Lexer rule is recognized where it wasn't needed
尝试使用 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');
最重要的部分在 COLUMN 声明 rankAnalytic 部分。我声明在 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 添加:
Ok but in case I have not only RANK as a lexer rule but the whole list
(>100) of such key words... What am I supposed to do?
如果 colAlias
可以是任何字面意思,那就让它:
colAlias
: '"' .+? '"' // must quote if multiple
| . // one token
;
如果该定义会引起歧义,则需要一个谓词来限定匹配:
colAlias
: '"' m+=.+? '"' { check($m) }? // multiple
| o=. { check($o) }? // one
;
从功能上讲,谓词只是子规则中的另一个元素。
尝试使用 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');
最重要的部分在 COLUMN 声明 rankAnalytic 部分。我声明在 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 添加:
Ok but in case I have not only RANK as a lexer rule but the whole list (>100) of such key words... What am I supposed to do?
如果 colAlias
可以是任何字面意思,那就让它:
colAlias
: '"' .+? '"' // must quote if multiple
| . // one token
;
如果该定义会引起歧义,则需要一个谓词来限定匹配:
colAlias
: '"' m+=.+? '"' { check($m) }? // multiple
| o=. { check($o) }? // one
;
从功能上讲,谓词只是子规则中的另一个元素。