mi piacerebbe implementare questa regola grammaticale utilizzando la libreria parsec di Haskell:Haskell parsec: `many` combinatore all'interno di un combinatore` optional`
((a | b | c)* (a | b))?
che è una regola parser che accetta un optional (cioè potenzialmente vuoto) stringa. Se la stringa che acccepts non è vuota, allora può essere consumato passando attraverso zero o più occorrenze dei a
b
o c
parser, ma la stringa accettata dalla più esterna ?
parser opzionale deve essere consumato mediante parser a
o b
, ma non c
. Ecco un esempio:
module Main where
import Text.Parsec
import Text.Parsec.Text
a,b,c :: GenParser() Char
a = char 'a'
b = char 'b'
c = char 'c'
-- ((a | b | c)* (a | b))?
myParser = undefined
shouldParse1,shouldParse2,shouldParse3,
shouldParse4,shouldFail :: Either ParseError String
-- these should succeed
shouldParse1 = runParser myParser() "" "" -- because ? optional
shouldParse2 = runParser myParser() "" "b"
shouldParse3 = runParser myParser() "" "ccccccb"
shouldParse4 = runParser myParser() "" "aabccab"
-- this should fail because it ends with a 'c'
shouldFail = runParser myParser() "" "aabccac"
main = do
print shouldParse1
print shouldParse2
print shouldParse3
print shouldParse4
print shouldFail
Un primo tentativo potrebbe essere simile a questo:
myParser = option "" $ do
str <- many (a <|> b <|> c)
ch <- a <|> b
return (str ++ [ch])
Ma la many
appena consuma tutta 'a' 'b' e '' caratteri C in ogni caso di test, lasciando a <|> b
nessun personaggio da consumare.
La domanda:
Utilizzando combinatori parsec, qual è la corretta attuazione del ((a | b | c)* (a | b))?
per definire myParser
?
Forse parse (A | B | c) + e rifiutalo più tardi se termina con c? –