Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex parsec中的完全回溯星算子_Regex_Haskell_Parsec - Fatal编程技术网

Regex parsec中的完全回溯星算子

Regex parsec中的完全回溯星算子,regex,haskell,parsec,Regex,Haskell,Parsec,我正在尝试在parsec上构建一个真正的、完全回溯+组合器 也就是说,接收解析器并尝试查找给定组合器的一个或多个实例的人 例如,这意味着解析一个或多个愚蠢的字符a将能够匹配一行中的九个字符a。(有关上下文,请参见下面的代码) 据我所知,它目前没有这样做的原因是,在a找到匹配项(前两个As)后,many1(try p1)从未放弃该匹配项 这在parsec中可能吗?很确定这会很慢(这个简单的例子已经是指数级的了!),但我想知道是否可以做到。这是一个没有时间限制的编程挑战——我不想在野外使用它 imp

我正在尝试在parsec上构建一个真正的、完全回溯+组合器

也就是说,接收解析器并尝试查找给定组合器的一个或多个实例的人

例如,这意味着
解析一个或多个愚蠢的字符a
将能够匹配一行中的九个字符a。(有关上下文,请参见下面的代码)

据我所知,它目前没有这样做的原因是,在
a
找到匹配项(前两个As)后,
many1(try p1)
从未放弃该匹配项

这在parsec中可能吗?很确定这会很慢(这个简单的例子已经是指数级的了!),但我想知道是否可以做到。这是一个没有时间限制的编程挑战——我不想在野外使用它

import Text.Parsec
import Text.Parsec.String (Parser)

parse_one_or_more :: Parser String -> Parser String
parse_one_or_more p1 = (many1 (try p1)) >> eof >> return "bababa"

foolish_a = parse_one_or_more (try (string "aa") <|> string "aaa")

good_a = parse_one_or_more (string "aaa")

-- |
-- >>> parse foolish_a "unused triplet" "aaaaaaaaa"
-- Left...
-- ...
-- >>> parse good_a "unused" "aaaaaaaaa"
-- Right...
import Text.Parsec
导入Text.Parsec.String(解析器)
解析一个或多个::解析器字符串->解析器字符串
解析一个或多个p1=(多个(尝试p1))>>eof>>返回“bababa”
愚蠢的a=parse一个或多个(try(string“aa”)string“aaa”)
good\u a=解析一个或多个(字符串“aaa”)
-- |
-->>>解析“未使用的三元组”“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
--左。。。
-- ...
-->>>解析“未使用的”“aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”
--对。。。

您是对的-类似于Parsec的库不能以适用于任何输入的方式完成这项工作。Parsec对
()
的实现是左偏的,如果匹配,则提交给左解析器,而不管语法后面可能发生什么。当
()
的两个参数重叠时,例如在
(try(string“aa”)string“aaa”)
中,如果左侧成功,则无法使parsec回溯到其中并尝试右侧匹配


如果您想这样做,您将需要一个不同的库,一个没有左偏并提交的
()
运算符的库。

您是对的-类似于Parsec的库不能以对任何输入都有效的方式来做这件事。Parsec对
()
的实现是左偏的,如果匹配,则提交给左解析器,而不管语法后面可能发生什么。当
()
的两个参数重叠时,例如在
(try(string“aa”)string“aaa”)
中,如果左侧成功,则无法使parsec回溯到其中并尝试右侧匹配


如果你想这样做,你需要一个不同的库,一个没有左偏和提交的
()
操作符的库。

是的,因为Parsec产生一个递归下降解析器,你宁愿先做一个明确的猜测,以最小化回溯的需要。因此,如果您的第一个猜测是
“aa”
,而这恰好与后来的猜测重叠
“aaa”
,则需要回溯。有时,对于某些k>1的语法是LL(k),出于纯粹的需要,您希望使用回溯

我唯一一次使用
try
是当我知道回溯非常有限(k很低)时。例如,我可能有一个操作符与另一个操作符重叠;我想先解析
,因为有优先规则,但我希望解析器在后面跟着
/
的情况下失败,以便它最终能够达到正确的解析。这里k=2,所以影响很小,但我也不需要一个让我任意回溯的操作符


如果您想要一个解析器组合器库,使您能够始终完全回溯,那么这可能会严重影响性能。您可以查看的对称选择运算符既可以选择这两个运算符,也可以选择这两个运算符。这是Carl建议的一个例子,一个不带左偏的提交。

是的,因为Parsec产生了一个递归下降解析器,所以您更希望首先进行明确的猜测,以最小化回溯的需要。因此,如果您的第一个猜测是
“aa”
,而这恰好与后来的猜测重叠
“aaa”
,则需要回溯。有时,对于某些k>1的语法是LL(k),出于纯粹的需要,您希望使用回溯

我唯一一次使用
try
是当我知道回溯非常有限(k很低)时。例如,我可能有一个操作符与另一个操作符重叠;我想先解析
,因为有优先规则,但我希望解析器在后面跟着
/
的情况下失败,以便它最终能够达到正确的解析。这里k=2,所以影响很小,但我也不需要一个让我任意回溯的操作符

如果您想要一个解析器组合器库,使您能够始终完全回溯,那么这可能会严重影响性能。您可以查看的对称选择运算符既可以选择这两个运算符,也可以选择这两个运算符。这是Carl建议的一个例子,一个不带偏见和提交的