如何使用ANTLR检查有效的变量名?

如何使用ANTLR检查有效的变量名?,antlr,antlr4,Antlr,Antlr4,我们都知道变量名不能以数字开头。(例如,foo1有效,1foo无效) 我试图编写一个语法文件,只允许有效的变量名,并且它们后面必须跟一个冒号。(这是一个大得多的语法的一部分——我只是停留在这一部分) 看起来应该很简单。我定义了一个规则id,它只接受一个字母值作为其第一个字符,后跟任意数量的字母数字字符。然而,对我来说,看似简单的任务却失败了。有人能解释为什么吗 这是我的语法: grammar validName; var_declaration :VAR id COLON; VAR: 'var

我们都知道变量名不能以数字开头。(例如,foo1有效,1foo无效)

我试图编写一个语法文件,只允许有效的变量名,并且它们后面必须跟一个冒号。(这是一个大得多的语法的一部分——我只是停留在这一部分)

看起来应该很简单。我定义了一个规则id,它只接受一个字母值作为其第一个字符,后跟任意数量的字母数字字符。然而,对我来说,看似简单的任务却失败了。有人能解释为什么吗

这是我的语法:

grammar validName;

var_declaration :VAR id COLON;
VAR: 'var';
COLON: ':';
DIGIT: [0-9];
ALPHA: [a-zA-Z_];
ALPHANUM: ALPHA | DIGIT;

id: ALPHA ALPHANUM*;

WS: [ \n\t\r]+ -> skip;
以下是我的测试输入:

var myId : 
下面是错误:

line 1:5 mismatched input 'y' expecting ':'

为什么ALPHANUM*与任何东西都不匹配???

在Antlr中,lexer将在解析器运行之前运行到完成。解析器规则对lexer的行为没有影响

因此,给定文本
myId
,lexer将发出四个
ALPHA
标记。这是因为
ALPHA
规则首先出现,并且
ALPHA
ALPHANUM
规则的匹配长度相同。实际上,
ALPHANUM
永远不会匹配,因为前面列出了
DIGIT

尝试:


现在的答案可能对你有帮助。它建议您接受SINGLE | MULTI,其中SINGLE只是ALPHA,MULTI是ALPHA-ALPHANUM+Close,但不完全是。他的问题似乎是关于贪婪操作符是如何工作的,他的问题略有不同。我需要第一个字符是ALPHA,后跟任何ALPHANUM。里面没有“或”。我不想在ALPHA和ALPHANUM之间进行选择。它是ALPHA-ALPHANUM*,这是唯一的选择。我不使用+运算符,我需要使用*。不过,我会关注那里的链接。至少你给了我一个开始的地方。这奏效了!现在你必须向我解释为什么ID:ALPHA(ALPHA | DIGIT)*与ALPHANUM:ALPHA | DIGIT不同;ID:ALPHA-ALPHANUM*;你们说ALPHANUM永远不会匹配是什么意思,因为数字列在前面?ALPHANUM可以是数字或Alpha。“|”不是指“或”吗?如果lexer一开始没有找到匹配项,那么它接下来会查看管道的另一侧。
ALPHA
DIGIT
都出现在
ALPHANUM
之前,因此lexer只会发出
ALPHA
DIGIT
标记。虽然您对alt运算符的理解是正确的,但是lexer将始终选择具有相同匹配长度的第一个匹配规则(所有三个规则的匹配长度均为1)。哎哟!很好的解释。似乎显示lexer输出的调试输出将帮助人们理解他们的语法是否正确。
var_declaration :VAR ID COLON;

VAR: 'var';
ID: ALPHA ( ALPHA | DIGIT )*;

COLON: ':';
DIGIT: [0-9];
ALPHA: [a-zA-Z_];
WS: [ \n\t\r]+ -> skip;