Swift ANTLR如何决定终端是否应该用空格分隔?
我正在用Swift为Swift编写词汇分析器。我使用了ANTLR的语法,但我面临的问题是,我不明白ANTLR如何决定终端是否应该用空格分隔 语法如下: 假设我们有斯威夫特的演员。它还可以与可选类型(Int?,String?)和非可选类型(Int?,String?)一起操作。这里有一些有效的例子:“as?Int”、“as?Int”、“as?Int”。无效示例:“asInt”(它不是演员阵容)。我已经实现了逻辑,语法规则中的终端可以用0个或更多的WS(空白)符号分隔。但使用此逻辑,“asInt”与强制转换匹配,因为它包含“as”和类型“Int”,并且具有0个或更多WS符号。但它应该是无效的 Swift语法包含以下规则:Swift ANTLR如何决定终端是否应该用空格分隔?,swift,antlr,antlr4,lexical-analysis,language-recognition,Swift,Antlr,Antlr4,Lexical Analysis,Language Recognition,我正在用Swift为Swift编写词汇分析器。我使用了ANTLR的语法,但我面临的问题是,我不明白ANTLR如何决定终端是否应该用空格分隔 语法如下: 假设我们有斯威夫特的演员。它还可以与可选类型(Int?,String?)和非可选类型(Int?,String?)一起操作。这里有一些有效的例子:“as?Int”、“as?Int”、“as?Int”。无效示例:“asInt”(它不是演员阵容)。我已经实现了逻辑,语法规则中的终端可以用0个或更多的WS(空白)符号分隔。但使用此逻辑,“asInt”与强
DOT : '.' ;
LCURLY : '{' ;
LPAREN : '(' ;
LBRACK : '[' ;
RCURLY : '}' ;
RPAREN : ')' ;
RBRACK : ']' ;
COMMA : ',' ;
COLON : ':' ;
SEMI : ';' ;
LT : '<' ;
GT : '>' ;
UNDERSCORE : '_' ;
BANG : '!' ;
QUESTION: '?' ;
AT : '@' ;
AND : '&' ;
SUB : '-' ;
EQUAL : '=' ;
OR : '|' ;
DIV : '/' ;
ADD : '+' ;
MUL : '*' ;
MOD : '%' ;
CARET : '^' ;
TILDE : '~' ;
WS : [ \n\r\t\u000B\u000C\u0000]+
a : WS? 'str1' WS? 'str2' WS? '+' WS? 'str3' WS?
我使用它们时,就好像它们是这些规则一样:
DOT : '.' ;
LCURLY : '{' ;
LPAREN : '(' ;
LBRACK : '[' ;
RCURLY : '}' ;
RPAREN : ')' ;
RBRACK : ']' ;
COMMA : ',' ;
COLON : ':' ;
SEMI : ';' ;
LT : '<' ;
GT : '>' ;
UNDERSCORE : '_' ;
BANG : '!' ;
QUESTION: '?' ;
AT : '@' ;
AND : '&' ;
SUB : '-' ;
EQUAL : '=' ;
OR : '|' ;
DIV : '/' ;
ADD : '+' ;
MUL : '*' ;
MOD : '%' ;
CARET : '^' ;
TILDE : '~' ;
WS : [ \n\r\t\u000B\u000C\u0000]+
a : WS? 'str1' WS? 'str2' WS? '+' WS? 'str3' WS?
我想他们应该是这样的(我不知道,这就是问题所在):
(注意,WS在“str1”和“str2”之间不是可选的)
所以有两个问题:
谢谢。以下是您的Swift语法中的ANTLR
WS
规则:
WS : [ \n\r\t\u000B\u000C\u0000]+ -> channel(HIDDEN) ;
->channel(HIDDEN)
指令告诉lexer将这些令牌放在一个单独的通道上,因此解析器根本看不到它们。你不应该把你的语法和WS
规则混在一起-它会变得不可读
ANTLR分两步工作:您有lexer和解析器。lexer生成标记,解析器试图从这些标记和语法中找出一个具体的语法树
ANTLR中的lexer的工作原理如下:
- 只要符合任何lexer规则,就使用字符
- 如果有多条规则与您使用的文本相匹配,请使用语法中出现的第一条规则
- 语法中的文字字符串(如
)被转换为隐式lexer规则(相当于'as'
,但名称仅为标记_as:'as';
)。在lexer规则列表中,这些规则排在第一位'as'
词法转换为?Int
(末尾有空格)时的后果:
。。。可能匹配a
和标识符
'as'
。。。可能匹配作为
和标识符
'as'
与任何lexer规则都不匹配as?
消费为,这将成为令牌。现在,您必须决定哪一种是令牌类型。标识符
和'as'
规则都匹配'as'
是一个隐式的词法规则,被认为在语法中首先出现,因此优先。lexer发出一个类型为'as'
的带有文本as
的令牌
下一个标记
?
。。。可能与问题
规则匹配
?I
与任何规则都不匹配
因此,您从输入中消费?
,并发出一个类型为QUESTION
的标记,其中包含文本?
下一个标记
I
。。。可能匹配标识符
中的。。。可能匹配标识符
Int
。。。可能匹配标识符
Int
(后跟空格)与任何内容都不匹配
因此,您从输入中使用Int
,并发出一个类型为Identifier
的标记,其中包含文本Int
下一个标记
- 您在那里有一个空格,它与
WS
规则匹配
您使用该空间,并在隐藏的频道上发出WS
标记。解析器不会看到这一点
例2
现在让我们看看asInt
是如何标记的
a
。。。可能匹配标识符
和'as'
作为
。。。可能匹配标识符
和'as'
asI
。。。可能匹配标识符
asIn
。。。可能匹配标识符
asInt
。。。可能匹配标识符
asInt
后跟空格与任何lexer规则都不匹配
因此,您从输入流中使用asInt
,并发出一个带有文本asInt
的Identifier
标记
解析器
解析器阶段只对它获得的令牌类型感兴趣。它不关心它们包含什么文本。默认通道之外的令牌将被忽略,这意味着以下输入:
as?Int
-令牌:'as'
问题
标识符
as?Int
-令牌:'as'
问题
WS
标识符
as?Int
-令牌:'as'
WS
问题
WS
标识符
所有这些都将导致解析器看到以下令牌类型:'as'
问题
标识符
,因为WS
在单独的频道上。哇,谢谢。我认为lexer和parser规则在创建标记树时是同时工作的。不,它们是解析的不同阶段-这使得这个概念非常容易掌握,同时可以很好地与大多数语言配合使用。但是解析语言需要来自lexer中解析器的信息,这使得解析语言变得很困难。非常感谢!你帮我写了我的工具。以下是输出:我很高兴。很好,我很高兴能帮上忙:)