packages feed

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

-----------------------------------------------------------------------------