HaRe-0.6: StrategyLib-4.0-beta/examples/joos-rule02/Parser.hs
{-----------------------------------------------------------------------------
This parser for JOOS is based on:
David A. Watt. JOOS action semantics. Version 1, available from
http://www.dcs.gla.ac.uk/~daw/publications/JOOS.ps, October 1997.
Several small adaptations were made to parse more Java fragments:
- Identifiers may now contain underscores.
- method invocations of the form m(args) are now accepted, and
interpreted as this.m(args).
-----------------------------------------------------------------------------}
module Parser where
import ParseLib
import Datatypes
parseAssignment
= do i <- parseIdentifier
parseSymbol ":="
e <- parseExpression
return (Assignment i e)
parseInstanceCreation
= do parseSymbol "new"
i <- parseIdentifier
args <- bracket (parseSymbol "(") parseArguments (parseSymbol ")")
return (InstanceCreation i args)
parseMethodInvocation
= do e <- parseExpression
case e of
(MethodInvocationExpr mi) -> return mi
_ -> mzero
parseSuperMethodInvocation
= do parseSymbol "super"
parseSymbol "."
i <- parseIdentifier
args <- bracket (parseSymbol "(") parseArguments (parseSymbol ")")
return (SuperInvocation i args)
parseMethodInvocationRemainder e
= do parseSymbol "."
i <- parseIdentifier
parseSymbol "("
args <- parseArguments
parseSymbol ")"
return (ExpressionInvocation e i args)
+++
case e of
(Identifier i) -> do parseSymbol "("
args <- parseArguments
parseSymbol ")"
return (ExpressionInvocation This i args)
_ -> mzero
parseArguments
= fmap Arguments (sepby parseExpression (parseSymbol ","))
parseExpression
= do e <- parseExpression1
parseExpressionRemainder e
parseExpressionRemainder e
= do e' <- (fmap MethodInvocationExpr (parseMethodInvocationRemainder e))
+++
do op <- parseInfixOperator
e2 <- parseExpression
return (InfixExpr e op e2)
+++
do parseSymbol "instanceof"
i <- parseIdentifier
return (InstanceOf e i)
+++
do ao <- parseAndOr
e2 <- parseExpression
return (AndOrExpr e ao e2)
parseExpressionRemainder e'
+++
return e
parseExpression1
= fmap Literal parseLiteral
+++
fmap Identifier parseIdentifier
+++
do { parseSymbol "this"; return This }
+++
do op <- parsePrefixOperator
e <- parseExpression
return (PrefixExpr op e)
+++
do t <- bracket (parseSymbol "(") parseType (parseSymbol ")")
e <- parseExpression
return (TypeCast t e)
+++
do (bracket (parseSymbol "(") parseExpression (parseSymbol ")"))
+++
fmap AssignmentExpr parseAssignment
+++
fmap InstanceCreationExpr parseInstanceCreation
+++
fmap MethodInvocationExpr parseSuperMethodInvocation
parsePrefixOperator
= do { parseSymbol "-"; return Neg }
+++
do { parseSymbol "!"; return Fac }
parseInfixOperator
= symbols [("==",Eq),("!=",NEQ),("<",Lt),(">",Gt),("<=",LEQ),(">=",GEQ),
("+",PLUS),("-",MINUS),("*",MUL),("/",DIV),("%",MOD)]
parseAndOr
= do { parseSymbol "||"; return OR }
+++
do { parseSymbol "&&"; return AND }
parseLiteral
= fmap BooleanLit parseBooleanLiteral
+++
fmap IntegerLit parseIntegerLiteral
+++
do { parseSymbol "null"; return Null }
+++
fmap StringLit parseStringLiteral
parseBooleanLiteral
= do { parseSymbol "true"; return TRUE }
+++
do { parseSymbol "false"; return FALSE }
parseIntegerLiteral
= fmap toInteger natural
parseStringLiteral
= token (bracket (char '"') (many (sat (/='"') )) (char '"'))
parseIdentifier
= parse joosIdent
parseBlock
= do vds <- many parseVarDeclaration
ss <- many parseStatement
return (Block vds ss)
parseStatement
= parseStatementNoBlock
+++
fmap BlockStat ( bracket (parseSymbol "{")
parseBlock
(parseSymbol "}") )
parseStatementNoBlock
= symbols [(";",Skip)]
+++
do a <- parseAssignment
parseSymbol ";"
return (AssignmentStat a)
+++
do i <- parseInstanceCreation
parseSymbol ";"
return (InstanceCreationStat i)
+++
do m <- parseMethodInvocation
parseSymbol ";"
return (MethodInvocationStat m)
+++
do parseSymbol "return"
e <- optional parseExpression
parseSymbol ";"
return (ReturnStat e)
+++
do parseSymbol "if"
c <- bracket (parseSymbol "(") parseExpression (parseSymbol ")")
parseSymbol "then"
t <- parseStatement
parseSymbol "else"
e <- parseStatement
return (IfStat c t e)
+++
do parseSymbol "while"
c <- bracket (parseSymbol "(") parseExpression (parseSymbol ")")
s <- parseStatement
return (WhileStat c s)
+++
fmap StatementFocus ( bracket (parseSymbol "<")
parseStatement
(parseSymbol ">") )
parseClassDeclaration
= do parseSymbol "public"
f <- do { parseSymbol "final"; return True } +++ return False
parseSymbol "class"
cn <- parseIdentifier
parseSymbol "extends"
scn <- parseIdentifier
parseSymbol "{"
fds <- many parseFieldDeclaration
cd <- parseConstructorDeclaration
mds <- parseMethodDecls
parseSymbol "}"
return (ClassDecl f cn scn fds cd mds)
parseProgram
= do cds <- many parseClassDeclaration
bs <- parseBlock
return (Program cds bs)
parseFieldDeclaration
= do parseSymbol "private"
t <- parseType
i <- parseIdentifier
return (FieldDecl t i)
parseConstructorDeclaration
= do parseSymbol "public"
mn <- parseIdentifier
parseSymbol "("
pars <- parseFormals
parseSymbol ")"
parseSymbol "{"
parseSymbol "super"
args <- bracket (parseSymbol "(") parseArguments (parseSymbol ")")
body <- parseBlock
parseSymbol "}"
return (ConstructorDecl mn pars args body)
parseMethodDecls
=
do {
mds <- ( bracket (parseSymbol "<<")
(many1 parseMethodDecl)
(parseSymbol ">>") );
return [MethodDeclFocus mds]
}
+++
( many ( parseMethodDecl
+++
parseFocusedMethodDecl
)
)
parseFocusedMethodDecl
= do { parseSymbol "<";
md <- parseMethodDecl;
parseSymbol ">";
return (MethodDeclFocus [md])
}
parseMethodDecl
= do parseSymbol "public"
t <- ( do { parseSymbol "void"; return Nothing }
+++
fmap Just parseType )
mn <- parseIdentifier
parseSymbol "("
pars <- parseFormals
parseSymbol ")"
parseSymbol "{"
body <- parseBlock
parseSymbol "}"
return (MethodDecl t mn pars body)
parseFormals
= fmap Formals (sepby parseFormal (parseSymbol ","))
parseFormal
= do t <- parseType
i <- parseIdentifier
return (Formal t i)
parseVarDeclaration
= do t <- parseType
i <- parseIdentifier
parseSymbol ";"
return (VarDecl t i)
parseType
= do { parseSymbol "int"; return INT }
+++
do { parseSymbol "boolean"; return BOOLEAN }
+++
fmap Type parseIdentifier
--- Auxiliary ---------------------------------------------------------------
parseSymbol = parse . symbol
joosIdent :: Parser String
joosIdent = token (do{ i <- joos_ident; if not (elem i ks) then return i
else mzero })
where ks = ["new","super","this","instanceof","null",
"true","false","return","if","else","while",
"public","final","extends","private","int","boolean"]
joos_ident = do {x <- sat isJOOSalpha; xs <- many joos_alphanum; return (x:xs)}
where joos_alphanum = sat isJOOSalphanum
isJOOSalphanum c = isAlphaNum' c || (c=='_')
isJOOSalpha c = isAlpha' c || (c=='_')
symbols :: [(String,a)] -> Parser a
symbols ss
= foldr (\(sym,a) p -> do {parseSymbol sym; return a} +++ p ) mzero ss
optional p = fmap Just p +++ return Nothing
-- These are not present in all preludes.
-- Therefore, we repeat them with primed names.
isUpper' c = c >= 'A' && c <= 'Z'
isLower' c = c >= 'a' && c <= 'z'
isAlpha' c = isUpper' c || isLower' c
isDigit' c = c >= '0' && c <= '9'
isAlphaNum' c = isAlpha' c || isDigit' c
-----------------------------------------------------------------------------