Message From Martijn Schrage

Center

-- DoaitseSwierstra - 02 Oct 2003

Ik zou graag de volgende combinator willen bestellen:

pErr :: ([Error] -> a) -> Parser a -> Parser a  
(of misschien: <!!>, <!?>, oid.)

Als er een error optreed in de argument parser, dan moet in plaats van zijn gerepareerde resultaat het eerste argument opgeleverd worden als resultaat (voorzien van de fouten). Het belangrijke is echter dat alleen de errors op het nivo van de argument parser zelf van belang zijn, en dus niet de errors in de kinderen of verderop.

Dus: (even uit m'n hoofd)

data Exp = IfExp Exp Exp Exp | IntExp Exp | ParseErrExp [Error]

parseExp = ParseErrExp `pErr`
           IfExp  <$  pIf   <*> parseExp
                  <*  pThen <*> parseExp
                  <*  pElse <*> parseExp
       <|> IntExp <$> pInt

De pInt, pIf, pThen, en pElse parsers gebruiken geen pErr, en dus komen hun errors in de aanroepende pExp parser terecht.

Dit zou de volgende resultaten moeten geven

"if 0 then 1 else 2" => IfExp (Int 0) (Int 1) (Int 2)
"if 0 then 1 ellse 2" => ParseErrExp
"if 0 then if 0 then 1 ellse 2 else 2" => IfExp (Int 0) ParseErrExp (Int 2)
"if 0x then 1 else 2" => liefst: IfExp ParseErrExp (Int 1) (Int 2)
                                  maar wellicht: ParseErrExp

Met alleen If en Int is het soms niet helemaal duidelijk waar de fout komt, maar zo lang hij maar afgehandeld wordt op de plek waar hij tijdens het parsen optreedt, dan is dit geen probleem.

Met deze combinators kan ik de parse fout zo lokaal mogelijk houden, en in combinatie met een layout regel verwacht ik dat tijdens het editen een programma dan grotendeels correct geparsed kan worden en daarop dus ook document (structure) editing operaties beschikbaar kunnen zijn. Dan hebben we dus scoping info, type checking, navigatie, etc. voor syntactisch nog niet helemaal correcte programma's.

Waarschijnlijk is het mooier om een algemenere pErr te maken, die ook het gerepareerde resultaat meegeeft aan het parseError argument:

pErr :: (a -> [Error] -> Parser a) -> a -> Parser a -> Parser a

De andere pErr is dan: pErr' err = pErr (const err)

Nu kun je ook voor het datatype  ".. | ParseErrExp [Error] Exp" parsen. Maar voor Proxima heb ik dat nog niet nodig. Bovendien ben ik huiverig voor gerepareerde stukken document in de editor presentatie. Het is druk voor de gebruiker, redelijk onvoorspelbaar, en bovendien is het voor een Haskell parser erg makkelijk om dingen weg te gooien en overal functie applicaties van te maken.