我在为Swift写词法分析器。我使用了ANTLR的语法,但我面临的问题是,我不明白ANTLR是如何决定终端是否应该用空白分隔的。
以下是语法:https://github.com/antlr/grammars-v4/blob/master/swift/swift.g4
假设我们选了斯威夫特。它还可以使用可选类型(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符号与其他的分开,而其他的终端则不然(例如“as”+标识符)。
我说的对吗?如果我是对的,问题就解决了。但可能还有更复杂的逻辑。
如果我有规矩
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在“str1”和“str2”之间不是可选的)
所以有两个问题:
多谢了。
以下是Swift语法中的ANTLRws
规则:
WS : [ \n\r\t\u000B\u000C\u0000]+ -> channel(HIDDEN) ;
->channel(HIDDEN)
指令告诉lexer将这些令牌放在一个单独的通道上,因此解析器根本看不到它们。您不应该在语法中乱放ws
规则--它会变得不可读。
ANTLR的工作分为两个步骤:您有了lexer和解析器。lexer生成标记,解析器试图从这些标记和语法中找出一个具体的语法树。
ANTLR中的lexer是这样工作的:
'as'
)被转换为隐式lexer规则(相当于token_as:'as';
,只是名称为'as'
)。这些将首先出现在lexer规则列表中。让我们看看当将写成?int
(结尾有空格)时这些后果:
A
...可能匹配标识符
和“as”
作为
...可能匹配标识符
和“as”
作为?
与任何lexer规则都不匹配因此,您将消费为
,这将成为一个令牌。现在您必须决定哪一种将是令牌类型。标识符
和“as”
规则都匹配。'as'
是一个隐式的lexer规则,被认为是语法中首先出现的,因此优先。lexer发出带有as
类型的文本as
的令牌。
下一个令牌。
?
...可能匹配问题
规则?I
与任何规则都不匹配因此,您从输入中使用?
并发出带有文本?
的问题
类型的令牌。
下一个令牌。
i
...可能匹配标识符
在
中...可能匹配标识符
int
...可能匹配标识符
int
(后跟空格)与任何内容不匹配因此,您从输入中使用int
并发出带有文本int
的identifier
类型的令牌。
下一个令牌。
ws
规则相匹配。您消耗了该空间,并在hidden
通道上发出ws
令牌。解析器不会看到这一点。
现在让我们看看asint
是如何标记化的。
A
...可能匹配标识符
和“as”
作为
...可能匹配标识符
和“as”
asi
...可能匹配标识符
asin
...可能匹配标识符
asint
...可能匹配标识符
asint
后跟空格与任何lexer规则不匹配。因此,您从输入流中使用asint
,并发出带有文本asint
的identifier
令牌。
解析器阶段只对它获得的令牌类型感兴趣。它并不关心它们包含什么文本。默认通道外的令牌将被忽略,这意味着以下输入:
as?int
-令牌:“as”
问题
标识符
作为?int
-令牌:“as”
问题
ws
标识符
作为?int
-令牌:“as”
ws
问题
ws
标识符
都将导致解析器看到以下令牌类型:'as'
question
identifier
,因为ws
在单独的通道上。
问题内容: 我有的: 我有jQuery AJAX函数,可在查询数据库后返回HTML。根据查询结果,该函数将返回HTML代码,或者根据需要返回任何内容(即空白)。 我需要的: 我需要有条件地检查数据何时为空。 我的代码: 我的问题: 我尝试了多种条件,但都无法正确检查数据。根据我的发现,警告消息为空并不表示数据是 空的 不存在的 等于零 长度为零 空值 未定义 如果这些都不是,那么我该如何有条件地检
问题内容: 使用Java 8和lambda,可以很容易地将集合作为流进行迭代,也很容易使用并行流。docs中的两个示例,第二个示例使用parallelStream: 只要我不关心顺序,使用并行会始终有益吗?有人会认为,更快地将工作划分到更多的内核上。 还有其他考虑事项吗?什么时候应该使用并行流,什么时候应该使用非并行? (问这个问题可以引发关于如何以及何时使用并行流的讨论,不是因为我认为始终使用并
问题内容: 这是我得到的: 但是该代码表示无法为该方法找到Symbol。我记得Java拥有这样的比较器…有什么建议吗? 问题答案: 是原始数据类型,因此可以与进行比较。 另外,通过使用双引号可以创建常量(),而使用单引号可以是常量()。
null
问题内容: 为什么或者为什么不? 问题答案: 对于性能而言,尤其是在较大范围内进行迭代时,通常会更好。但是,在某些情况下,你可能更喜欢: 在Python 3,range()做什么用做的,不存在。如果要编写可在Python 2和Python 3上运行的代码,则不能使用。 在某些情况下实际上可以更快-例如。如果多次重复相同的序列。 xrange()每次都必须重新构造整数对象,但是range()将拥有真
在数千项从字符串转换为int的循环中,在调用Integer之前应该检查字符串是否为空。parseInt或应直接依赖NumberFormatException移动到下一个?