2016-07-25 3 views
0

La documentation Parsec a un exemple d'utilisation makeTokenParser pour construire un lexer:Évitez les répétitions dans lexing lors de l'utilisation parsec

module Main where 

import Text.Parsec 
import qualified Text.Parsec.Token as P 
import Text.Parsec.Language (haskellDef) 

-- The parser 
... 

expr = parens expr 
     <|> identifier 
     <|> ... 


-- The lexer 
lexer  = P.makeTokenParser haskellDef  

parens  = P.parens lexer 
braces  = P.braces lexer 
identifier = P.identifier lexer 
reserved = P.reserved lexer 
... 

Dans le bloc « Le lexer », chaque P.* est appliqué à lexer de telle sorte que l'on peut éviter de répéter dans le bloc "Le parseur". Cependant répéter cela pour chaque jeton est toujours fastidieux. Y a-t-il un moyen d'éviter la répétition encore plus? Je pensais implicitement appliquer lexer partout dans "The Parser", mais je suis perdu à comment.

Répondre

3

Il y a un syntax for pattern matching on records général Haskell (j'ai commencé par remarquer que tous P.parens, P.braces, etc. sont des fonctions de projection records - vous pouvez voir qu'en regardant la docs.). Vous pouvez l'utiliser ici

P.TokenParser { P.parens  = parens 
       , P.braces  = braces 
       , P.identifier = identifier 
       , P.reserved = reserved 
       } = P.makeTokenParser haskellDef 

EDIT

Comme ErikR l'a souligné, il vous ne voulez pas seulement quelques-uns des parseurs, mais vous voulez tout 29 des champs GenTokenParser mis en portée mondiale , vous pouvez activer l'extension RecordWildCards et il suffit d'écrire

P.TokenParser {..} = P.makeTokenParser haskellDef 
+2

Si vous activez 'RecordWildCards', vous pouvez utiliser simplement' P.TokenParser {..} = lexer' au niveau supérieur pour définir tous les champs d'enregistrement. – ErikR