【问题标题】:Parsing an optionally-multi-line expression with FParsec使用 FParsec 解析可选的多行表达式
【发布时间】:2011-12-16 11:08:35
【问题描述】:

我正在为这种形式的字符串编写 FParsec 解析器:

do[ n times]([ action] | \n([action]\n)*endDo)

换句话说,这是一个带有可选时间量词的“do”语句,以及单个“action”语句或一个“action”列表(每个都在一个新行上),在结束(为简单起见,我省略了缩进/尾随空格处理)。

这些是有效输入的示例:

do action

do 3 times action

do
endDo

do 3 times
endDo

do
action
action
endDo

do 3 times
action
action
endDo

这看起来不是很复杂,但是:

为什么这不起作用?

let statement = pstring "action"
let beginDo = pstring "do"
                >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")
let inlineDo = tuple2 beginDo (spaces >>. statement |>> fun w -> [w])
let expandedDo = (tuple2 (beginDo .>> newline)
                    (many (statement .>> newline)))
                 .>> pstring "endDo"
let doExpression = (expandedDo <|> inlineDo)

什么是这个表达式的正确解析器?

【问题讨论】:

    标签: f# fparsec


    【解决方案1】:

    您需要使用attempt 函数。 我刚刚修改了你的 beginDodoExpression 函数。

    这是代码:

    let statement  o=o|>  pstring "action"
    
    let beginDo o= 
        attempt (pstring "do"
            >>. opt (spaces1 >>. pint32 .>> spaces1 .>> pstring "times")) <|> 
            (pstring "do" >>% None)                                       <|o
    
    let inlineDo   o= tuple2 beginDo (spaces >>. statement |>> fun w -> [w]) <|o
    let expandedDo o= (tuple2 (beginDo .>> newline) (many (statement .>> newline)))
                     .>> pstring "endDo" <|o
    
    let doExpression o= ((attempt expandedDo) <|> inlineDo) .>> eof <|o
    

    我在最后添加了一个eof。这样会更容易测试。

    我还添加了虚拟o 参数以避免值限制。

    【讨论】:

    • 有效!所以基本上我错过了两个attempt?我仍然不明白为什么需要它们。
    • 是的,因为如果第一个解析器(在 p1 p2 表达式中)失败并且它已经消耗了输入,那么您需要一种回溯的方法。这基本上就是尝试函数的作用。
    • 好的,知道了。但是,你什么时候可以不加尝试地使用 呢?每次执行 a b 时,a 必须失败才能选择 b,不是吗?
    • 例如,如果您执行 pFloat 某些操作,则不需要它,因为如果 pFloat 失败,它不会消耗任何输入。问题是,当您编写解析器时,可能最后一个解析器失败,但其他解析器消耗了一些输入。
    • 请注意这个解析器。 spaces 也使用换行符,因此解析器将接受不带 'endDo' 的“do[newline]action”,这可能会在以后成为问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多