intellij-haskforce
intellij-haskforce copied to clipboard
Parser consumes too much in do block
I'm pretty sure the problem here either lies in HaskellParserUtilBase.stateHackMess
or HaskellParserWrapper.increaseRbraceDebt
. I'm having trouble deciphering the logic in those methods.
The line runGhcModT' :: IOish m ...
is being considered part of the do
block and parsed as an exp
instead of a gendecl
.
module Layout00021 where
runGhcModT :: IOish m
=> Options
-> GhcModT m a
-> m (Either GhcModError a, GhcModLog)
runGhcModT opt action = do
env <- liftBase $ newGhcModEnv opt =<< getCurrentDirectory
first (fst <$>) <$> (runGhcModT' env defaultState $ do
dflags <- getSessionDynFlags
defaultCleanupHandler dflags $ do
initializeFlagsWithCradle opt (gmCradle env)
action)
runGhcModT' :: IOish m
=> GhcModEnv
-> GhcModState
-> GhcModT m a
-> m (Either GhcModError (a, GhcModState), GhcModLog)
runGhcModT' r s a = do
(res, w') <-
flip runReaderT r $ runJournalT $ runErrorT $
runStateT (unGhcModT $ initGhcMonad (Just ghcLibDir) >> a) s
return (res, w')
The logic is broken and hard to decipher as you say; we're essentially squeezing square pegs into round holes. Will take a look on saturday.
The problem is line 33-38 in Layout00021.txt for the parsing lexer test suite. The lexer alone can't compensate for that though, so ideally the parser should tell the lexer to get a grip and insert the synthetic braces in the right place. That's not possible with IntelliJ though; the lexer runs over the entire file and the content is cached so the parser can work on that. So the problem on lines 33-38 must remain, it's supposed to look that way despite being wrong.
The broken logic tries to compensate for the situation dynamically, but as expected it's fragile and doesn't work all the time.
This seems like it may be useful: http://stackoverflow.com/questions/1413204/how-to-use-indentation-as-block-delimiters-with-bison-and-flex
There's a paper about parsing Haskell with Parsec at the Haskell Symposium this year. That approach doesn't need the L algorithm (which is what the crap in the parsing lexer + the logic you pointed out tries to implement), so it might actually work. Will start in that end; our current lexer is sufficient for that approach.
I had a look at the approach. I think it will pan out in the long run, but it's not exactly a work of art. Nevertheless--works is a pretty important metric. I just pushed a partial fix for this ticket.
This is definitely fixable with the approach. I have a large outstanding patch for Haskell.bnf that is not ready for merging yet, so it would be great if we could hold off other commits to that file for a few days to avoid conflicts.
Please ignore if not not related (or move to a different issue). I have the following test case:
module Hello where
-- | Parser for the endianess.
endianessParser :: IO Char
endianessParser = do
case 'c' of
x | x == 'c' -> return 'b'
x -> return 'a'
{-# INLINE endianessParser #-}
symParser :: Char
symParser = 'a' -- Need to consume the \0 byte
{-# INLINE symParser #-}
I'm not entirely sure what is happening, but if I remove the do it is fine, similarly when I remove the case statement or the INLINE pragma. Otherwise it is complaining with:
" unexpected.
I understand this is a completely evil piece of code, in reality it is blowing up on this code: https://github.com/jkozlowski/kdb-haskell/blob/kdb-haskell-2/src/Database/Kdb/Internal/IPC.hs#L302.
Almost all weird parsing error messages relate to the same shortcoming with indentation handling, so you're probably in the right ticket.
We should probably have a disclaimer about the shortcomings of the parser somewhere. HaskForce should parse all legal Haskell, whether it's evil or not.