2017-05-29 14 views
0

我正在为大学项目构建java的编译器,在我的项目中,我的解析器大多是StateT (Scope,SymbolTable) String m a,其中Scope是我们现在的范围(方法,类等),并且SymbolTable成立直到现在定义的符号。如何在StateT上使用megaparsec的组合器

我想用百万秒差距的组合程序上的解析器,为parensbraces这不是问题,我只是用mapStateTsepBy等我开发了这一功能:

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等,这样我可以多次运行解析器,但将结果状态从第一个链接到第二个到第三个等等?

+1

这看起来不对。 'runState'应该让你'((b,s),a)',而不是'[a]',这样你就可以'放'这个状态。 –

+0

@BartekBanachewicz状态是'(b,s)'所以'runState'会返回'(a,(b,s))',我对结果运行函数'f'来得到'[((b,s) ),a)]' – niceman

+1

所以有你的问题。你留下了多个国家。你现在应该选择哪一个? –

回答

0

我不知道为什么,我觉得我需要一个特殊的功能,要做到这一点,sepBy和其他人正在Alternative定义,因为每个StateT有一个像sepBymany等的Alternative实例功能,可直接调用。

我的问题可能是因为我不得不用symbolchar,等我想是ParsecT ...但后来我意识到这些功能在MonadParsec类型类,其StateT再有实例来定义的,所以我根本就不需要liftmapStateT

所以我所做的只是改变功能签名与MonadParsec一起工作,我的问题就解决了。

0

百万秒差距具有单子变压器接口ParsecT

data ParsecT e s m a 

ParsecT e s m a是与错误e的自定义数据分量,流类型s解析器,底层单子m和返回类型a

你应该能够用的东西用这个像type Parser = ParsecT Dec Text (State (Scope, SymbolTable)),这将增加分析功能,底层State (Scope, SymbolTable)单子。

+0

我的所有解析器都是'StateT(Scope,SymbolTable)String(ParsecT ...)a'这里,我有很多他们我不能轻易改变他们,无论如何,我找到了解决方案,我将会发布它 – niceman