我在2018.04玩这个最长的代币匹配,但我不认为最长的代币匹配:
say 'aaaaaaaaa' ~~ m/
| a+?
| a+
/; # 「a」
我期望第二个选项有最长的标记,因为它有一个贪婪的量词,看起来非贪婪的量词被算作最长标记的一部分,尽管大纲5指出它不应该被包括在内。
如果颠倒顺序,我会得到预期的输出:
say 'aaaaaaaaa' ~~ m/
| a+
| a+?
/; # 「aaaaaaaaa」
这应该是这样发生的吗?引擎认为这些标记的长度是多少?官方文档是相当模糊的,所以我借鉴了大纲5来苏斯清楚这是如何工作的。
2条答案
按热度按时间ar5n3qh51#
我在编译器中进行了深入的研究,看看那里发生了什么,
+
限定符action方法调用backmod,它反过来将backtrack属性设置为“f”。然而,为量词编译NFA的代码根本不考虑回溯属性,因此对每个量词都一视同仁,而不管其回溯模式如何。因此,它的行为就像
?
不存在一样,这意味着它将考虑长度相等的两个分支。然后,它使用声明顺序作为平局决胜局。这导致它选择第一个分支。然后,一旦选择,就应用节俭量词,因此匹配单个“a”。(这也解释了为什么交换顺序会改变事情。)这看起来确实与S05的设想不一致,即
a+?
应该被简单地视为“命运”(在本例中,意味着a+?
替代品将具有零长度的最长令牌)。规范(即指定语言的测试套件)对这一问题保持沉默,然而,目前使其成为未定义的行为。S05中提出的行为对我来说是有意义的,所以我主张以这种方式指定和实现它。
axkjgtzd2#
我认为目前的行为是正确的。
只有能被NFA或DFA匹配的东西才能成为Longest-Token Match的一部分,而且据我所知,简约量词并不能转化为自动机形式(自动机的工作原理是将所有字符输入自动机,并且在读取完整字符串之前没有接受的概念)。