Use Parsec to parse #DEFINE directives.
This is much neater, and I'll need most of the code to implement comparisons anyway.
This commit is contained in:
parent
6d4f1dd702
commit
a5fd73130a
|
@ -189,25 +189,12 @@ handleUse m [modName]
|
||||||
-- | Handle the @#DEFINE@ directive.
|
-- | Handle the @#DEFINE@ directive.
|
||||||
handleDefine :: DirectiveFunc
|
handleDefine :: DirectiveFunc
|
||||||
handleDefine m [definition]
|
handleDefine m [definition]
|
||||||
= do (var, value) <- lookup definition definitionTypes
|
= do (var, value) <- runPreprocParser m defineDirective definition
|
||||||
st <- get
|
st <- get
|
||||||
when (Map.member var $ csDefinitions st) $
|
when (Map.member var $ csDefinitions st) $
|
||||||
dieP m $ "Preprocessor symbol is already defined: " ++ var
|
dieP m $ "Preprocessor symbol is already defined: " ++ var
|
||||||
put $ st { csDefinitions = Map.insert var value $ csDefinitions st }
|
put $ st { csDefinitions = Map.insert var value $ csDefinitions st }
|
||||||
return (return, id)
|
return (return, id)
|
||||||
where
|
|
||||||
definitionTypes :: [(Regex, [String] -> (String, PreprocDef))]
|
|
||||||
definitionTypes =
|
|
||||||
[ (mkRegex "^([^ ]+)$", (\[name] -> (name, PreprocNothing)))
|
|
||||||
, (mkRegex "^([^ ]+) +([0-9]+)$", (\[name, num] -> (name, PreprocInt num)))
|
|
||||||
, (mkRegex "^([^ ]+) \"(.*)\"$", (\[name, str] -> (name, PreprocString str)))
|
|
||||||
]
|
|
||||||
|
|
||||||
lookup s [] = dieP m "Invalid definition syntax"
|
|
||||||
lookup s ((re, func):ds)
|
|
||||||
= case matchRegex re s of
|
|
||||||
Just fields -> return $ func fields
|
|
||||||
Nothing -> lookup s ds
|
|
||||||
|
|
||||||
-- | Handle the @#UNDEF@ directive.
|
-- | Handle the @#UNDEF@ directive.
|
||||||
handleUndef :: DirectiveFunc
|
handleUndef :: DirectiveFunc
|
||||||
|
@ -218,7 +205,7 @@ handleUndef m [var]
|
||||||
-- | Handle the @#IF@ directive.
|
-- | Handle the @#IF@ directive.
|
||||||
handleIf :: DirectiveFunc
|
handleIf :: DirectiveFunc
|
||||||
handleIf m [condition]
|
handleIf m [condition]
|
||||||
= do b <- evalExpression m condition
|
= do b <- runPreprocParser m expression condition
|
||||||
return (skipCondition b 0, id)
|
return (skipCondition b 0, id)
|
||||||
where
|
where
|
||||||
skipCondition :: Bool -> Int -> [Token] -> PassM [Token]
|
skipCondition :: Bool -> Int -> [Token] -> PassM [Token]
|
||||||
|
@ -255,6 +242,15 @@ ppLexer = P.makeTokenParser (haskellDef
|
||||||
, P.identLetter = letter <|> digit <|> char '.'
|
, P.identLetter = letter <|> digit <|> char '.'
|
||||||
})
|
})
|
||||||
|
|
||||||
|
lexeme :: PreprocParser a -> PreprocParser a
|
||||||
|
lexeme = P.lexeme ppLexer
|
||||||
|
|
||||||
|
whiteSpace :: PreprocParser ()
|
||||||
|
whiteSpace = P.whiteSpace ppLexer
|
||||||
|
|
||||||
|
identifier :: PreprocParser String
|
||||||
|
identifier = P.identifier ppLexer
|
||||||
|
|
||||||
parens :: PreprocParser a -> PreprocParser a
|
parens :: PreprocParser a -> PreprocParser a
|
||||||
parens = P.parens ppLexer
|
parens = P.parens ppLexer
|
||||||
|
|
||||||
|
@ -265,10 +261,25 @@ symbol = P.symbol ppLexer
|
||||||
tryVX :: PreprocParser a -> PreprocParser b -> PreprocParser a
|
tryVX :: PreprocParser a -> PreprocParser b -> PreprocParser a
|
||||||
tryVX a b = try (do { av <- a; b; return av })
|
tryVX a b = try (do { av <- a; b; return av })
|
||||||
|
|
||||||
|
literal :: PreprocParser PreprocDef
|
||||||
|
literal
|
||||||
|
= do { ds <- lexeme $ many1 digit; return $ PreprocInt ds }
|
||||||
|
<|> do { char '"'; s <- manyTill anyChar $ char '"'; return $ PreprocString s }
|
||||||
|
<?> "preprocessor literal"
|
||||||
|
|
||||||
|
defineDirective :: PreprocParser (String, PreprocDef)
|
||||||
|
defineDirective
|
||||||
|
= do whiteSpace
|
||||||
|
var <- identifier
|
||||||
|
value <- option PreprocNothing literal
|
||||||
|
eof
|
||||||
|
return (var, value)
|
||||||
|
<?> "preprocessor definition"
|
||||||
|
|
||||||
defined :: PreprocParser Bool
|
defined :: PreprocParser Bool
|
||||||
defined
|
defined
|
||||||
= do symbol "DEFINED"
|
= do symbol "DEFINED"
|
||||||
i <- parens $ P.identifier ppLexer
|
i <- parens identifier
|
||||||
definitions <- getState
|
definitions <- getState
|
||||||
return $ Map.member i definitions
|
return $ Map.member i definitions
|
||||||
|
|
||||||
|
@ -288,20 +299,19 @@ expression
|
||||||
<|> operand
|
<|> operand
|
||||||
<?> "preprocessor expression"
|
<?> "preprocessor expression"
|
||||||
|
|
||||||
fullExpression :: PreprocParser Bool
|
-- | Match a 'PreprocParser' production.
|
||||||
fullExpression
|
runPreprocParser :: Meta -> PreprocParser a -> String -> PassM a
|
||||||
= do P.whiteSpace ppLexer
|
runPreprocParser m prod s
|
||||||
e <- expression
|
|
||||||
eof
|
|
||||||
return e
|
|
||||||
|
|
||||||
-- | Evaluate a preprocessor expression.
|
|
||||||
evalExpression :: Meta -> String -> PassM Bool
|
|
||||||
evalExpression m s
|
|
||||||
= do st <- get
|
= do st <- get
|
||||||
case runParser fullExpression (csDefinitions st) (show m) s of
|
case runParser wrappedProd (csDefinitions st) (show m) s of
|
||||||
Left err -> dieP m $ "Error parsing expression: " ++ show err
|
Left err -> dieP m $ "Error parsing preprocessor instruction: " ++ show err
|
||||||
Right b -> return b
|
Right b -> return b
|
||||||
|
where
|
||||||
|
wrappedProd
|
||||||
|
= do whiteSpace
|
||||||
|
v <- prod
|
||||||
|
eof
|
||||||
|
return v
|
||||||
--}}}
|
--}}}
|
||||||
|
|
||||||
-- | Load and preprocess an occam program.
|
-- | Load and preprocess an occam program.
|
||||||
|
|
Loading…
Reference in New Issue
Block a user