4632N/A{-# LANGUAGE TypeSynonymInstances #-}
4632N/ADescription : Parser for basic specs
4632N/ACopyright : (c) Dominik Dietrich, DFKI Bremen 2010
4632N/AMaintainer : dominik.dietrich@dfki.de
4632N/AParser for abstract syntax for CSL
4632N/A-- TODO: extract range information for the basic term and command types
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- * Interface to the syntax class
4632N/A-- ---------------------------------------------------------------------------
4632N/AparseBasicSpec = Just (const basicSpec)
4632N/AparseSymbItems :: Maybe (GenParser Char st SYMB_ITEMS)
4632N/AparseSymbItems = Just symbItems
4632N/AparseSymbMapItems :: Maybe (GenParser Char st SYMB_MAP_ITEMS)
4632N/AparseSymbMapItems = Just symbMapItems
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ---------------------------------------------------------------------------
4632N/AaddToPosition :: SourcePos -- ^ original position
4632N/A -> SourcePos -- ^ relative position
4632N/A -> SourcePos -- ^ new position
4632N/A setSourceColumn (setSourceLine sp1
4632N/AposInputParser :: a -> GenParser tok st (a, SourcePos, [tok], st)
4632N/Alet p1 = getState >>= many1 . string
4632N/ArunParser (string "h" >> runSubParser p1 "\n" "sourcename" >>= posInputParser) () "k" "h\n\nghurra"
4632N/ArunSubParser :: GenParser tok st a -> st -> SourceName
4632N/A -> GenParser tok st' (Either ParseError (st, a))
4632N/A case runParser (sp >>= posInputParser) st sn inp of
4632N/A Left err -> return $ Left err
4632N/A Right (x, pos', inp', st') -> do
4632N/A setPosition $ addToPosition pos pos'
4632N/A lookupOperator _ = lookupOperator ()
4632N/A lookupBinder _ = lookupBinder ()
4632N/Ainstance OperatorState a => OperatorState (OpVarState a) where
4632N/A lookupOperator (OpVarState x _) = lookupOperator x
4632N/A lookupBinder (OpVarState x _) = lookupBinder x
4632N/A-- call opvar-state-subparser on given state
4632N/ArunWithVars :: OperatorState a => [String] -> CharParser (OpVarState a) res
4632N/A Left err -> parseError $ unlines $ map messageString $ errorMessages err
4632N/AparseError :: String -> CharParser st a
4632N/ApComma :: CharParser st String
4632N/ApComma = lexemeParser $ string ","
4632N/ApSemi :: CharParser st String
4632N/ApSemi = lexemeParser $ string ";"
4632N/Alstring :: String -> CharParser st String
4632N/Alstring = lexemeParser . string
4632N/A-- | parser for symbols followed by whitechars
4632N/AlexemeParser :: CharParser st a -> CharParser st a
4632N/AgetOpName :: String -> [OPNAME] -> OPNAME
4632N/A where f (x : xs) = if s == show x then x else f xs
4632N/A f [] = error $ "getOpName: no op found for " ++ s ++ " in " ++ show l
4632N/AmkFromOps :: [OPNAME] -> String -> [EXPRESSION] -> EXPRESSION
4632N/AmkFromOps l s = mkPredefOp (getOpName s l)
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ---------------------------------------------------------------------------
4632N/A{- | parsing of identifiers. an identifier is a letter followed by
4632N/A letters, numbers, or _, but not a keyword -}
4632N/A-- | parses a possibly signed number to an EXPRESSION
4632N/AsignednumberExp :: CharParser st EXPRESSION
4632N/A let f (eN, rg) = either (flip Int rg) (flip Rat rg . readRat) eN
4632N/A-- | parses a possibly signed number (both integers and floats)
4632N/Asignednumber :: CharParser st (Either APInt String, Range)
4632N/A let f c x = return (c $ tokStr x, tokPos x)
4632N/A g x | isFloating x = f Right x
4632N/A | otherwise = f (Left . read) x
4632N/AreadRat :: String -> APFloat
4632N/AreadRat s = case readFloat fls of
4632N/A _ -> error $ "readRat: cannot read float " ++ s
4632N/A where withSgn x = if sgn then - x else x
4632N/A (sgn, fls) = case dropWhile isSpace s of
4632N/Awhich may start with ".". This one does it.
4632N/AThis version is still not compatible with -! -}
4632N/AkeySignNumCompat :: CharParser st a -> CharParser st a
4632N/AkeySignNumCompat = try . (<< notFollowedBy (oneOf signNumCompatChars))
4632N/AsignNumCompatChars :: String
4632N/AsignNumCompatChars = "!#$&*+-/:<=>?@\\^|~" ++
4632N/A "\161\162\163\167\169\172\176\177\178\179\181\182\183\185\191\215\247"
4632N/AoneOfKeys :: [String] -> CharParser st String
4632N/AoneOfKeys l = lexemeParser $ keySignNumCompat $ choice $ map tryString l
4632N/Aplusmin :: OperatorState st => CharParser st EXPRESSION
4632N/A let ops = [OP_plus, OP_minus]
4632N/A exps <- many $ pair (oneOfKeys $ map show ops) factor
4632N/A return $ if null exps then exp1
4632N/A else foldl (\ a b -> mkFromOps ops (fst b) [a, snd b]) exp1 exps
4632N/A-- | parse a product of basic expressions
4632N/Afactor :: OperatorState st => CharParser st EXPRESSION
4632N/A let ops = [OP_mult, OP_div]
4632N/A exps <- many $ pair (oneOfKeys $ map show ops) expexp
4632N/A return $ if null exps then exp1
4632N/A else foldl (\ a b -> mkFromOps ops (fst b) [a, snd b]) exp1 exps
4632N/A-- | parse a sequence of exponentiations
4632N/Aexpexp :: OperatorState st => CharParser st EXPRESSION
4632N/A exps <- many $ pair (oneOfKeys ["**", "^"]) expatom
4632N/A return $ if null exps then exp1
4632N/A else foldl (\ a b -> mkPredefOp OP_pow [a, snd b]) exp1 exps
4632N/A-- | parse a basic expression
4632N/Aexpatom :: OperatorState st => CharParser st EXPRESSION
4632N/Aexpatom = try signednumberExp <|> (oParenT >> plusmin << cParenT)
4632N/A <|> listexp <|> intervalexp <|> expsymbol
4632N/Aexpsymbol :: OperatorState st => CharParser st EXPRESSION
4632N/A ident <- prefixidentifier -- EXTENDED
4632N/A case mkAndAnalyzeOp' True st (tokStr ident) (fst ep) (fst exps)
4632N/A Left s -> parseError $ "expsymbol at op " ++ tokStr ident
4632N/A ++ show (fst exps) ++ ": " ++ s
4632N/Aopdecl :: OperatorState st => CharParser st OpDecl
4632N/A ident <- prefixidentifier -- EXTENDED
4632N/A let vdl = map (flip VarDecl Nothing) $ fst args
4632N/A return $ OpDecl (SimpleConstant $ tokStr ident) (fst ep) vdl $ tokPos ident
4632N/A-- | parses a list expression
4632N/Alistexp :: OperatorState st => CharParser st EXPRESSION
4632N/A keySignNumCompat $ string "{"
4632N/A keySignNumCompat $ string "}"
4632N/A return (List (fst elems) nullRange)
4632N/Aintervalexp :: CharParser st EXPRESSION
4632N/A let getFloat = either fromInteger readDbl
4632N/A [(x, rg1), (y, rg2)] -> return $ Interval (getFloat x) (getFloat y) $ Range
4632N/A $ joinRanges $ map rangeToList [rg1, rg2]
4632N/A "intervalexp: Parse error: interval with other than two arguments"
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ** parser for extended parameter,
e.g., [I=0,...]
4632N/A-- ---------------------------------------------------------------------------
4632N/Aextparam :: CharParser st EXTPARAM
4632N/A liftM2 (EP i) (oneOfKeys ["=", "<=", ">=", "!=", "<", ">", "-|"])
4632N/A >-> either id (error "extparam: floats not supported") . fst
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ---------------------------------------------------------------------------
4632N/AparseVarList :: CharParser st EXPRESSION
4632N/A return (List (fst elems) nullRange)
4632N/AparseVar :: CharParser st EXPRESSION
4632N/AquantFormula :: OperatorState st => OPNAME -> CharParser st EXPRESSION
4632N/A -- TODO: static analysis requires probably a better representation of quantifiers
4632N/A vars <- parseVar <|> parseVarList
4632N/A expr <- formulaorexpression
4632N/A return (mkPredefOp q [vars, expr])
4632N/AtruefalseFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A return (mkPredefOp OP_true [])
4632N/A return (mkPredefOp OP_false [])
4632N/A <|> quantFormula OP_ex <|> quantFormula OP_all
4632N/ApredFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A let ops = [ OP_leq, OP_geq, OP_neq, OP_eq, OP_lt, OP_gt ]
4632N/A $ pair (oneOfKeys (map show $ take 3 ops) -- the first 3 print as 2-chars
4632N/A <|> lexemeParser (single $ oneOf "=<>")) plusmin
4632N/A Just (op, exp2) -> return $ mkFromOps ops op [exp1, exp2]
4632N/AatomicFormula :: OperatorState st => CharParser st EXPRESSION
4632N/AatomicFormula = truefalseFormula <|> predFormula <|> parenFormula
4632N/AaFormula :: OperatorState st => CharParser st EXPRESSION
4632N/AaFormula = try negFormula <|> impOrFormula
4632N/AnegFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A return (mkPredefOp OP_not [f])
4632N/A-- | parses a formula within brackets
4632N/AparenFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A-- | parser for implications and ors (same precedence)
4632N/AimpOrFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A let ops = [ OP_or, OP_impl ]
4632N/A $ tryString (show OP_or) <|> tryString (show OP_impl))
4632N/A return $ if null opfs then f1
4632N/A else foldl (\ a (op, b) -> mkFromOps ops op [a, b]) f1 opfs
4632N/A-- | a parser for and sequence of and formulas
4632N/AandFormula :: OperatorState st => CharParser st EXPRESSION
4632N/A opfs <- many $ pair (lexemeParser $ keyWord $ tryString $ show OP_and)
4632N/A return $ if null opfs then f1
4632N/A else foldl (\ b a -> (mkPredefOp OP_and [b, snd a])) f1 opfs
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ---------------------------------------------------------------------------
4632N/Aformulaorexpression :: OperatorState st => CharParser st EXPRESSION
4632N/Aformulaorexpression = try aFormula <|> plusmin
4632N/Acommand = reduceCommand <|> try assignment <|> repeatExpr <|> caseExpr
4632N/A <|> sequenceExpr <|> constraint
4632N/AreduceCommand :: OperatorState st => CharParser st CMD
4632N/A ["solve", "simplify", "divide", "int", "rlqe", "factorize", "print"]
4632N/A arg1 <- formulaorexpression
4632N/A args <- many $ pComma >> formulaorexpression
4632N/A return $ Cmd cmd $ arg1 : args
4632N/Aassignment :: OperatorState st => CharParser st CMD
4632N/A ident@(OpDecl _ _ vdl _) <- opdecl
4632N/A lexemeParser $ choice [tryString ":=", tryString "="]
4632N/A exp' <- runWithVars (map varDeclName vdl) plusmin
4632N/Aconstraint :: OperatorState st => CharParser st CMD
4632N/A return $ Cmd "constraint" [exp']
4632N/A _ -> fail "Malformed constraint"
4632N/A let p1 = lstring "else" >> return (mkPredefOp OP_true [])
4632N/A cond <- choice [try p1, aFormula]
4632N/AcaseExpr = many1 singleCase >-> Cond << lstring "end"
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- | parser for operator declarations: example: operator a,b,c
4632N/AopItem :: CharParser st OP_ITEM
4632N/A vars <- sepBy1 identifier pComma
4632N/A return $ Op_item vars nullRange
4632N/A-- | Parser for variable declarations: example: vars x,y in {1,2}; z in [-1,1]
4632N/AvarItems :: CharParser st [VAR_ITEM]
4632N/AvarItems = oneOfKeys ["vars", "var"] >> sepBy1 varItem pSemi
4632N/A-- | Parser for a variable declaration: example: vars x,y in {1,2}
4632N/AvarItem :: CharParser st VAR_ITEM
4632N/A vars <- sepBy1 identifier pComma
4632N/A return $ Var_item vars dom nullRange
4632N/A{- | Parser for extended parameter declarations:
4632N/A{- | Parser for extended parameter default values and domain variable
4632N/Adeclarations: example: I = 1; n=2 -}
4632N/A getSignedNumber >-> (,) epId . read
4632N/AparseDomain :: CharParser st Domain
4632N/A lp <- lexemeParser $ oneOf "{[]"
4632N/A gcl <- sepBy1 (signednumber >-> either GCI (GCR . readRat) . fst) pComma
4632N/A rp <- lexemeParser $ oneOf "[]}"
4632N/A [lb, rb] -> return $ IntVal (lb, o) (rb, c)
4632N/A _ -> parseError "parseDomain: incorrect interval-list"
4632N/A _ -> parseError "parseDomain: malformed domain parens"
4632N/AparseEPVal :: CharParser st EPVal
4632N/A mId <- optionMaybe identifier
4632N/A Just n -> return $ EPConstRef n
4632N/A _ -> getSignedNumber >-> EPVal . read
4632N/AparseEPDomain :: CharParser st EPDomain
4632N/A return $ ClosedInterval l r
4632N/A-- | Toplevel parser for basic specs
4632N/AparseBasicItems = parseOpDecl <|> parseVarDecl <|> parseEPDefValOrDomDecl
4632N/A <|> parseEPDecl <|> parseAxItems
4632N/A-- | parser for operator declarations
4632N/AparseOpDecl = opItem >-> Op_decl
4632N/A-- | parser for variable declarations
4632N/AparseVarDecl = varItems >-> Var_decls
4632N/A{- | parser for extended parameter declarations, one of:
4632N/Adefault value for an extended parameter (I=2)
4632N/Aa domain variable declaration (n=10) -}
4632N/A mDef <- optionMaybe $ try $ lexemeParser $ string "default"
4632N/A Nothing -> sepBy1 epNumValAss pSemi >-> EP_domdecl
4632N/A _ -> sepBy1 epNumValAss pSemi >-> EP_defval
4632N/A-- | parser for extended parameter declarations
4632N/AparseEPDecl = oneOfKeys ["eps", "ep"] >> sepBy1 epDecl pSemi >-> EP_decl
4632N/A-- ---------------------------------------------------------------------------
4632N/A-- * parser for symbol maps etc.
4632N/A-- ---------------------------------------------------------------------------
4632N/Asymb :: GenParser Char st SYMB
4632N/Asymb = identifier >-> Symb_id
4632N/A-- | parsing one symbol or a mapping of one to a second symbol
4632N/AsymbMap :: GenParser Char st SYMB_OR_MAP
4632N/A do f <- pToken $ toKey mapsTo
4632N/A return (Symb_map s t $ tokPos f)
4632N/A-- | Parse a list of comma separated symbols.
4632N/AsymbItems :: GenParser Char st SYMB_ITEMS
4632N/A return (Symb_items is $ catRange ps)
4632N/A-- | parse a comma separated list of symbols
4632N/Asymbs :: GenParser Char st ([SYMB], [Token])
4632N/A do c <- commaT `followedWith` symb
4632N/A-- | parse a list of symbol mappings
4632N/AsymbMapItems :: GenParser Char st SYMB_MAP_ITEMS
4632N/A return (Symb_map_items is $ catRange ps)
4632N/A-- | parse a comma separated list of symbol mappings
4632N/AsymbMaps :: GenParser Char st ([SYMB_OR_MAP], [Token])
4632N/A do c <- commaT `followedWith` symb
4632N/AparseCommand :: String -> Maybe CMD
4632N/AparseExpression :: OperatorState a => a -> String -> Maybe EXPRESSION
4632N/A case runParser formulaorexpression st "" inp of