2009-10-06 6 views
3
data Expr = Var Char | Tall Int | Sum Expr Expr | Mult Expr Expr | Neg Expr | Let Expr Expr Expr 
    deriving(Eq, Show) 

parseExpr :: String -> (Expr, String) 

parseExpr ('*':'(':s) = (Mult x y, s'') 
    where (x,',':s') = parseExpr s 
      (y,')':s'') = parseExpr s' 
parseExpr ('+':'(':s) = (Sum x y, s'') 
    where (x,',':s') = parseExpr s 
      (y,')':s'') = parseExpr s' 
parseExpr (x : xs) | isDigit x = (Tall (digitToInt x), xs) 
parseExpr (x:s) = (Var x,s) 
    where x >= 'A' = True 
     x <= 'Z' = True 

Mon analyseur manque de deux choses avant qu'il ne soit complet. A partir du type de données ci-dessus, il manque "Neg Expr" et Let "Expr Expr Expr". La première partie serait quelque chose comme ceci:Problème récursif Haskell, analyseur minuscule. Négation de Expr et laisser des expressions

parseExpr('-' 
parseExpr('l':'e':'t':x:'b':'e 

Comme dans le type de données, les expressions Let commence par let et prend place dans trois Expr. Je ne sais pas comment écrire ces dernières fonctions. Toute aide sera très appréciée.

J'ai posé une autre question ici sur SO à ce sujet, et here est le lien pour cette question.


Voici un exemple:

parseProg "let X be 4 in let Y be *(2 , X) in let Z be +(Y , X) in 
+(+(X , Y) , Z)" 
Let (Var 'X') (Tall 4) (Let (Var 'Y') (Mult (Tall 2) (Var 'X')) (Let 
(Var 'Z') (Sum (Var 'Y') (Var 'X')) (Sum (Sum (Var 'X') (Var 'Y')) (Var 
'Z')))) 

Répondre

1

La stratégie de base pour ces parties de l'expression serait le même que pour les autres opérations, juste que vous n'avez pas à analyser deux sous-expressions, mais un ou trois. Pour let il ressemblerait à ceci:

parseExpr ('l':'e':'t':s) = (Let x y z, s3) 
    where (x, 'b':'e':s1) = parseExpr s 
      (y, 'i':'n':s2) = parseExpr s1 
      (z, s3)   = parseExpr s2 

Si une chaîne commence par les lettres l, e, t prennent la chaîne restante (s) et essayer d'analyser l'expression de celle-ci. Cela entraîne une expression (x) et une chaîne restante. Nous nous attendons à ce que cette chaîne restante commence par les lettres b, e. Comme cela devrait être suivi d'une autre expression, nous donnons à nouveau le reste de cette chaîne (s2) à parseExpr pour analyser une autre expression. Etc.

Le seul problème avec ceci est que nous ne tenons pas compte des espaces qui pourraient séparer ces mots-clés tels que "let" et "be" des expressions environnantes. La solution facile serait d'exiger exactement un espace avant/après ces mots-clés et de modifier les motifs parseExpr à inclure explicitement ceux-ci, par exemple:

where (x, ' ':'b':'e':' ':s1) = parseExpr s 

plus souple serait d'ajouter une fonction dropSpaces :: String -> String qui élimine les principaux espaces et est appelé dans les endroits appropriés.

+0

En effet, j'ai une fonction pour supprimer les espaces. La fonction de filtre fonctionne très bien. – Algific