命题解析器使用榆树中的递归

发布于 2025-01-18 11:04:15 字数 3282 浏览 1 评论 0原文

昨天,我发布了一份解析逻辑命题的作业。经过大量研究并尝试不同的事情后,我让它适用于单个命题:从字符串到我自己的自定义类型命题。然而,现在我完全遇到了障碍——我几乎不知道如何组合这些组件来实现更复杂的命题。我什至不确定他们是否适合结合在一起工作。您将在下面看到我当前输出的代码和屏幕截图,任何解决此问题的建议/方法将不胜感激!

type Proposition
  = A 
  | B 
  | C
  | And Proposition Proposition
  | Or Proposition Proposition
  | Implies Proposition Proposition
  | Not Proposition
  | Equal Proposition Proposition

andParser : Parser Proposition
andParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed And
        |. symbol "&"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> andParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> andParser)
        |. spaces
        |. symbol ")"
    ]

orParser : Parser Proposition
orParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Or
        |. symbol "|"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> orParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> orParser)
        |. spaces
        |. symbol ")"
    ]

implParser : Parser Proposition
implParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Implies
        |. symbol ">"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> implParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> implParser)
        |. spaces
        |. symbol ")"
    ]

equalParser : Parser Proposition
equalParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Equal
        |. symbol "="
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> equalParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> equalParser)
        |. spaces
        |. symbol ")"
    ]

notParser : Parser Proposition
notParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> notParser)
        |. spaces
        |. symbol ")"
    ]

my_results: List String
my_results =
    [     "and parser test ____& (A , B)______",
          pr <| Parser.run andParser "& (A , C)",
          "or parser test ____ | (A , B) ______",
          pr <| Parser.run orParser "| (A , B)",
          "implies parser test ____ > (A , B) ______",
          pr <| Parser.run implParser "> (A , B)",
          "equal parser test ____ = (A , B) ______",
          pr <| Parser.run equalParser "= (A , B)",
          "equal parser test ____ N ( A ) ______",
          pr <| Parser.run notParser "N(B)",
          "parsing & ( N (B) ) C",
          pr <| Parser.run andParser "& ( A, N(B) ) "
    ] 

到目前为止的代码输出:

在此处输入图像描述

Yesterday, I posted about an assignment I got for parsing logical propositions. After a lot of research and trying different things, I got it to work for individual propositions: going from a string to my own custom type Proposition. However, now I am at a complete roadblock - I have almost no idea how to combine these components to work for more complex propositions. I am not even sure whether they are suitable to be combined and work together. You will the code and the screenshot of my current output below, any advice / ways for approaching this would be greatly appreciated!

type Proposition
  = A 
  | B 
  | C
  | And Proposition Proposition
  | Or Proposition Proposition
  | Implies Proposition Proposition
  | Not Proposition
  | Equal Proposition Proposition

andParser : Parser Proposition
andParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed And
        |. symbol "&"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> andParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> andParser)
        |. spaces
        |. symbol ")"
    ]

orParser : Parser Proposition
orParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Or
        |. symbol "|"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> orParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> orParser)
        |. spaces
        |. symbol ")"
    ]

implParser : Parser Proposition
implParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Implies
        |. symbol ">"
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> implParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> implParser)
        |. spaces
        |. symbol ")"
    ]

equalParser : Parser Proposition
equalParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Equal
        |. symbol "="
        |. spaces
        |. symbol "("
        |. spaces
        |= lazy (\_ -> equalParser)
        |. spaces
        |. symbol ","
        |. spaces
        |= lazy (\_ -> equalParser)
        |. spaces
        |. symbol ")"
    ]

notParser : Parser Proposition
notParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> notParser)
        |. spaces
        |. symbol ")"
    ]

my_results: List String
my_results =
    [     "and parser test ____& (A , B)______",
          pr <| Parser.run andParser "& (A , C)",
          "or parser test ____ | (A , B) ______",
          pr <| Parser.run orParser "| (A , B)",
          "implies parser test ____ > (A , B) ______",
          pr <| Parser.run implParser "> (A , B)",
          "equal parser test ____ = (A , B) ______",
          pr <| Parser.run equalParser "= (A , B)",
          "equal parser test ____ N ( A ) ______",
          pr <| Parser.run notParser "N(B)",
          "parsing & ( N (B) ) C",
          pr <| Parser.run andParser "& ( A, N(B) ) "
    ] 

Code output so far:

enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

莫言歌 2025-01-25 11:04:15

你已经快完成了,但是你需要一个可以解析任何类型命题的解析器,并且你需要递归地调用它而不是单独的解析器。有几种方法可以做到这一点。最简单的方法是将所有现有的解析器放在 oneOf 中:

propositionParser : Parser Proposition
propositionParser =
    oneOf
        [ andParser
        , orParser
        , implParser
        , equalParser
        , notParser
        ]

然后从其他解析器调用它,例如从 notParser

notParser : Parser Proposition
notParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> propositionParser)
        |. spaces
        |. symbol ")"
    ]

但这有很多重复,因为为每个表达式解析变量,这会使添加更多变量容易出错。因此,让我们通过将它们移入 propositionParser 来简化:

propositionParser : Parser Proposition
propositionParser =
    oneOf
        [ succeed A
            |. keyword "A"
        , succeed B
            |. keyword "B"
        , succeed C
            |. keyword "C"
        , andParser
        , orParser
        , implParser
        , equalParser
        , notParser
        ]

这将允许我们从各个解析器中删除 oneOf,因为它们每个只处理一种情况:

notParser : Parser Proposition
notParser =
    succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> propositionParser)
        |. spaces
        |. symbol ")"

您现在应该是可以看到解析器的结构反映了它解析的类型。我们现在有一个带有 oneOfpropositionParser,其中每个案例对应于 Proposition 类型中的一个案例,并且每个案例解析器都使用 >propositionParser 其中类型表明它需要一个Proposition。知道了这一点,您应该希望能够通过为每个单独的部分创建小型解析器来为任何自定义类型创建解析器,然后通过简单地模仿类型的结构来组合它们。

You're almost there, but you need a parser that can parse any kind of proposition, and you need to call that recursively instead of the individual parsers. There's a couple ways you can do that. The easiest is to just put all your existing parsers in a oneOf:

propositionParser : Parser Proposition
propositionParser =
    oneOf
        [ andParser
        , orParser
        , implParser
        , equalParser
        , notParser
        ]

and just call that from the other parsers, e.g. from notParser:

notParser : Parser Proposition
notParser =
  oneOf
    [ succeed A
        |. keyword "A"
    , succeed B
        |. keyword "B"
    , succeed C
        |. keyword "C"
    , succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> propositionParser)
        |. spaces
        |. symbol ")"
    ]

This has a lot of duplication though, as the variables are parsed for each expression, which would ale make it error-prone to add more variables. So let's simplify by moving those into propositionParser:

propositionParser : Parser Proposition
propositionParser =
    oneOf
        [ succeed A
            |. keyword "A"
        , succeed B
            |. keyword "B"
        , succeed C
            |. keyword "C"
        , andParser
        , orParser
        , implParser
        , equalParser
        , notParser
        ]

which will allow us to remove the oneOf from the individual parsers, since they're only handling one case each:

notParser : Parser Proposition
notParser =
    succeed Not
        |. symbol "N"
        |. symbol "("
        |. spaces
        |= lazy (\_ -> propositionParser)
        |. spaces
        |. symbol ")"

You should now be able to see that the structure of the parser mirrors the type it parses. We now have a propositionParser with a oneOf where each case corresponds to a case from the Proposition type, and with each individual case parser using propositionParser where the type says it needs a Proposition. Knowing this, you should hopefully be able to create a parser for any custom type by creating small parsers for each individual piece, and then combine them by simply mimicking the structure of the type.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文