0

我正在为大学项目构建一个 java 编译器,在我的项目中,我的解析器主要位于我们现在StateT (Scope,SymbolTable) String m a所处的范围(方法、类等)并保存到目前为止定义的符号。 ScopeSymbolTable

我想在这些解析器上使用 megaparsec 的组合器,因为parensbraces这不是问题,我只是使用mapStateT,但是对于sepBy其他人,我开发了这个函数:

mapsequence :: (Monoid s,Monad m) => (m (a,(b,s)) -> m [(a,(b,s))]) -> StateT (b,s) m a -> StateT (b,s) m [a]
mapsequence f stm = do
                      s <- get
                      ases <- lift $ f $ runStateT stm s
                      case ases of
                        (_:_) -> do
                               put ((fst . snd . last) ases,(mconcat . map (snd . snd)) ases)
                               return $ map fst ases
                        [] -> return []

现在f例如:

\p -> p `sepBy` semi

无论如何,我最近意识到上面的函数是错误的,该函数将运行解析器(封装在 中StateT)向它提供我们现在拥有的状态,s然后它将再次运行它,而不是向它提供第一次运行产生的新状态它会s一次又一次地喂它,然后......

如何使用 megaparsec 的组合器,例如sepBysepEndBy等等,以便我多次运行解析器,但将结果状态从第一个到第二个到第三个等链接起来?

4

2 回答 2

0

Megaparsec 有一个单子转换器接口ParsecT

data ParsecT e s m a

ParsecT e s m a是一个具有错误e、流类型s、底层 monadm和返回类型的自定义数据组件的解析器a

您应该可以将它与类似的东西一起使用type Parser = ParsecT Dec Text (State (Scope, SymbolTable)),这将为底层State (Scope, SymbolTable)monad 添加解析功能。

于 2017-05-30T03:33:07.963 回答
0

我不知道为什么我认为我需要一个特殊的函数来执行此操作,sepBy而其他函数是在上面定义的Alternative,因为每个函数StateT都有一个Alternative实例函数,例如sepBy,many等可以直接调用。

我的问题可能是因为我不得不使用我认为是的symbolchar等等,ParsecT ...但后来我意识到这些函数是根据MonadParsectypeclass定义的,它又StateT具有实例,所以我什至不需要liftor mapStateT

所以我所做的就是更改要使用的函数签名MonadParsec,我的问题就解决了。

于 2017-05-30T09:11:24.970 回答