2010-11-28 9 views
2

Am encore nouveau pour Haskell, alors mes excuses s'il y a une réponse évidente à cette ...


Je voudrais faire une fonction qui divise la toutes les listes de chaînes suivantes soit [chaîne]:Haskell: Délimiter une chaîne par sous-chaînes choisies et les espaces

["int x = 1", "y := x + 123"] 
["int x= 1", "y:= x+123"] 
["int x=1", "y:=x+123"] 


tous dans la même chaîne de chaînes par exemple [[chaîne]]:

[["int", "x", "=", "1"], ["y", ":=", "x", "+", "123"]] 



Vous pouvez utiliser map words.lines pour le premier [Chaîne].

Mais je ne sais pas de moyens vraiment bien de prendre également en compte les autres - où vous utiliserez les différents sous-chaînes "=", ":=", etc. "+" pour briser la chaîne principale.



Merci de prendre le temps de me éclairer sur Haskell :-)

Répondre

7

Le Prélude est livré avec une fonction pratique peu connue appelée lex, qui est un lexer pour les expressions Haskell. Ceux-ci correspondent au formulaire dont vous avez besoin.

lex :: String -> [(String,String)] 

Quel type étrange cependant! La liste est là pour l'interfaçage avec un type d'analyseur standard, mais je suis à peu près sûr que lex renvoie toujours des éléments 1 ou 0 (0 indiquant une erreur d'analyse). Le tuple est (token-lexed, rest-of-input), donc lex ne retire qu'un jeton. Il existe un moyen LEX une chaîne entière serait:

lexStr :: String -> [String] 
lexStr "" = [] 
lexStr s = 
    case lex s of 
     [(tok,rest)] -> tok : lexStr rest 
     []   -> error "Failed lex" 

Pour apaiser les pédants, ce code est en forme terrible. Un appel explicite à error au lieu de renvoyer une erreur raisonnable en utilisant Maybe, en supposant que lex ne renvoie que des éléments 1 ou 0, etc. Le code qui le fait de manière fiable est de la même longueur, mais est significativement plus abstrait, donc j'ai épargné vos yeux débutants.

3

je prendrais un coup d'œil à parsec et construire une grammaire simple pour analyser vos cordes.

+0

Merci pour votre réponse. J'espérais cependant un moyen simple de le faire «purement», c'est-à-dire sans autres bibliothèques. Oh, et de préférence sans monades non plus (parce que je n'ai pas encore tout à fait appris à les connaître encore lol). –

+0

Ouais parsec n'est pas génial quand vous commencez. J'ai trouvé qu'il était relativement facile d'éditer un analyseur que quelqu'un d'autre avait écrit, mais écrire le mien dépassait mes capacités pendant un moment. Nécessite un peu de confort avec des monades. – luqui

+0

Assez juste. Cela vaut la peine de considérer cela comme une option. Si vous voulez quelque chose d'autre qui n'est pas monadique, vous devrez peut-être choisir une option personnalisée. –

0

que diriez-vous d'utiliser des mots.) words :: String -> [String] et mots de soins pour habitude .. espaces blancs

words "Hello World" 
= words "Hello  World" 
= ["Hello", "World"] 
+0

Oh - je viens de voir que je n'ai pas pensé longtemps: les mots ne seront pas divisés "y: =" en "y", ": =", donc vous devrez soit écrire votre propre analyseur simple (peut-être avec le aide de mots: P) ou utiliser parsec (ce qui est un bon choix à savoir de toute façon). –

+0

Plus l'utilisation de 'mots' était déjà mentionnée dans la question;) –

+0

Wonderfull - Je devrais commencer à utiliser la désorientation de mes commentaires comme indicateur pour aller dormir ... –