{ {-# OPTIONS_GHC -w #-} module DPM.Core.QueryParser (parseQuery, querySyntax) where import DPM.Core.DataTypes import DPM.Core.Lexer -- import Test.Framework } %name parse %tokentype { Token } %error { parseError } %monad { Maybe } %token '+' { TOr } ' ' { TAnd } '^' { TNot } ':' { TSpecial } '{' { TOpen } '}' { TClose } string { TString $$ } %% Query : Query '+' Query1 { QOr $1 $3 } | Query1 { $1 } Query1 : Query1 ' ' Query2 { QAnd $1 $3 } | Query2 { $1 } Query2 : '^' Query3 { QNot $2 } | Query3 { $1 } Query3 : '{' Query '}' { $2 } | ':' string { trySpecial $2 } | string { QPrim $1 } { querySyntax :: String querySyntax = unlines $ ["Query ::= Query ' + ' Query -- logical OR" ," | Query ' ' Query -- logical AND" ," | '^' Query -- logical NOT" ," | '{' Query '}' -- grouping" ," | ':' Special" ," | String" ,"" ,"Special is one of \"undecided\", \"rejected\", \"obsolete\", \"applied\"," ,"\"reviewed\", \"open\", or \"closed\", and String is an arbitrary sequence " ,"of non-whitespace characters not starting with '^', '{', '}', '+', or ':'."] parseError :: [Token] -> Maybe a parseError _ = Nothing trySpecial :: String -> Query trySpecial s = case s of "undecided" -> QState PatchStateUNDECIDED "rejected" -> QState (PatchStateDISCARDED ReasonRejected) "obsolete" -> QState (PatchStateDISCARDED ReasonObsolete) "applied" -> QState PatchStateAPPLIED "reviewed" -> QReviewed "open" -> QGroupState PatchGroupOpen "closed" -> QGroupState PatchGroupClosed _ -> QPrim s parseQuery :: String -> Maybe Query parseQuery = parse . scan -- FIXME: tests }