我在Swift for Swift中编写词法分析器。我使用了ANTLR的语法,但是我遇到了一些问题,我不明白ANTLR是如何判断终端是否应该用空格分隔的。
这里是语法:https://github.com/antlr/grammars-v4/blob/master/swift/Swift.g4
假设我们在Swift中进行了转换。它还可以使用可选类型(Int?,String?)和非可选类型(Int,String)操作。以下是有效的例子:" as? Int"," as Int"," as?Int"。无效的例子:" asInt" (它不是演员)。当语法规则中的终端可以用0或更多WS(空白)符号分隔时,我实现了逻辑。但是有了这个逻辑" asInt"正在匹配一个演员,因为它包含" as"和类型" Int"并且有0个或更多WS符号。但它应该是无效的。
Swift语法包含以下规则:
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 : '~' ;
似乎所有这些终端都可以与其他终端分开,其中有0个WS符号,而其他终端不在其中(例如&#34; as&#34; + Identifier)。
我是对的吗?如果我没错,问题就解决了。但可能有更复杂的逻辑。
现在,如果我有规则
WS : [ \n\r\t\u000B\u000C\u0000]+
a : 'str1' b
b : 'str2' c
c : '+' d
d : 'str3'
我使用它们好像是这些规则:
WS : [ \n\r\t\u000B\u000C\u0000]+
a : WS? 'str1' WS? 'str2' WS? '+' WS? 'str3' WS?
我认为他们应该是这样的(我不知道,这就是问题):
WS : [ \n\r\t\u000B\u000C\u0000]+
a: 'str1' WS 'str2' WS? '+' WS? 'str3'
(注意WS在&#39; str1&#39;和&#39; str2&#39;之间不是可选的)
所以有两个问题:
感谢。
答案 0 :(得分:2)
这是Swift语法中的ANTLR WS
规则:
WS : [ \n\r\t\u000B\u000C\u0000]+ -> channel(HIDDEN) ;
-> channel(HIDDEN)
指令告诉词法分析器将这些标记放在一个单独的通道上,因此解析器根本不会看到它们。你不应该用WS
规则乱丢你的语法 - 它会变得不可读。
ANTLR有两个步骤:你有词法分析器和解析器。词法分析器生成标记,解析器试图从这些标记和语法中找出具体的语法树。
ANTLR中的词法分析器的工作原理如下:
'as'
)被转换为隐式词法分析器规则(相当于TOKEN_AS: 'as';
,但名称只是'as'
)。这些最终在词法分析器规则列表中 first 。让我们看看lexing as?Int
(最后有一个空格)时的后果:
a
...可能与Identifier
和'as'
as
...可能与Identifier
和'as'
as?
与任何词法分析器规则不匹配因此,您使用as
,这将成为一个标记。现在你必须决定哪个是令牌类型。 Identifier
和'as'
规则都匹配。 'as'
是一个隐式词法分析器规则,被认为在语法中首先出现,因此它优先。词法分析器会使用as
类型的文本'as'
发出令牌。
下一个标记。
?
...可能与QUESTION
规则相匹配?I
与任何规则都不匹配因此,您从输入中使用?
并发出带有文本QUESTION
的{{1}}类型的标记。
下一个标记。
?
...可能与I
Identifier
...可能与In
Identifier
...可能与Int
Identifier
(后跟空格)与任何内容都不匹配因此,您从输入中使用Int
并发出带有文本Int
的{{1}}类型的标记。
下一个标记。
Identifier
规则匹配。您占用该空间,并在Int
频道上发出WS
令牌。解析器不会看到这个。
现在让我们看看WS
是如何被标记化的。
HIDDEN
...可能与asInt
和a
Identifier
...可能与'as'
和as
Identifier
...可能与'as'
asI
...可能与Identifier
asIn
...可能与Identifier
asInt
后跟空格与任何词法规则都不匹配。因此,您从输入流中使用Identifier
,并发出带有文字asInt
的{{1}}令牌。
解析器阶段仅对其获得的令牌类型感兴趣。它不关心它们包含哪些文本。忽略默认通道外的标记,这意味着以下输入:
asInt
- 代币:Identifier
asInt
as?Int
'as'
- 代币:QUESTION
Identifier
as? Int
'as'
QUESTION
- 代币:WS
Identifier
as ? Int
'as'
WS
所有这些都会导致解析器看到以下令牌类型:QUESTION
WS
Identifier
,因为'as'
位于单独的频道上。