-
Notifications
You must be signed in to change notification settings - Fork 203
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Paren parser problems #982
Comments
You say the paren parser is greedy, but does that also mean that all |
I think problem lies in paren parser only, or rather not in underlying library. I forgot exactly what I meant by indent parser but I believe it is thr name for one of the other haskell mode parsers (which do not exhibit the bug). You can see the bug by adding tracing into the underlying Alex code and see the position and tokens it consumes. It then becomes easy to try other modes and see uf the problem persists. |
I found the problem: the adjustBlock function. Changing & modeAdjustBlockA .~ adjustBlock to & modeAdjustBlockA .~ (\_ _ -> return ()) fixes the greedy behaviour. |
Aha, I'm going to blame |
Just for the record: the adjustBlock situation is "solved" by 3f6df01 |
I think |
|
Ah, I didn't see that part. But still, what if a type can do optimizations if it is applicative, but can't do those if it is monadic? Should it just not be an instance of Monad, or should it have some kind of newtype wrapper? |
You're free to implement A famous example is Haxl where |
I think something similar is happening in You say:
Do you mean it goes into an infinite loop? You could view an infinite loop as just a very inefficient implementation. But overall I agree that we should do some more research on this. |
IIRC it outright crashed. Anyway those parsers are based on a paper, might be worth reading that first. Maybe someone "optimised" original code and broke it. |
@Fuuzetsu can you link to the code where pTree is defined? |
yi/yi-mode-haskell/src/Yi/Syntax/Paren.hs Line 120 in 51855c9
|
|
I have replaced parse and parse' with: parse :: P TT (Tree TT)
parse = liftM Expr (parse' tokT tokFromT)
parse' :: (TT -> Token) -> (Token -> TT) -> P TT [Tree TT]
parse' toTok _ = liftM2 const pExpr eof
where
-- parse a special symbol
sym c = symbol (isSpecial [c] . toTok)
pleaseSym c = recoverWith errTok <|> sym c
pExpr :: P TT (Expr TT)
pExpr = liftM2 (:) pTree pExpr <|> pure []
pBlocks = (liftM Expr pExpr) `sepBy1` sym '.' -- the '.' is generated by the layout, see HACK above
-- note that we can have empty statements, hence we use sepBy1.
pTree :: P TT (Tree TT)
pTree = (liftM3 Paren (sym '(') pExpr (pleaseSym ')'))
<|> (liftM3 Paren (sym '[') pExpr (pleaseSym ']'))
<|> (liftM3 Paren (sym '{') pExpr (pleaseSym '}'))
<|> (liftM Block (liftM3 (\_ a _ -> a) (sym '<') pBlocks (sym '>'))) -- see HACK above
<|> (liftM Atom (symbol (isNoise . toTok)))
<|> (liftM Error (recoverWith (symbol (isSpecial "})]" . toTok)))) And that seems to still work (i.e. I opened some haskell files with cleverMode after recompiling yi and nothing crashed). |
I was investigating why clever Haskell mode works as bad as it does (again). I have several findings
Yi.Syntax.Paren.parse
) forces whole result even when it is going to be thrown away.That is, open a file, only screenfull gets loaded. Edit any part, the (lazy) parser for the rest of the file runs in full then we run another parse for the screenfull.
Basically it seems it's written poorly and needs to be greedy
Parse
(Parser.Incremental.Parse
) violates basic laws.ap
/=<*>
. Fun exercise is replacingpure <$> pTree
withreplicateM 1 pTree
and watching it crash. Indeed these two things aren't equivalent:The text was updated successfully, but these errors were encountered: