2012-10-17 4 views
3

J'ai ceci:Comment supprimer les commentaires d'un fichier avec Parsec?

comment :: GenParser Char st() 
comment = 
    (string "--" >> manyTill anyChar newline >> spaces >> return()) <|> 
    (string "/*" >> manyTill anyChar (string "*/") >> spaces >> return()) 

eatComments :: GenParser Char st String 
eatComments = do 
    xs <- many (do 
      optional comment 
      x <- manyTill anyChar (try comment) 
      return x) 
    return $ intercalate " " xs 

Cela fonctionne si l'entrée se termine par un commentaire, mais il échoue si elle se termine par autre chose. Dans ce cas, le message d'erreur est comme

No match (line 13, column 1): 
unexpected end of input 
expecting "--" or "/*" 

L'analyseur recherche un commentaire par le temps eof arrive. J'ai besoin d'aide pour trouver les bons combinateurs dont j'ai besoin pour manger tous les commentaires dans tous les cas possibles.

+1

Si vous ne souhaitez pas conserver les commentaires, utilisez le module Token. Voir les exemples dans la distribution Parsec 2.0 d'origine pour l'utilisation du module Token et de LanguageDef: http://legacy.cs.uu.nl/daan/parsec.html –

+0

Est-ce que cela nécessite un langage def pour la version MySQL de SQL et DDL? – dan

+0

Oui. Effectivement, un LangaugeDef est une spécification lexer pour Parsec. Ils sont beaucoup plus simples à écrire qu'un Alex Alex - bien qu'ils soient moins puissants. –

Répondre

3

Peut-être utiliser quelque chose comme eof?

comment :: GenParser Char st() 
comment = 
    (string "--" >> manyTill anyChar newline >> spaces >> return()) <|> 
    (string "/*" >> manyTill anyChar ((try (string "*/") >> return()) <|> eof) >> spaces >> return()) 
+0

Pour moi qui produit l'erreur "Impossible de correspondre type attendu' String 'avec le type réel '()'" – dan

+0

... Dans le second argument de '(<|>) ', à savoir' eof' Dans le deuxième argument de 'manyTill ', à savoir ' (string "* /" <|> eof)' – dan

+0

Désolé, je l'ai corrigé maintenant. Notez également que vous avez besoin de quelque chose comme 'try (string" */")' pour fermer le commentaire, sinon l'entrée suivante échouera:/* Hello World ** / –

0

J'ai frappé sur ce qui semble fonctionner. Mais n'hésitez pas à critiquer:

comment :: GenParser Char st() 
comment = 
    (string "--" >> manyTill anyChar newline >> spaces >> return()) <|> 
    (string "/*" >> manyTill anyChar (string "*/") >> spaces >> return()) 

notComment = manyTill anyChar (lookAhead (comment <|> eof)) 

eatComments :: GenParser Char st String 
eatComments = do 
    optional comment 
    xs <- sepBy notComment comment 
    optional comment 
    return $ intercalate "" xs 
Questions connexes