如何在 State 上使用 megaparsecs 组合器
how to use megaparsec's combinators on StateT
我正在为大学项目 java 构建编译器,在我的项目中,我的解析器主要是 StateT (Scope,SymbolTable) String m a
,其中 Scope
是我们现在的范围(方法, class,etc) 和 SymbolTable
包含到目前为止定义的符号。
我想在那些解析器上使用 megaparsec 的组合器,对于 parens
、braces
这不是问题,我只使用 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 的组合器,如 sepBy
、sepEndBy
等,以便我 运行 解析器多次但将结果状态从第一个链接到第二个到第三等 ?
Megaparsec 有一个 monad 转换器接口 ParsecT
:
data ParsecT e s m a
ParsecT e s m a
is a parser with custom data component of error e
, stream type s
, underlying monad m
and return type a
.
您应该能够将它与 type Parser = ParsecT Dec Text (State (Scope, SymbolTable))
之类的东西一起使用,它将向底层 State (Scope, SymbolTable)
monad 添加解析功能。
我不知道为什么我认为我需要一个特殊的函数来做到这一点,sepBy
和其他定义在 Alternative
上,因为每个 StateT
都有一个 Alternative
实例函数如sepBy
、many
等可以直接调用。
我的问题可能是因为我不得不使用 symbol
、char
等,我认为它们是 ParsecT ...
但后来我意识到这些函数是根据 MonadParsec
类型类 StateT
再次具有实例,所以我什至不需要 lift
或 mapStateT
。
所以我所做的就是更改函数签名以使用 MonadParsec
,我的问题就解决了。
我正在为大学项目 java 构建编译器,在我的项目中,我的解析器主要是 StateT (Scope,SymbolTable) String m a
,其中 Scope
是我们现在的范围(方法, class,etc) 和 SymbolTable
包含到目前为止定义的符号。
我想在那些解析器上使用 megaparsec 的组合器,对于 parens
、braces
这不是问题,我只使用 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 的组合器,如 sepBy
、sepEndBy
等,以便我 运行 解析器多次但将结果状态从第一个链接到第二个到第三等 ?
Megaparsec 有一个 monad 转换器接口 ParsecT
:
data ParsecT e s m a
ParsecT e s m a
is a parser with custom data component of errore
, stream types
, underlying monadm
and return typea
.
您应该能够将它与 type Parser = ParsecT Dec Text (State (Scope, SymbolTable))
之类的东西一起使用,它将向底层 State (Scope, SymbolTable)
monad 添加解析功能。
我不知道为什么我认为我需要一个特殊的函数来做到这一点,sepBy
和其他定义在 Alternative
上,因为每个 StateT
都有一个 Alternative
实例函数如sepBy
、many
等可以直接调用。
我的问题可能是因为我不得不使用 symbol
、char
等,我认为它们是 ParsecT ...
但后来我意识到这些函数是根据 MonadParsec
类型类 StateT
再次具有实例,所以我什至不需要 lift
或 mapStateT
。
所以我所做的就是更改函数签名以使用 MonadParsec
,我的问题就解决了。