-
Notifications
You must be signed in to change notification settings - Fork 0
/
Parser.hs
102 lines (82 loc) · 2.95 KB
/
Parser.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
module Parser ( Parser
, Resultat
, caractere
, echoue
, parse
, (|||)
, carCond
, car
, chaine
, unOuPlus
, zeroOuPlus
, reussi
, complet
, resultat )
where
import Data.Maybe (isJust)
-- | Définition du type des analyseurs syntaxiques
type Resultat a = Maybe (a, String)
newtype Parser a = MkParser (String -> Resultat a)
-- | Briques de base
-- | Définition de la monade associée aux analyseurs syntaxiques
-- Cette définition repose sur un analyseur de base, return
-- et sur le combinateur qui séquentialise deux analyseurs
instance Monad Parser where
return v = MkParser (\s -> Just (v, s))
p >>= pf = MkParser (\s -> case parse p s of
Nothing -> Nothing
Just (a, s') -> parse (pf a) s')
fail _ = echoue
-- | Analyseur syntaxique qui retrouve le premier caractère de la
-- chaîne
caractere :: Parser Char
caractere = MkParser (\s -> case s of
"" -> Nothing
(c:cs) -> Just (c, cs))
-- | Analyseur qui échoue toujours
echoue :: Parser a
echoue = MkParser (const Nothing)
-- | Combinateur qui retourne le résultat du premier analyseur si
-- celui-ci réussit, sinon celui du second
(|||) :: Parser a -> Parser a -> Parser a
p ||| p' = MkParser (\s -> case parse p s of
Nothing -> parse p' s
r -> r)
-- | Déclenche un analyseur syntaxique sur une chaîne donnée
parse :: Parser a -> String -> Resultat a
parse (MkParser p) = p
-- | Petits analyseurs utiles
-- | Parse un caractère qui vérifie une condition donnée
carCond :: (Char -> Bool) -> Parser Char
carCond cond = caractere >>= filtre
where filtre c | cond c = return c
| otherwise = echoue
-- | Parse un unique caractère
car :: Char -> Parser Char
car c = carCond (c ==)
-- | Parse une chaîne constante
chaine :: String -> Parser String
chaine "" = return ""
chaine (c:cs) = do car c
chaine cs
return (c:cs)
-- | Combine des parseurs pour des séquences d’au moins un élément
unOuPlus :: Parser a -> Parser [a]
unOuPlus p = do r <- p
rs <- zeroOuPlus p
return (r:rs)
-- | Combine des parseurs pour des séquences de zéro ou plusieurs
-- éléments
zeroOuPlus :: Parser a -> Parser [a]
zeroOuPlus p = unOuPlus p ||| return []
-- | Détecte si l’analyse a réussi
reussi :: Resultat a -> Bool
reussi = isJust
-- | Détecte si l’analyse a complètement réussi (c’est-à-dire si toute
-- la chaîne a été analysée)
complet :: Resultat a -> Bool
complet (Just (_, "")) = True
complet _ = False
-- | Extrait le résultat, en cas de réussite du parseur
resultat :: Resultat a -> a
resultat (Just (r, _)) = r