stream.UserState 更新时 FParsec ‘many’ 原语失败
FParsec ‘many’ primitive fails when stream.UserState updated
以下例程是 official documentation, "Tracing a parser"“解析器跟踪包装器的一个小的简化更改。
let (<!>) (parser: Parser<_,USER_STATE>) label : Parser<_,USER_STATE> =
fun stream ->
do stream.UserState <- stream.UserState // <= works if commented out!
let reply = parser stream
reply
此包装器允许在解析器执行时检查 reply
并根据需要更新 stream.UserState
。
注意:此代码只是将 stream.UserState
复制到自身,实际上什么都不做,因为这是出现以下错误的最小操作。 official documentation manipulating stream.UserState ("Recursive grammers with nesting restrictions”) 操纵 stream.UserState
更多...
在第 3 行注释掉 do stream.UserState <- stream.UserState
允许重复(生成列表)和非重复 FParsec 原语成功.对于这些生成列表的原语,最后的从属解析器失败被解除并且应用程序,例如,many
成功。
如果上述包装器中的 parser
不是 创建结果列表的 FParsec 原语(如 many
或 sepEndBy
) , 从属解析器的重复应用则这段代码解析成功.
如果parser
是一个FParsec重复原语(例如many
或sepEndBy
),那么从属解析器应用程序的失败是作为重复 FParsec 原语的失败也传回 - 意外失败.
为什么包含 do stream.UserState <- stream.UserState
会导致像 many
这样的 FParsec 原语失败?
EDIT1:请注意,FParsec documentation 对 stream.UserState
进行了分配,如本问题中所做的那样。 @brianbern,根据文档,我不明白你的 post 我在做什么是错的。谢谢!
如何在不中断对 FParsec many
原语的调用的情况下分配给 stream.UserState
?
发生这种情况的原因是 CharStream.UserState
的 setter 作为副作用增加了流的 StateTag
。来自 FParsec source code:
public TUserState UserState {
get { return _UserState; }
set { _UserState = value; ++StateTag; }
}
因此,当您将流的 UserState
分配给自身时,不 等同于什么都不做。
更新:“many”解析器的文档指出:
The parser many p
repeatedly applies the parser p
until p
fails. It returns a list of the results returned by p
. At the end of the sequence p
must fail without changing the parser state and without signalling a FatalError
, otherwise many p
will fail with the error reported by p
.
FParsec 文档中的示例不会在序列末尾修改解析器状态,但您的示例解析器会在每次调用时修改解析器状态。
以下例程是 official documentation, "Tracing a parser"“解析器跟踪包装器的一个小的简化更改。
let (<!>) (parser: Parser<_,USER_STATE>) label : Parser<_,USER_STATE> =
fun stream ->
do stream.UserState <- stream.UserState // <= works if commented out!
let reply = parser stream
reply
此包装器允许在解析器执行时检查 reply
并根据需要更新 stream.UserState
。
注意:此代码只是将 stream.UserState
复制到自身,实际上什么都不做,因为这是出现以下错误的最小操作。 official documentation manipulating stream.UserState ("Recursive grammers with nesting restrictions”) 操纵 stream.UserState
更多...
在第 3 行注释掉 do stream.UserState <- stream.UserState
允许重复(生成列表)和非重复 FParsec 原语成功.对于这些生成列表的原语,最后的从属解析器失败被解除并且应用程序,例如,many
成功。
如果上述包装器中的 parser
不是 创建结果列表的 FParsec 原语(如 many
或 sepEndBy
) , 从属解析器的重复应用则这段代码解析成功.
如果parser
是一个FParsec重复原语(例如many
或sepEndBy
),那么从属解析器应用程序的失败是作为重复 FParsec 原语的失败也传回 - 意外失败.
为什么包含 do stream.UserState <- stream.UserState
会导致像 many
这样的 FParsec 原语失败?
EDIT1:请注意,FParsec documentation 对 stream.UserState
进行了分配,如本问题中所做的那样。 @brianbern,根据文档,我不明白你的 post 我在做什么是错的。谢谢!
如何在不中断对 FParsec many
原语的调用的情况下分配给 stream.UserState
?
发生这种情况的原因是 CharStream.UserState
的 setter 作为副作用增加了流的 StateTag
。来自 FParsec source code:
public TUserState UserState {
get { return _UserState; }
set { _UserState = value; ++StateTag; }
}
因此,当您将流的 UserState
分配给自身时,不 等同于什么都不做。
更新:“many”解析器的文档指出:
The parser
many p
repeatedly applies the parserp
untilp
fails. It returns a list of the results returned byp
. At the end of the sequencep
must fail without changing the parser state and without signalling aFatalError
, otherwisemany p
will fail with the error reported byp
.
FParsec 文档中的示例不会在序列末尾修改解析器状态,但您的示例解析器会在每次调用时修改解析器状态。