Haskell解析器到AST数据类型 - 输入"|"时解析错误

Joh*_*Gis 1 parsing haskell

我正在努力完成我们给予的任务.我在这里稍微基于不同的指南编写了这段代码:不在范围内:数据构造函数

我遇到的问题是这里的管道:

| x == "+" = (Sum y y',xs'') where
Run Code Online (Sandbox Code Playgroud)

问题似乎与3个管道或管道跟在"哪里"有关.如果我交换最后2个管道.把

x == "+"  = (Sum y y' (...))
Run Code Online (Sandbox Code Playgroud)

之前

x == "*"  = (Prod y y' (...))
Run Code Online (Sandbox Code Playgroud)

导致错误移动到该代码.如果我注释掉这两个代码段中的任何一个,一切正常,但是我需要它们来完成我们给出的赋值.

快速摘要:

| x == "*" = (Prod y y',xs'') where
                (y,xs') = ast xs
                (y',xs'') = ast xs'
Run Code Online (Sandbox Code Playgroud)

| x == "+" = (Sum y y',xs'') where
                (y,xs') = ast xs
                (y',xs'') = ast xs'
Run Code Online (Sandbox Code Playgroud)

两者都单独工作,但当我把它们放在一起时,我的程序无法编译.

完整代码:

import Data.Char

data AST = Leaf Int 
            | Sum AST AST 
            | Min AST 
            | Prod AST AST
            deriving Show

tokenize::String -> [String]
tokenize[] = []
tokenize('+':xs) = "+": tokenize xs
tokenize('-':xs) = "-": tokenize xs
tokenize('*':xs) = "*": tokenize xs
tokenize(x:xs) = if isDigit x then (takeWhile isDigit (x:xs)) : tokenize (dropWhile isDigit xs) else tokenize(xs)

ast :: [String] -> (AST,[String])
ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
    | x == "-" = let (y,xs') = ast xs in (Min y,xs')
    | x == "*" = (Prod y y',xs'') where
            (y,xs') = ast xs
            (y',xs'') = ast xs'
    | x == "+" = (Sum y y',xs'') where
            (y,xs') = ast xs
            (y',xs'') = ast xs'
Run Code Online (Sandbox Code Playgroud)

Dan*_*her 7

问题在于

ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
    | x == "-" = let (y,xs') = ast xs in (Min y,xs')
    | x == "*" = (Prod y y',xs'') where
            (y,xs') = ast xs
            (y',xs'') = ast xs'
    | x == "+" = (Sum y y',xs'') where
            (y,xs') = ast xs
            (y',xs'') = ast xs'
Run Code Online (Sandbox Code Playgroud)

就是where在函数定义中每个方程只能有一个子句.因此,wherex == "*"替代方案之后,解析器期望模式的等式(x:xs)完成.

只要删除有问题where,该where子句的范围是等式中的所有替代,并且两个where子句具有相同的内容(并且where根据我的偏好将其缩进更好,属于它自己的行).由于let第一个替代方案使用了where子句中也存在的绑定,因此也可以删除:

ast [] = error "Empty string"
ast (x:xs) | all isDigit x = (Leaf (read x),xs)
    | x == "-" = (Min y,xs')
    | x == "*" = (Prod y y',xs'')
    | x == "+" = (Sum y y',xs'')
      where
        (y,xs') = ast xs
        (y',xs'') = ast xs'
Run Code Online (Sandbox Code Playgroud)