Parsing Haskell:如果块计算器在GHCI中正常工作,但在通过解析表达式对其求值时却不能正常工作

Parsing Haskell:如果块计算器在GHCI中正常工作,但在通过解析表达式对其求值时却不能正常工作,parsing,haskell,eval,Parsing,Haskell,Eval,我正试图为我的语言编写一个计算器,它接受一个解析的if块,计算所有条件并过滤掉假分支,然后随机选择一个分支。我正处于这样一个阶段,我可以过滤掉分支,留下我可能的路径,但只能在GHCI内。当我试图通过命令行将if块传递到程序中时,如果第一个分支为True,则会发生这种情况,这是唯一执行的分支,否则不管是否有任何分支,都会返回一个空列表。我的二进制表达式求值器工作正常,因此我知道我的错误与if求值器或解析器中的逻辑有关 以下是通过命令行执行的行为: ~/Desktop/Olivia > ./M

我正试图为我的语言编写一个计算器,它接受一个解析的if块,计算所有条件并过滤掉假分支,然后随机选择一个分支。我正处于这样一个阶段,我可以过滤掉分支,留下我可能的路径,但只能在GHCI内。当我试图通过命令行将if块传递到程序中时,如果第一个分支为True,则会发生这种情况,这是唯一执行的分支,否则不管是否有任何分支,都会返回一个空列表。我的二进制表达式求值器工作正常,因此我知道我的错误与if求值器或解析器中的逻辑有关

以下是通过命令行执行的行为:

~/Desktop/Olivia > ./Main "if (1 > 3)-> 1 + 1 [] (1 < 2)-> 2 + 2"
[] 
~/Desktop/Olivia > ./Main "if (1 < 3)-> 1 + 1 [] (1 < 2)-> 2 + 2"
[2]
这是我预期的结果。对于
n
sub if表达式的数量,我将选择整个列表中的一个列表作为我的分支,然后再回去评估循环保护并开始程序的下一次迭代

我的数据类型:

data HVal
  = HInteger Integer
  | HBool    Bool
  | HString  String
  | HList    [HVal]
  | Expr    HVal Op HVal  
  | EqExpr  HVal Op HVal 
  | Neg      HVal
  | Assign   HVal   HVal  
  | Do       HVal   [HVal]
  | If       HVal   [HVal] [HVal]
  | SubIf    HVal  [HVal]
  | Load     String
  deriving (Eq, Read)
我的解析器:

parseIf :: Parser HVal
parseIf = do
 _  <-  string "if"
 spaces
 _  <-  string "("
 cond  <- (parseExpr <|> parseEqExpr <|> parseBool)
 _  <-  string ")->"
 expr  <- spaces *> many (parseExpression <* spaces)
 expr' <- spaces *> many (parseExpression <* spaces)
 return $ If cond expr expr'

parseSubIf :: Parser HVal
parseSubIf = do
  _ <- string "[]"
  spaces
  _ <- string "("
  cond <- (parseExpr <|> parseEqExpr <|> parseBool)
  _ <- string ")->"
  expr <- spaces *> many (parseExpression <* spaces)
  return $ SubIf cond expr

我认为错误可能与if块的解析器有关。我的想法是,if块包含第一个分支的条件及其计算结果,然后是一个子表达式列表,其中列表的每个元素都包含分支条件及其计算结果。

听起来您需要自己测试解析器,在ghci中或通过在编译的程序中打印解析结果。您可能需要为HVal导出
Show
,以便可以打印它。
expr many(parseExpression@chi Many的使用使得一个分支可能包含多个表达式,如果其条件为真。这就是为什么
if
采用列表。第一个列表指可能的表达式。如果第一个分支的条件为真,那么第二个列表是包含if语句的下一个
n
分支的列表
parseIf :: Parser HVal
parseIf = do
 _  <-  string "if"
 spaces
 _  <-  string "("
 cond  <- (parseExpr <|> parseEqExpr <|> parseBool)
 _  <-  string ")->"
 expr  <- spaces *> many (parseExpression <* spaces)
 expr' <- spaces *> many (parseExpression <* spaces)
 return $ If cond expr expr'

parseSubIf :: Parser HVal
parseSubIf = do
  _ <- string "[]"
  spaces
  _ <- string "("
  cond <- (parseExpr <|> parseEqExpr <|> parseBool)
  _ <- string ")->"
  expr <- spaces *> many (parseExpression <* spaces)
  return $ SubIf cond expr
eval :: HVal -> HVal
---------- EVALUATING PRIMITIVES ----------
eval val@(HString _) = val
eval val@(HInteger _) = val
eval val@(HBool _) = val
eval val@(HList _) = val
eval (Expr x op y) = evalExpr x op y
eval (If cond expr expr') = evalIf cond expr expr'
eval (SubIf cond expr) = evalSubIf cond expr

evalIf :: HVal -> [HVal] -> [HVal] -> HVal
evalIf cond expr expr' = if ((eval cond) == (HBool True))
                            then HList $ map eval expr
                            else HList $ (filter (/= (HInteger 1)) (map eval expr'))

evalSubIf :: HVal -> [HVal] -> HVal
evalSubIf cond expr = if ((eval cond) == (HBool True))
                         then HList $ map eval expr
                         else (HInteger 1)