-- | This is the input module accompanying the implementation of Dung's -- argumentation frameworks. It defines a simple parser for an argumentation framework -- that assumes the input file is in CEGARTIX/PrefSat-like format. -- -- Files are assumed to have one argument or attack on each line, ending -- in a dot. (Our parser is slightly more relaxed than this and doesn't care about whitespace.) -- -- @att(a1,a2).@ or @arg(a1).@ -- -- Argument names are assumed to consist only of letters and numbers. -- Arguments used in attacks should be declared separately as well. module Language.Dung.Input ( -- * Parsing functions parseAF, pAF ) where import Language.Dung.AF import Text.Parsec import Text.Parsec.String (Parser) import Text.Parsec.Char (char, string) import qualified Text.Parsec.Token as P import Text.Parsec.Language(haskellStyle) import Text.Parsec.Error(errorMessages, messageString) import Data.Either (partitionEithers) lexer :: P.TokenParser () lexer = P.makeTokenParser haskellStyle whiteSpace :: Parser () whiteSpace = P.whiteSpace lexer identifier :: Parser String identifier = P.identifier lexer stringLiteral :: Parser String stringLiteral = P.stringLiteral lexer -- |An argument name consists of one or more letters and digits -- or a string literal. argName :: Parser String argName = try identifier <|> stringLiteral -- |A complete argument consists of @arg(argName).@ pArgument :: Parser String pArgument = do string "arg(" arg <- argName string ")." whiteSpace return arg -- |A complete attack consists of @atk(argName,argName).@ -- or @att(argName,argName).@. pAttack :: Parser (String, String) pAttack = do string "at" string "t(" <|> string "k(" arg1 <- argName char ',' whiteSpace arg2 <- argName string ")." return (arg1, arg2) -- |Parses one attack or argument and returns the result -- in the 'Either' data type. pArgOrAttack :: Parser (Either String (String, String)) pArgOrAttack = try (do arg <- pArgument whiteSpace return $ Left arg) <|> do atk <- pAttack whiteSpace return $ Right atk -- |An AF is parsed by parsing at least one argument or attack, -- followed by an end of file token. pAF :: Parser (DungAF String) pAF = do ps <- many1 pArgOrAttack eof let (args, atks) = partitionEithers ps return $ AF args atks -- |Parses a 'String' containing multiple arguments/attacks. -- If parsing fails, it propagates the parse error. parseAF :: String -> Either ParseError (DungAF String) parseAF = parse pAF ""