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

使用makeExprParser遇歧义:含>运算符的表达式解析失败

解决方案

你的问题核心是两个点:一是parseInteger强制要求数字后必须跟空白,导致无空白的1223>234无法被解析;二是Megaparsec需要明确表达式的边界,避免把外层的>误判为运算符。以下是可直接运行的修复代码,同时保留makeExprParser的使用:

-- uses megaparsec, text, and parser-combinators
{-# LANGUAGE OverloadedStrings #-}

module Main where

import Control.Monad.Combinators.Expr
import Data.Text
import Data.Void
import System.Environment
import Text.Megaparsec
import Text.Megaparsec.Char
import qualified Text.Megaparsec.Char.Lexer as L

type BinaryOperator = Text

type Name = Text

data Expr
  = IntExpr Integer
  | BinaryExpression BinaryOperator Expr Expr
  deriving (Eq, Show)

type Parser = Parsec Void Text

lexeme :: Parser a -> Parser a
lexeme = L.lexeme sc

symbol :: Text -> Parser Text
symbol = L.symbol sc

sc :: Parser ()
sc = L.space space1 (L.skipLineComment "//") (L.skipBlockCommentNested "/*" "*/")

-- 修复:用lexeme包裹L.decimal,自动处理数字后的空白(包括无空白的情况)
parseInteger :: Parser Expr
parseInteger = lexeme $ IntExpr <$> L.decimal

parseExpr :: Parser Expr
parseExpr = makeExprParser parseInteger 
  [[InfixL (BinaryExpression ">" <$ symbol ">")]]

parseBracketList :: Parser [Expr]
parseBracketList = do
  _ <- symbol "<"
  -- 关键:用try确保表达式解析失败时回溯,避免外层>被误吞
  exprs <- sepBy (try parseExpr) (symbol ",")
  _ <- symbol ">"
  return exprs

main :: IO ()
main = do
  text : _ <- getArgs
  let res = runParser parseBracketList "stdin" (pack text)
  case res of
    Right suc -> print suc
    Left err -> putStrLn $ errorBundlePretty err

关键修改说明

  • 修复parseInteger:原代码中手动调用sc强制要求数字后必须有空白,改用lexeme $ L.decimal后,lexeme会自动处理数字后的空白(包括无空白的场景),让1223>234中的1223能被正确解析。
  • 添加try到sepBy:在sepBy (try parseExpr) (symbol ",")中用try包裹parseExpr,确保当表达式解析失败(比如遇到外层>而非运算符>)时,解析器能回溯并终止表达式解析,转而匹配外层的>。

测试输入<1223>234>会输出[BinaryExpression ">" (IntExpr 1223) (IntExpr 234)],完全符合预期。你不需要手动编写表达式解析器,makeExprParser依然可以正常使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 23:25:27