Haskell 在标准下结合Alex和Happy”;单子;包装纸

Haskell 在标准下结合Alex和Happy”;单子;包装纸,haskell,happy,alex,Haskell,Happy,Alex,我成功地结合了Alex lexer和Happy解析器。然而,我的工作中有一些方面我不满意: 建立初始状态 将状态传递给Alex时的样板代码 Alex和myExpParsermonad是分离的实体 我将在下面解释这些方面 我的ExpParsermonad如下所示: data ParserEnv = ParserEnv { varModifier :: String -> String } newtype ExpParser a = ExpParser { runExpParse

我成功地结合了Alex lexer和Happy解析器。然而,我的工作中有一些方面我不满意:

  • 建立初始状态
  • 将状态传递给Alex时的样板代码
  • Alex
    和my
    ExpParser
    monad是分离的实体
  • 我将在下面解释这些方面

    我的
    ExpParser
    monad如下所示:

     data ParserEnv = ParserEnv
      { varModifier :: String -> String }
    
    newtype ExpParser a = ExpParser 
      { runExpParser :: ReaderT ParserEnv (StateT AlexState (Except String)) a }
      deriving ( Functor, Applicative, Monad
               , MonadReader ParserEnv
               , MonadState AlexState
               , MonadError String
               )
    
    顶级解析函数定义为:

    -- | Parsing function.
    parse :: (String -> String) -> String -> Either String Exp
    parse f str = runExcept $ (`evalStateT` initState) $ runReaderT (runExpParser calc) initEnv
      where initEnv = ParserEnv { varModifier = f}
            initState = AlexState -- TODO: isn't it a standard initial state that we can use?        
              { alex_pos = AlexPn 0 0 0
              , alex_inp = str
              , alex_chr = '\n' -- TODO: What to include here?
              , alex_bytes = []
              , alex_scd = 0
              }
    
    第一个问题是,我必须用一些我不确定的字段设置初始状态。此外,我希望为Alex lexer定义一个标准的“初始状态”

    然后,我以以下方式使用lexer(使用“monad”包装器生成):

    mLexer :: (Token -> ExpParser a) -> ExpParser a
    mLexer cont = do -- TODO: is there a way to reduce this boilerplate?
      alexSt <- get
      case unAlex alexMonadScan alexSt of
        Left err -> throwError err
        Right (nextAlexSt, token) ->
          do
            put nextAlexSt
            cont token
    
    mLexer::(令牌->ExpParser a)->ExpParser a
    mLexer cont=do--TODO:有没有办法减少这个样板文件?
    阿列克斯特投手失误
    右(nextAlexSt,令牌)->
    做
    下一步
    连续令牌
    
    但我正在编写一些样板文件,也在重复我自己,因为上面的代码中嵌入了状态monad的行为。如果
    Alex
    State
    monad定义了一个实例,我可以避免这种情况,但我认为情况并非如此


    在上述方面是否有改进当前解决方案的方法?

    “Alex和Axel”?你是说“Alex和Happy”?是的。谢谢。为什么不用
    ExpParser
    作为Alex的单子呢?