ReadP递归解析

时间:2016-09-13 17:29:08

标签: parsing haskell recursion

在使用wikibooks article"(a*b+c^d)"之类的字符串解析为树的ReadP中,有以下代码:

import Text.ParserCombinators.ReadP

brackets p = do char '('
                r <- p
                char ')'
                return r

data Operator = Add | Mul | Exp deriving Show
operators = [(Add,'+'),(Mul,'*'),(Exp,'^')]

data Tree = Branch Operator Tree Tree | Leaf String deriving Show

leaf = do s <- many1 (choice (map char ['a'..'z']))
          return (Leaf s)

tree = foldr (\(op,name) p ->
               let this = p +++ (p +++ brackets tree
                        >>= (\a -> char name
                        >>= (\_ -> this
                        >>= (\b -> return (Branch op a b)))))
                in this)
             (leaf +++ brackets tree)
             operators

我无法得到的是this上的递归在这里的作用方式(我已经贬低do希望它能帮助我理解它,但无济于事)。有人可以解释一下this - do块中的jQuery.validator.addMethod("myRule", function (value, element, params) { return this.optional(element) || value== params[0]; }, "Account number 00000000 is invalid"); $('#myform').validate({ // initialize the plugin submitHandler: function (form) { console.log("Submitted!"); }, rules: { accountNumber: { required: true, minlength: 8, maxlength: 8, /*MyRule solution found online but not working as expected any other option I could try within JQUERY Validator????*/ myRule: ["00000000"], digits: true }, companyNumber: { required: true, digits: true } }, messages: { accountNumber: { digits: 'Account Number must be an number', minlength: 'Account number cannot be less than 8 digits', maxlength: 'Account number cannot be more than 8 digits', required : 'Account number is required' }, companyNumber: { digits: 'Company number must be a number', required : 'Company number is required' } } }); 是如何被评估的(因为它看起来像是对我的无限递归,显然不是这样)?

2 个答案:

答案 0 :(得分:6)

让我们看一下public struct MyContainer { public MyContainer(int myValue) : this() { MyValue = myValue; } public int MyValue { get; private set; } } public struct MyContainer2 { private readonly int _myValue; public MyContainer2(int myValue) { _myValue = myValue; } public int MyValue { get { return _myValue; } } } 的定义(我发现使用this表示法更容易):

do

所以在这里,右侧唯一出现的let this = p +++ do a <- p +++ brackets tree char name b <- this return (Branch op a b) in this 位于this操作的第二个参数内,即:

+++

如您所见,在此表达式中,do a <- p +++ brackets tree char name b <- this return (Branch op a b) 出现在其他一些操作之后,即thisa <- p +++ brackets tree。这意味着将在char name之前首先尝试这些其他操作。如果其中一个失败,则不会尝试任何后续操作。例如,如果this成功,但输入流不包含等于a <- p +++ brackets tree引用值的字符,name将失败,char name行将不会一切都在尝试。所以这意味着b <- this无需以无条件递归方式自我调用

答案 1 :(得分:3)

以下是查看tree的定义的另一种方式:

t0 = leaf +++ brackets tree
t1 = do a <- t0 +++ (t0 +++ brackets tree)
        char '+'
        b <- t1
        return (Branch Add a b)
t2 = do a <- t1 +++ (t1 +++ brackets tree)
        char '*'
        b <- t2
        return (Branch Mul a b)
t3 = do a <- t2 +++ (t2 +++ brackets tree)
        char '^'
        b <- t3
        return (Branch Exp a b)
tree = t3

注意树的定义是循环依赖:tree - &gt; t3 - &gt; t2 - &gt; t1 - &gt; t0 - &gt; treet0&#34;的定义与结结合了#34;以来 它指的是brackets tree

每个级别都添加了解析新运算符的功能:t0只解析 叶子节点和括号,t1t0t2之上添加了添加内容 在t1之上添加乘法等等。

(编辑:实际上,由于这是一个正确的折叠,运算符会以相反的顺序有效地添加 - 即。t1添加取幂,t3添加加法。)

这使得最终解析器tree成为正确关联,即a+b+c被解析为a + (b + c)