在标准的“monad”包装下结合Alex和Happy

时间:2017-07-21 10:41:34

标签: haskell happy alex

我设法结合了Alex lexer和Happy parser。但是我的current solution有些方面我不满意:

  1. 设置初始状态,
  2. 将状态传递给Alex时的Boilerplate代码,
  3. Alex和我的ExpParser monad是分开的实体。
  4. 我在下面解释这些方面。

    我的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的标准“初始状态”。

    然后我以下列方式使用词法分析器(使用“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
    

    但是我正在编写一些样板文件,并且还重复自己,因为上面的代码中嵌入了状态monad的行为。如果AlexState monad定义了一个实例,我可以避免这种情况,但我不认为是这种情况。

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

0 个答案:

没有答案