2017-06-30 4 views
3

J'écris un programme pour modifier les fichiers de code source. J'ai besoin d'analyser le fichier (par exemple avec megaparsec), de modifier son arbre de syntaxe abstraite AST (par exemple avec Uniplate), et de régénérer le fichier avec aussi peu de changements que possible (par exemple préserver les espaces, les commentaires, ...).comment écrire un analyseur qui ne consomme pas d'espace?

Ainsi, l'AST doit contenir les espaces, par exemple:

data Identifier = Identifier String String 

où la première chaîne est le nom de l'identifiant, et le second est les espaces après. La même chose s'applique pour n'importe quel symbole dans la langue.

Comment écrire un analyseur pour Identifier?

+1

Je pense que cela a été demandé avant, mais je ne sais pas d'une norme solution (je l'ai déjà fait moi-même d'une manière un peu lourde). – leftaroundabout

Répondre

2

Je fini par écrire parseLexeme, pour remplacer lexème dans this tutorial

data Lexeme a = Lexeme a String -- String contains the spaces after the lexeme 

whites :: Parser String 
whites = many spaceChar 

parseLexeme :: Parser a -> Parser (Lexeme a) 
parseLexeme p = do 
    value <- p 
    w <- whites 
    return $ Lexeme value w 

instance PPrint a => PPrint (Lexeme a) where 
    pprint (Lexeme value w) = (pprint value) ++ w 

L'analyseur pour identifier devient:

data Identifier = Identifier (Lexeme String) 

parseIdentifier :: Parser Identifier 
parseIdentifier = do 
    v <- parseLexeme $ (:) <$> letterChar <*> many (alphaNumChar <|> char '_') 
    return $ Identifier v 

instance PPrint Identifier where 
    pprint (Identifier l) = pprint l 
+0

Impossible d'utiliser makeExprParser, ce qui est dommage, car il traite de la priorité des opérateurs, ... – user474491