2016-09-02 11:47:33 +02:00
|
|
|
---
|
|
|
|
abstract: Rant about Haskell's parser "Happy".
|
2019-10-30 13:28:37 +01:00
|
|
|
lastupdated: 2014
|
2016-09-02 11:47:33 +02:00
|
|
|
---
|
|
|
|
|
|
|
|
![](UNHAPPY.PNG)
|
|
|
|
|
|
|
|
|
2016-09-02 23:32:55 +02:00
|
|
|
# Unhappy About Happy: A Reflection or Something Like That
|
2016-09-02 11:47:33 +02:00
|
|
|
|
2019-10-30 13:28:37 +01:00
|
|
|
*2014.*
|
|
|
|
|
2016-09-02 11:47:33 +02:00
|
|
|
For the purposes of my quiet rage, this document will be written in all
|
|
|
|
caps. I also will not use proper language. I won't even give suggestions
|
|
|
|
on how to improve Happy; I'll just complain.
|
|
|
|
|
|
|
|
STARTING NOW
|
|
|
|
|
|
|
|
WHAT HAPPY ???
|
|
|
|
--------------
|
|
|
|
|
|
|
|
HAPPY IS PARSER GENERATOR. IT GENERATE HASKELL CODE. VISIT
|
|
|
|
[<HTTP://WWW.HASKELL.ORG/HAPPY/>](http://www.haskell.org/happy/) FOR
|
|
|
|
UGLY INFO.
|
|
|
|
|
|
|
|
HOW HAPPY GOOD
|
|
|
|
--------------
|
|
|
|
|
|
|
|
- EFFICIENT I GUESS
|
|
|
|
- WORKS OK
|
|
|
|
- PRETTY LOGO
|
|
|
|
|
|
|
|
WHY I NOT LIKE HAPPY
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
### JUZT TYPICAL
|
|
|
|
|
|
|
|
![](MEME0.PNG)
|
|
|
|
|
|
|
|
ONE ERROR IN PARSER.Y GIVE HUGE TYPE ERROR
|
|
|
|
|
|
|
|
**WHAT IS THIS!**
|
|
|
|
|
|
|
|
dist/build/l0c/l0c-tmp/Language/L0/Parser/Parser.hs:2452:42:
|
|
|
|
Couldn't match type `Value' with `BasicValue -> Value'
|
|
|
|
Expected type: HappyAbsSyn
|
|
|
|
(Name, SrcLoc)
|
|
|
|
[(Name,
|
|
|
|
DeclTypeBase Name,
|
|
|
|
[ParamBase Name],
|
|
|
|
ExpBase NoInfo Name,
|
|
|
|
SrcLoc)]
|
|
|
|
(Name,
|
|
|
|
DeclTypeBase Name,
|
|
|
|
[ParamBase Name],
|
|
|
|
ExpBase NoInfo Name,
|
|
|
|
SrcLoc)
|
|
|
|
Uniqueness
|
|
|
|
([Maybe (DimSize Name)], ElemTypeBase NoInfo Name)
|
|
|
|
(ElemTypeBase NoInfo Name)
|
|
|
|
[TypeBase NoInfo Name]
|
|
|
|
[TypeBase NoInfo Name]
|
|
|
|
[ParamBase Name]
|
|
|
|
(Maybe (CertificatesBase NoInfo Name), [ExpBase NoInfo Name])
|
|
|
|
[ExpBase NoInfo Name]
|
|
|
|
[ExpBase NoInfo Name]
|
|
|
|
/* ... 200-300 MORE LINES ... */
|
|
|
|
[TupIdentBase NoInfo Name]
|
|
|
|
(TupIdentBase NoInfo Name)
|
|
|
|
(LambdaBase NoInfo Name)
|
|
|
|
(TupleLambdaBase NoInfo Name)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
Int
|
|
|
|
(BasicValue -> Value)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
Value
|
|
|
|
(BasicValue -> Value)
|
|
|
|
(BasicValue -> Value)
|
|
|
|
[Value]
|
|
|
|
[Value]
|
|
|
|
In the second argument of `happySpecReduce_3', namely
|
|
|
|
`happyReduction_191'
|
|
|
|
In the expression: happySpecReduce_3 38# happyReduction_191
|
|
|
|
In an equation for `happyReduce_191':
|
|
|
|
happyReduce_191 = happySpecReduce_3 38# happyReduction_191
|
|
|
|
|
|
|
|
**NOT NICE NOT NICE AT ALL**
|
|
|
|
|
|
|
|
### MONADA CAN I HAZ
|
|
|
|
|
|
|
|
MAYHAPS U NEED TO PARSE DIFFERENT THAN NORMAL KAY. HOW U THINK. YES:
|
|
|
|
MENTALINCRMENTAL PARSING IT IS
|
|
|
|
|
|
|
|
![](MEME1.PNG)
|
|
|
|
|
|
|
|
YOU GOT NEED TO PARSE IO GETLINE SOURCES YEAH
|
|
|
|
|
|
|
|
PARSE EXPRESSION "2 + 1 \*4" OVER MULTI LINES LIKE THIS HERE
|
|
|
|
|
|
|
|
WELCOM TO DA FUNKY MULTILINE EXPRESSION PARSER; ENTER UR EXPRESSION
|
|
|
|
> 2 +
|
|
|
|
1 *4
|
|
|
|
TY GOT IT!! PARSED EXPRESSION IS "2 + 1 * 4" AND U NICE; RESULT IS 6 BTW
|
|
|
|
>
|
|
|
|
|
|
|
|
PARSER SHOULD KNOW "YEAH NOT DUHNE PARSIN YET" WHEN "2 +" READ, SHOULD
|
|
|
|
TEHN READ NEW LINE AND PARSE MORE!
|
|
|
|
|
|
|
|
WE CAN PARSE FROM BEGINNING EVERY TIME SURE BUT INEFECICIENT!!!
|
|
|
|
|
|
|
|
![](MEME2.PNG)
|
|
|
|
|
|
|
|
BUT HOW WE SHOULD / COULD DO THAT SMARTLY I IMPLORE TO LIKE ASK U
|
|
|
|
|
|
|
|
![](MEME3.PNG)
|
|
|
|
|
|
|
|
YES WE USE CONTINUATION WHICH SMART. LOOK ATTOPARSEC USE CONTINUATION IN
|
|
|
|
RETURN!
|
|
|
|
[<HTTP://HACKAGE.HASKELL.ORG/PACKAGE/ATTOPARSEC-0.11.1.0/DOCS/DATA-ATTOPARSEC-TEXT.HTML#T:IRESULT>](http://hackage.haskell.org/package/attoparsec-0.11.1.0/docs/Data-Attoparsec-Text.html#t:IResult)
|
|
|
|
|
|
|
|
YEAH BUT NOT IN HAPPY............
|
|
|
|
|
|
|
|
SO WE MAKE IT MANUAL. WE SPECIFY OWN LEXER AND IMPROVE MONAD. WHEN END
|
|
|
|
OF LINE IS REACH, WE TELL PARSER (FROM INSIDE DA PRASER) DAT DERE IS NO
|
|
|
|
MORE EVER; IF THAT FAILS WE CATCH ERROR (EITHER-LIKE MONAD) AND READ NEW
|
|
|
|
LINE FOR REALS
|
|
|
|
|
|
|
|
![](MEME4.PNG)
|
|
|
|
|
|
|
|
CLEVER SOLUTION OF US! BUT IN PARSE EXPRESION EXAMPLE ABOV WE USE IO TO
|
|
|
|
GETLINE
|
|
|
|
|
|
|
|
**WE NOT WANT IO IN ALL PARSING.... EVER EVER!!!!!!!!**
|
|
|
|
|
|
|
|
HOWTO ABSTRACT IO AWAY? WE WANT TYPE OF EXPORTED FUNCTIONS FROM PARSER
|
|
|
|
TO NOT USE **IO** *AT ALL*
|
|
|
|
|
|
|
|
![](MEME5.PNG)
|
|
|
|
|
|
|
|
SO WE USE WHATEVER MONAD TO GETLINE RIGHT?
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
class GetLiner m where -- KAY SO m IS MONAD RIGHT
|
|
|
|
getSomeLine :: m String
|
|
|
|
|
|
|
|
instance GetLiner IO where
|
|
|
|
getSomeLine = getLine
|
|
|
|
```
|
|
|
|
|
|
|
|
WAIT I DONT GET IT
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
CLASS GETLINER M WHERE -- KAY SO M IS MONAD RIGHT
|
|
|
|
GETSOMELINE :: M STRING
|
|
|
|
|
|
|
|
INSTANCE GETLINER IO WHERE
|
|
|
|
GETSOMELINE = GETLINE
|
|
|
|
```
|
|
|
|
|
|
|
|
MUCH BETTR. COZ TEHN WE CAN USE
|
|
|
|
|
|
|
|
![](MEME6.PNG)
|
|
|
|
|
|
|
|
BUT YIAH WE COULD USE TYPE CONSTRAINTS!
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
LEXER :: GETLINER M => M SOMETHNIG
|
|
|
|
LEXER = MEHMEHMEH
|
|
|
|
WOO <- GETSOMELINE
|
|
|
|
MEH MEH
|
|
|
|
```
|
|
|
|
|
|
|
|
SURE COULD WORK WE NEED JUST TELL HAPPY BOUT IT.
|
|
|
|
|
|
|
|
%MONAD { GETLINER M => SOMETHINNG M }
|
|
|
|
|
|
|
|
FAILS MISERBLY.................... :-( :( :(
|
|
|
|
|
|
|
|
WE ARE LEFT 4 PONDER HOW TO SOLVE! HOWTO ABSTRAKT OUT IO! HOW!!
|
|
|
|
|
|
|
|
![](MEME7.PNG)
|
|
|
|
|
|
|
|
SOOOO..... WE NEED KINDA CONTINUATIN COMPUTATON MONADY THINGY. I GOT
|
|
|
|
FRIEND WHO COME WIT CODE, SAY IT GOOD CODE. I CHECK, HE RIGHT! IS HERE
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
DATA READLINEMONAD A = VALUE A
|
|
|
|
| GETLINE (STRING -> READLINEMONAD A)
|
|
|
|
|
|
|
|
INSTANCE MONAD READLINEMONAD WHERE
|
|
|
|
RETURN = VALUE
|
|
|
|
VALUE X >>= F = F X
|
|
|
|
GETLINE G >>= F = GETLINE $ \S -> G S >>= F
|
|
|
|
```
|
|
|
|
|
|
|
|
HA CLEVER!!! NOW WE NEED NO TYPE CONSTRAINTS BECAUSE NOW COMPUTATION IS
|
|
|
|
MONAD ITSELF! HOW YOU ASK.
|
|
|
|
|
|
|
|
READLINEMONAD HAS NO IO OR ANY ELSE BUILTIN; IT GETS LINE BY CREATE
|
|
|
|
FUNCTION WHICH TAKES LINE TO CONTINUU EXECUTION. AGAIN AND AGAIN! LINE
|
|
|
|
CAN COME FROM ANYTHIN.
|
|
|
|
|
|
|
|
EXAMPLE FOR USING RESULT!
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
GETLINESFROMIO :: READLINEMONAD A -> IO A
|
|
|
|
GETLINESFROMIO (VALUE X) = RETURN X
|
|
|
|
GETLINESFROMIO (GETLINE F) = DO
|
|
|
|
S <- GETLINE
|
|
|
|
GETLINESFROMIO $ F S
|
|
|
|
```
|
|
|
|
|
|
|
|
U SEE WAT GOIN ON DERE! IN OUR LEXER WE NAMELI USED
|
|
|
|
|
|
|
|
``` {.haskell}
|
|
|
|
GETLINE VALUE
|
|
|
|
```
|
|
|
|
|
|
|
|
TO GET LINE (BECAUSE FITS WITH CLEVER MONAD!)
|
|
|
|
|
|
|
|
**NICE-O!**
|
|
|
|
|
|
|
|
CODE IN QUSTION
|
|
|
|
---------------
|
|
|
|
|
|
|
|
LOOKIE HER FOR FULL DETAILS (ALTHOU WITH NO FULL CAPS):
|
|
|
|
[<HTTPS://RARRW.GITHUB.COM/HIPERFIT/L0LANGUAGE/MASTER/SRC/LANGUAGE/L0/PARSER/PARSER.Y>](https://raw.github.com/HIPERFIT/L0Language/master/src/Language/L0/Parser/Parser.y)
|
|
|
|
|
|
|
|
CONCLUSION
|
|
|
|
----------
|
|
|
|
|
|
|
|
![](MEME8.PNG)
|
|
|
|
|
|
|
|
![](MEME9.PNG)
|
|
|
|
|
|
|
|
THIS IS ENTRELY OBJECTIVE.
|
|
|
|
|
|
|
|
THIS IS ENTIREY OBJECTIVE.
|
|
|
|
|
|
|
|
THIS IS ENTIRLY OBJECTIVE.
|