You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

逻辑公式解析器Either类型列表解析失败问题求助

逻辑公式解析器Either列表解析问题修复方案

问题复现

解析P(f(x:X)=a:A,b:B)时,预期输出:

  • 替换项:[((f,([(x,X)],A),(a,A))]
  • 谓词:(P, [(a,A),(b,B)])

实际输出仅为(P, [Left b:B]),替换项完全丢失。但单独用commaSep parseVSub解析f(x:X)=a:A,b:B能得到正确结果[Right (f(x:X),a:A),Left b:B],说明问题出在pparens与commaSep parseVSub的组合逻辑中。

问题根源分析

  1. 符号处理不一致:代码中混用string和symbol处理符号,string不会自动跳过前后空格,可能导致解析过程中因空格匹配失败触发回溯,丢失第一个元素。
  2. 回溯逻辑冗余:pparens和parsePredSub中的try包裹范围过大,可能在局部解析失败时触发不必要的全局回溯,导致部分元素被跳过。
  3. 预期与代码逻辑不匹配:当前代码中,替换项里的a:A不会被加入谓词参数列表,但你的预期中需要包含该元素,这是逻辑设计的偏差。

修复步骤

1. 统一符号解析逻辑

将所有符号((、)、:、=)替换为symbol函数处理,确保自动跳过前后空格,避免因空格导致的解析失败:

parseVS :: Parser VarSrt
parseVS = do {v<-identifier; symbol ":"; s<-identifier; return $ (v,s)}

pparens :: Parser a -> Parser (String,a)
pparens par = do {p<-identifier; symbol "("; z <- par; symbol ")";
                  return (p,z)}

parseSub :: Parser Sub
parseSub =
  do {(f,a) <- pparens (commaSep parseVS); symbol "=";
       (x,s) <- parseVS;
       return $ ((f,(a,s)),(x,s))}

2. 优化解析器顺序与回溯

调整parseVSub的解析顺序,先尝试复杂的parseSub再尝试简单的parseVS,减少不必要的回溯;同时移除pparens中的冗余try(因为identifier+(是独特前缀,不会与其他解析器冲突):

parseVSub :: Parser VSub
parseVSub = choice [Right <$> try parseSub, Left <$> parseVS]

3. 修正谓词参数逻辑

如果需要将替换项中的VarSrt(即a:A)加入谓词参数列表,调整parsePredSub的返回逻辑:

parsePredSub :: Parser PredSub
parsePredSub = do {(p,bc) <- pparens (commaSep parseVSub);
                   let subs = rights bc
                       -- 将替换项中的变量类型对加入谓词参数
                       params = lefts bc ++ map snd subs
                   return (subs, (p, params))}

验证效果

修复后解析P(f(x:X)=a:A,b:B),将得到:

  • 替换项:[((f,([(x,X)],A),(a,A))]
  • 谓词:(P, [(a,A),(b,B)])
    完全符合预期。

内容的提问来源于stack exchange,提问作者CB Wells

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 08:10:54