-- | Parser for ECMAScript 3.
{-# LANGUAGE FlexibleContexts #-}
module Language.ECMAScript3.Parser
  (parse
  , Parser  
  , expression
  , statement
  , program
  , parseFromString
  , parseFromFile
  -- old and deprecated   
  , parseScriptFromString
  , parseJavaScriptFromFile
  , parseScript
  , parseExpression
  , parseString
  , ParsedStatement
  , ParsedExpression
  , parseSimpleExpr'
  , parseBlockStmt
  , parseStatement
  , StatementParser
  , ExpressionParser
  , assignExpr
  , parseObjectLit  
  ) where

import Language.ECMAScript3.Lexer hiding (identifier)
import qualified Language.ECMAScript3.Lexer as Lexer
import Language.ECMAScript3.Parser.State
import Language.ECMAScript3.Parser.Type
import Language.ECMAScript3.Syntax hiding (pushLabel)
import Language.ECMAScript3.Syntax.Annotations
import Data.Default.Class
import Text.Parsec hiding (parse)
import Text.Parsec.Expr
import Control.Monad(liftM,liftM2)
import Control.Monad.Trans (MonadIO,liftIO)
import Numeric(readDec,readOct,readHex, readFloat)
import Data.Char
import Control.Monad.Identity
import Data.Maybe (isJust, isNothing, fromMaybe)
import Control.Monad.Error.Class
import Control.Applicative ((<$>), (<*>))
import Control.Exception (throwIO)

{-# DEPRECATED ParsedStatement, ParsedExpression, StatementParser,
               ExpressionParser
    "These type aliases will be hidden in the next version" #-}

{-# DEPRECATED parseSimpleExpr', parseBlockStmt, parseObjectLit
   "These parsers will be hidden in the next version" #-}

{-# DEPRECATED assignExpr, parseExpression "Use 'expression' instead" #-}

{-# DEPRECATED parseStatement "Use 'statement' instead" #-}

{-# DEPRECATED parseScript "Use 'program' instead" #-}

{-# DEPRECATED parseScriptFromString, parseString "Use 'parseFromString' instead" #-}

{-# DEPRECATED parseJavaScriptFromFile "Use 'parseFromFile' instead" #-}

-- We parameterize the parse tree over source-locations.
type ParsedStatement = Statement SourcePos
type ParsedExpression = Expression SourcePos

-- These parsers can store some arbitrary state
type StatementParser s = Parser s ParsedStatement
type ExpressionParser s = Parser s ParsedExpression

initialParserState :: ParserState
initialParserState :: ParserState
initialParserState = []

-- | checks if the label is not yet on the stack, if it is -- throws
-- an error; otherwise it pushes it onto the stack
pushLabel :: String -> Parser s ()
pushLabel :: forall s. String -> Parser s ()
pushLabel String
lab = do labs <- ParsecT s ParserState Identity ParserState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
                   pos <- getPosition
                   if lab `elem` labs 
                     then fail $ "Duplicate label at " ++ show pos
                     else putState (lab:labs)

popLabel :: Parser s ()
popLabel :: forall s. Parser s ()
popLabel = (ParserState -> ParserState) -> ParsecT s ParserState Identity ()
forall (m :: * -> *) u s. Monad m => (u -> u) -> ParsecT s u m ()
modifyState ParserState -> ParserState
forall {a}. [a] -> [a]
safeTail
  where safeTail :: [a] -> [a]
safeTail [] = []
        safeTail (a
_:[a]
xs) = [a]
xs

clearLabels :: ParserState -> ParserState
clearLabels :: ParserState -> ParserState
clearLabels ParserState
_ = []

withFreshLabelStack :: Parser s a -> Parser s a
withFreshLabelStack :: forall s a. Parser s a -> Parser s a
withFreshLabelStack Parser s a
p = do oldState <- ParsecT s ParserState Identity ParserState
forall (m :: * -> *) s u. Monad m => ParsecT s u m u
getState
                           putState $ clearLabels oldState
                           a <- p
                           putState oldState
                           return a

identifier :: Stream s Identity Char => Parser s (Id SourcePos)
identifier :: forall s. Stream s Identity Char => Parser s (Id SourcePos)
identifier =
  (SourcePos -> String -> Id SourcePos)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity (Id SourcePos)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> String -> Id SourcePos
forall a. a -> String -> Id a
Id ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition ParsecT s ParserState Identity String
forall s. Stream s Identity Char => Parser s String
Lexer.identifier

--{{{ Statements

-- Keep in mind that Token.reserved parsers (exported from the lexer) do not
-- consume any input on failure.  Note that all statements (expect for labelled
-- and expression statements) begin with a reserved-word.  If we fail to parse
-- this reserved-word, no input is consumed.  Hence, we can have the massive or
-- block that is parseExpression.  Note that if the reserved-word is parsed, it 
-- must be whatever statement the reserved-word indicates.  If we fail after the
-- reserved-word, we truly have a syntax error.  Since input has been consumed,
-- <|> will not try its alternate in parseExpression, and we will fail.

parseIfStmt:: Stream s Identity Char => StatementParser s 
parseIfStmt :: forall s. Stream s Identity Char => StatementParser s
parseIfStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "if"
  test <- parseParenExpr <?> "parenthesized test-expression in if statement"
  consequent <- parseStatement <?> "true-branch of if statement"
  optional semi -- TODO: in spec?
  ((do reserved "else"
       alternate <- parseStatement
       return $ IfStmt pos test consequent alternate)
   <|> return (IfSingleStmt pos test consequent))

parseSwitchStmt :: Stream s Identity Char => StatementParser s
parseSwitchStmt :: forall s. Stream s Identity Char => StatementParser s
parseSwitchStmt =
  let parseDefault :: ParsecT s ParserState Identity (CaseClause SourcePos)
parseDefault = do
        pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
        reserved "default"
        colon
        statements <- many parseStatement
        return (CaseDefault pos statements)
      parseCase :: ParsecT s ParserState Identity (CaseClause SourcePos)
parseCase = do
         pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
         reserved "case"
         condition <- parseListExpr
         colon
         actions <- many parseStatement
         return (CaseClause pos condition actions)
      isCaseDefault :: CaseClause a -> Bool
isCaseDefault (CaseDefault a
_ [Statement a]
_) = Bool
True   
      isCaseDefault CaseClause a
_                 = Bool
False
      checkClauses :: [CaseClause a] -> m ()
checkClauses [CaseClause a]
cs = case (CaseClause a -> Bool) -> [CaseClause a] -> [CaseClause a]
forall a. (a -> Bool) -> [a] -> [a]
filter CaseClause a -> Bool
forall {a}. CaseClause a -> Bool
isCaseDefault [CaseClause a]
cs of
        (CaseClause a
_:CaseClause a
c:[CaseClause a]
_) -> String -> m ()
forall a. String -> m a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> m ()) -> String -> m ()
forall a b. (a -> b) -> a -> b
$ String
"duplicate default clause in switch statement at " String -> String -> String
forall a. [a] -> [a] -> [a]
++
                          a -> String
forall a. Show a => a -> String
show (CaseClause a -> a
forall b. CaseClause b -> b
forall (a :: * -> *) b. HasAnnotation a => a b -> b
getAnnotation CaseClause a
c)
        [CaseClause a]
_ -> () -> m ()
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return ()                  
    in do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
          reserved "switch"
          test <- parseParenExpr
          clauses <- braces $ many $ parseDefault <|> parseCase
          checkClauses clauses
          return (SwitchStmt pos test clauses)

parseWhileStmt:: Stream s Identity Char => StatementParser s
parseWhileStmt :: forall s. Stream s Identity Char => StatementParser s
parseWhileStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "while"
  test <- parseParenExpr <?> "parenthesized test-expression in while loop"
  body <- parseStatement
  return (WhileStmt pos test body)

parseDoWhileStmt:: Stream s Identity Char => StatementParser s
parseDoWhileStmt :: forall s. Stream s Identity Char => StatementParser s
parseDoWhileStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "do"
  body <- parseStatement
  reserved "while" <?> "while at the end of a do block"
  test <- parseParenExpr <?> "parenthesized test-expression in do loop"
  optional semi
  return (DoWhileStmt pos body test)

parseContinueStmt:: Stream s Identity Char => StatementParser s
parseContinueStmt :: forall s. Stream s Identity Char => StatementParser s
parseContinueStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "continue"
  pos' <- getPosition
  -- Ensure that the identifier is on the same line as 'continue.'
  id <- if sourceLine pos == sourceLine pos'
        then liftM Just identifier <|> return Nothing
        else return Nothing
  optional semi
  return $ ContinueStmt pos id

parseBreakStmt:: Stream s Identity Char => StatementParser s
parseBreakStmt :: forall s. Stream s Identity Char => StatementParser s
parseBreakStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "break"
  pos' <- getPosition
  -- Ensure that the identifier is on the same line as 'break.'
  id <- if sourceLine pos == sourceLine pos'
        then liftM Just identifier <|> return Nothing
        else return Nothing
  optional semi           
  return $ BreakStmt pos id

parseBlockStmt:: Stream s Identity Char => StatementParser s
parseBlockStmt :: forall s. Stream s Identity Char => StatementParser s
parseBlockStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  statements <- braces (many parseStatement)
  return (BlockStmt pos statements)

parseEmptyStmt:: Stream s Identity Char => StatementParser s
parseEmptyStmt :: forall s. Stream s Identity Char => StatementParser s
parseEmptyStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  semi
  return (EmptyStmt pos)

parseLabelledStmt:: Stream s Identity Char => StatementParser s
parseLabelledStmt :: forall s. Stream s Identity Char => StatementParser s
parseLabelledStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  -- Lookahead for the colon.  If we don't see it, we are parsing an identifier
  -- for an expression statement.
  label <- try (do label <- identifier
                   colon
                   return label)
  pushLabel $ unId label
  statement <- parseStatement
  popLabel
  return (LabelledStmt pos label statement)

parseExpressionStmt:: Stream s Identity Char => StatementParser s
parseExpressionStmt :: forall s. Stream s Identity Char => StatementParser s
parseExpressionStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  expr <- parseExpression -- TODO: spec 12.4?
  optional semi
  return $ ExprStmt pos expr


parseForInStmt:: Stream s Identity Char => StatementParser s
parseForInStmt :: forall s. Stream s Identity Char => StatementParser s
parseForInStmt =
  let parseInit :: ParsecT s ParserState Identity (ForInInit SourcePos)
parseInit = (String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reserved String
"var" Parser s ()
-> ParsecT s ParserState Identity (ForInInit SourcePos)
-> ParsecT s ParserState Identity (ForInInit SourcePos)
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (Id SourcePos -> ForInInit SourcePos)
-> ParsecT s ParserState Identity (Id SourcePos)
-> ParsecT s ParserState Identity (ForInInit SourcePos)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM Id SourcePos -> ForInInit SourcePos
forall a. Id a -> ForInInit a
ForInVar ParsecT s ParserState Identity (Id SourcePos)
forall s. Stream s Identity Char => Parser s (Id SourcePos)
identifier)
               ParsecT s ParserState Identity (ForInInit SourcePos)
-> ParsecT s ParserState Identity (ForInInit SourcePos)
-> ParsecT s ParserState Identity (ForInInit SourcePos)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (LValue SourcePos -> ForInInit SourcePos)
-> ParsecT s ParserState Identity (LValue SourcePos)
-> ParsecT s ParserState Identity (ForInInit SourcePos)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM LValue SourcePos -> ForInInit SourcePos
forall a. LValue a -> ForInInit a
ForInLVal ParsecT s ParserState Identity (LValue SourcePos)
forall s. Stream s Identity Char => Parser s (LValue SourcePos)
lvalue
  in do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
        -- Lookahead, so that we don't clash with parseForStmt
        (init,expr) <- try $ do reserved "for"
                                parens $ do init <- parseInit
                                            reserved "in"
                                            expr <- parseExpression
                                            return (init,expr)
        body <- parseStatement
        return $ ForInStmt pos init expr body

parseForStmt:: Stream s Identity Char => StatementParser s
parseForStmt :: forall s. Stream s Identity Char => StatementParser s
parseForStmt =
  let parseInit :: ParsecT s ParserState Identity (ForInit SourcePos)
parseInit = (String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reserved String
"var" Parser s ()
-> ParsecT s ParserState Identity (ForInit SourcePos)
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ([VarDecl SourcePos] -> ForInit SourcePos)
-> ParsecT s ParserState Identity [VarDecl SourcePos]
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM [VarDecl SourcePos] -> ForInit SourcePos
forall a. [VarDecl a] -> ForInit a
VarInit (Parser s (VarDecl SourcePos)
forall s. Stream s Identity Char => Parser s (VarDecl SourcePos)
parseVarDecl Parser s (VarDecl SourcePos)
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity [VarDecl SourcePos]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy` ParsecT s ParserState Identity String
forall s. Stream s Identity Char => Parser s String
comma))
               ParsecT s ParserState Identity (ForInit SourcePos)
-> ParsecT s ParserState Identity (ForInit SourcePos)
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (ParsedExpression -> ForInit SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM ParsedExpression -> ForInit SourcePos
forall a. Expression a -> ForInit a
ExprInit ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseListExpr
               ParsecT s ParserState Identity (ForInit SourcePos)
-> ParsecT s ParserState Identity (ForInit SourcePos)
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ForInit SourcePos
-> ParsecT s ParserState Identity (ForInit SourcePos)
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ForInit SourcePos
forall a. ForInit a
NoInit
    in do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
          reserved "for"
          reservedOp "("
          init <- parseInit
          semi
          test <- optionMaybe parseExpression
          semi
          iter <- optionMaybe parseExpression
          reservedOp ")" <?> "closing paren"
          stmt <- parseStatement
          return $ ForStmt pos init test iter stmt

parseTryStmt:: Stream s Identity Char => StatementParser s
parseTryStmt :: forall s. Stream s Identity Char => StatementParser s
parseTryStmt =
  let parseCatchClause :: ParsecT s ParserState Identity (CatchClause SourcePos)
parseCatchClause = do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
                            reserved "catch"
                            id <- parens identifier
                            stmt <- parseStatement
                            return $ CatchClause pos id stmt
  in do String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reserved String
"try"
        pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
        guarded <- parseStatement
        mCatch <- optionMaybe parseCatchClause
        mFinally <- optionMaybe $ reserved "finally" >> parseStatement
        -- the spec requires at least a catch or a finally block to
        -- be present
        if isJust mCatch || isJust mFinally 
          then return $ TryStmt pos guarded mCatch mFinally
          else fail $ "A try statement should have at least a catch\ 
                      \ or a finally block, at " ++ show pos

parseThrowStmt:: Stream s Identity Char => StatementParser s
parseThrowStmt :: forall s. Stream s Identity Char => StatementParser s
parseThrowStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "throw"
  expr <- parseExpression
  optional semi
  return (ThrowStmt pos expr)

parseReturnStmt:: Stream s Identity Char => StatementParser s
parseReturnStmt :: forall s. Stream s Identity Char => StatementParser s
parseReturnStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "return"
  expr <- optionMaybe parseListExpr
  optional semi
  return (ReturnStmt pos expr)

parseWithStmt:: Stream s Identity Char => StatementParser s
parseWithStmt :: forall s. Stream s Identity Char => StatementParser s
parseWithStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "with"
  context <- parseParenExpr
  stmt <- parseStatement
  return (WithStmt pos context stmt)

parseVarDecl :: Stream s Identity Char => Parser s (VarDecl SourcePos) 
parseVarDecl :: forall s. Stream s Identity Char => Parser s (VarDecl SourcePos)
parseVarDecl = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  id <- identifier
  init <- (reservedOp "=" >> liftM Just assignExpr) <|> return Nothing
  return (VarDecl pos id init)

parseVarDeclStmt:: Stream s Identity Char => StatementParser s
parseVarDeclStmt :: forall s. Stream s Identity Char => StatementParser s
parseVarDeclStmt = do 
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "var"
  decls <- parseVarDecl `sepBy` comma
  optional semi
  return (VarDeclStmt pos decls)

parseFunctionStmt:: Stream s Identity Char => StatementParser s
parseFunctionStmt :: forall s. Stream s Identity Char => StatementParser s
parseFunctionStmt = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  name <- try (reserved "function" >> identifier) -- ambiguity with FuncExpr
  args <- parens (identifier `sepBy` comma)
  -- label sets don't cross function boundaries
  BlockStmt _ body <- withFreshLabelStack parseBlockStmt <?> 
                      "function body in { ... }"
  return (FunctionStmt pos name args body)

parseStatement :: Stream s Identity Char => StatementParser s
parseStatement :: forall s. Stream s Identity Char => StatementParser s
parseStatement = StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseIfStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseSwitchStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseWhileStmt 
  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseDoWhileStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseContinueStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseBreakStmt 
  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseBlockStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseEmptyStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseForInStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseForStmt
  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseTryStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseThrowStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseReturnStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseWithStmt 
  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseVarDeclStmt  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseFunctionStmt
  -- labelled, expression and the error message always go last, in this order
  StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseLabelledStmt StatementParser s -> StatementParser s -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseExpressionStmt StatementParser s -> String -> StatementParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"statement"

-- | The parser that parses a single ECMAScript statement
statement :: Stream s Identity Char => Parser s (Statement SourcePos)
statement :: forall s. Stream s Identity Char => StatementParser s
statement = StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseStatement

--}}}

--{{{ Expressions

-- References used to construct this stuff:
-- + http://developer.mozilla.org/en/docs/
--     Core_JavaScript_1.5_Reference:Operators:Operator_Precedence
-- + http://www.mozilla.org/js/language/grammar14.html
--
-- Aren't expression tables nice?  Well, we can't quite use them, because of 
-- JavaScript's ternary (?:) operator.  We have to use two expression tables.
-- We use one expression table for the assignment operators that bind looser 
-- than ?: (assignTable).  The terms of assignTable are ternary expressions 
-- (parseTernaryExpr).  parseTernaryExpr left-factors the left-recursive
-- production for ?:, and is defined over the second expression table, 
-- exprTable, which consists of operators that bind tighter than ?:.  The terms
-- of exprTable are atomic expressions, parenthesized expressions, functions and
-- array references.

--{{{ Primary expressions

parseThisRef:: Stream s Identity Char => ExpressionParser s
parseThisRef :: forall s. Stream s Identity Char => ExpressionParser s
parseThisRef = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "this"
  return (ThisRef pos)

parseNullLit:: Stream s Identity Char => ExpressionParser s
parseNullLit :: forall s. Stream s Identity Char => ExpressionParser s
parseNullLit = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "null"
  return (NullLit pos)


parseBoolLit:: Stream s Identity Char => ExpressionParser s
parseBoolLit :: forall s. Stream s Identity Char => ExpressionParser s
parseBoolLit = do
    pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
    let parseTrueLit  = String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reserved String
"true"  Parser s ()
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SourcePos -> Bool -> ParsedExpression
forall a. a -> Bool -> Expression a
BoolLit SourcePos
pos Bool
True)
        parseFalseLit = String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reserved String
"false" Parser s ()
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SourcePos -> Bool -> ParsedExpression
forall a. a -> Bool -> Expression a
BoolLit SourcePos
pos Bool
False)
    parseTrueLit <|> parseFalseLit

parseVarRef:: Stream s Identity Char => ExpressionParser s
parseVarRef :: forall s. Stream s Identity Char => ExpressionParser s
parseVarRef = (SourcePos -> Id SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity (Id SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> Id SourcePos -> ParsedExpression
forall a. a -> Id a -> Expression a
VarRef ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition ParsecT s ParserState Identity (Id SourcePos)
forall s. Stream s Identity Char => Parser s (Id SourcePos)
identifier

parseArrayLit:: Stream s Identity Char => ExpressionParser s
parseArrayLit :: forall s. Stream s Identity Char => ExpressionParser s
parseArrayLit = (SourcePos -> [ParsedExpression] -> ParsedExpression)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity [ParsedExpression]
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> [ParsedExpression] -> ParsedExpression
forall a. a -> [Expression a] -> Expression a
ArrayLit ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition (ParsecT s ParserState Identity [ParsedExpression]
-> ParsecT s ParserState Identity [ParsedExpression]
forall s a. Stream s Identity Char => Parser s a -> Parser s a
squares (ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
assignExpr ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity [ParsedExpression]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepEndBy` ParsecT s ParserState Identity String
forall s. Stream s Identity Char => Parser s String
comma))

parseFuncExpr :: Stream s Identity Char => ExpressionParser s
parseFuncExpr :: forall s. Stream s Identity Char => ExpressionParser s
parseFuncExpr = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  reserved "function"
  name <- optionMaybe identifier
  args <- parens (identifier `sepBy` comma)
  -- labels don't cross function boundaries
  BlockStmt _ body <- withFreshLabelStack parseBlockStmt
  return $ FuncExpr pos name args body

--{{{ parsing strings

escapeChars :: [(Char, Char)]
escapeChars =
 [(Char
'\'',Char
'\''),(Char
'\"',Char
'\"'),(Char
'\\',Char
'\\'),(Char
'b',Char
'\b'),(Char
'f',Char
'\f'),(Char
'n',Char
'\n'),
  (Char
'r',Char
'\r'),(Char
't',Char
'\t'),(Char
'v',Char
'\v'),(Char
'/',Char
'/'),(Char
' ',Char
' '),(Char
'0',Char
'\0')]

allEscapes:: String
allEscapes :: String
allEscapes = ((Char, Char) -> Char) -> [(Char, Char)] -> String
forall a b. (a -> b) -> [a] -> [b]
map (Char, Char) -> Char
forall a b. (a, b) -> a
fst [(Char, Char)]
escapeChars

parseEscapeChar :: Stream s Identity Char => Parser s Char
parseEscapeChar :: forall s. Stream s Identity Char => Parser s Char
parseEscapeChar = do
  c <- String -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
allEscapes
  let (Just c') = lookup c escapeChars -- will succeed due to line above
  return c' 

parseAsciiHexChar :: Stream s Identity Char => Parser s Char
parseAsciiHexChar :: forall s. Stream s Identity Char => Parser s Char
parseAsciiHexChar = do
  Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'x'
  d1 <- ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
hexDigit
  d2 <- hexDigit
  return ((chr.fst.head.readHex) (d1:d2:""))

parseUnicodeHexChar :: Stream s Identity Char => Parser s Char
parseUnicodeHexChar :: forall s. Stream s Identity Char => Parser s Char
parseUnicodeHexChar = do
  Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'u'
  (String -> Char)
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity Char
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (Line -> Char
chr(Line -> Char) -> (String -> Line) -> String -> Char
forall b c a. (b -> c) -> (a -> b) -> a -> c
.(Line, String) -> Line
forall a b. (a, b) -> a
fst((Line, String) -> Line)
-> (String -> (Line, String)) -> String -> Line
forall b c a. (b -> c) -> (a -> b) -> a -> c
.[(Line, String)] -> (Line, String)
forall a. HasCallStack => [a] -> a
head([(Line, String)] -> (Line, String))
-> (String -> [(Line, String)]) -> String -> (Line, String)
forall b c a. (b -> c) -> (a -> b) -> a -> c
.String -> [(Line, String)]
forall a. (Eq a, Num a) => ReadS a
readHex) 
        ([ParsecT s ParserState Identity Char]
-> ParsecT s ParserState Identity String
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
forall (m :: * -> *) a. Monad m => [m a] -> m [a]
sequence [ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
hexDigit,ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
hexDigit,ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
hexDigit,ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
hexDigit])
        
isWhitespace :: Char -> Bool
isWhitespace Char
ch = Char
ch Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
" \t"


-- The endWith argument is either single-quote or double-quote, depending on how
-- we opened the string.
parseStringLit' :: Char -> ParsecT s ParserState Identity String
parseStringLit' Char
endWith =
  (Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
endWith ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT s ParserState Identity String
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return String
"") ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
  (do ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m a
try (String -> ParsecT s ParserState Identity String
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m String
string String
"\\'")
      cs <- Char -> ParsecT s ParserState Identity String
parseStringLit' Char
endWith
      return $ "'" ++ cs) ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
  (do Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\\'
      c <- ParsecT s ParserState Identity Char
forall s. Stream s Identity Char => Parser s Char
parseEscapeChar ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsecT s ParserState Identity Char
forall s. Stream s Identity Char => Parser s Char
parseAsciiHexChar ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsecT s ParserState Identity Char
forall s. Stream s Identity Char => Parser s Char
parseUnicodeHexChar ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> 
           Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\r' ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\n'
      cs <- parseStringLit' endWith
      if c == '\r' || c == '\n' 
        then return (c:dropWhile isWhitespace cs) 
        else return (c:cs)) ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
   (Char -> String -> String)
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity String
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (:) ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar (Char -> ParsecT s ParserState Identity String
parseStringLit' Char
endWith)

parseStringLit:: Stream s Identity Char => ExpressionParser s
parseStringLit :: forall s. Stream s Identity Char => ExpressionParser s
parseStringLit = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  -- parseStringLit' takes as an argument the quote-character that opened the
  -- string.
  str <- lexeme $ (char '\'' >>= parseStringLit') <|> (char '\"' >>= parseStringLit')
  -- CRUCIAL: Parsec.Token parsers expect to find their token on the first
  -- character, and read whitespaces beyond their tokens.  Without 'lexeme'
  -- above, expressions like:
  --   var s = "string"   ;
  -- do not parse.
  return $ StringLit pos str

--}}}

parseRegexpLit:: Stream s Identity Char => ExpressionParser s
parseRegexpLit :: forall s. Stream s Identity Char => ExpressionParser s
parseRegexpLit = do
  let parseFlags :: ParsecT s u Identity ((Bool -> Bool -> t) -> t)
parseFlags = do
        flags <- ParsecT s u Identity Char -> ParsecT s u Identity String
forall s u (m :: * -> *) a. ParsecT s u m a -> ParsecT s u m [a]
many (String -> ParsecT s u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
oneOf String
"mgi")
        return $ \Bool -> Bool -> t
f -> Bool -> Bool -> t
f (Char
'g' Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
flags) (Char
'i' Char -> String -> Bool
forall a. Eq a => a -> [a] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` String
flags) 
  let parseEscape :: Stream s Identity Char => Parser s Char
      parseEscape :: forall s. Stream s Identity Char => Parser s Char
parseEscape = Char -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\\' ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
-> ParsecT s ParserState Identity Char
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar
  let parseChar :: Stream s Identity Char => Parser s Char
      parseChar :: forall s. Stream s Identity Char => Parser s Char
parseChar = String -> ParsecT s ParserState Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
String -> ParsecT s u m Char
noneOf String
"/"
  let parseRe :: ParsecT s u Identity String
parseRe = (Char -> ParsecT s u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'/' ParsecT s u Identity Char
-> ParsecT s u Identity String -> ParsecT s u Identity String
forall a b.
ParsecT s u Identity a
-> ParsecT s u Identity b -> ParsecT s u Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> String -> ParsecT s u Identity String
forall a. a -> ParsecT s u Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return String
"") ParsecT s u Identity String
-> ParsecT s u Identity String -> ParsecT s u Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> 
                (do Char -> ParsecT s u Identity Char
forall s (m :: * -> *) u.
Stream s m Char =>
Char -> ParsecT s u m Char
char Char
'\\'
                    ch <- ParsecT s u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar -- TODO: too lenient
                    rest <- parseRe
                    return ('\\':ch:rest)) ParsecT s u Identity String
-> ParsecT s u Identity String -> ParsecT s u Identity String
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> 
                (Char -> String -> String)
-> ParsecT s u Identity Char
-> ParsecT s u Identity String
-> ParsecT s u Identity String
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (:) ParsecT s u Identity Char
forall s (m :: * -> *) u. Stream s m Char => ParsecT s u m Char
anyChar ParsecT s u Identity String
parseRe
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  char '/'
  notFollowedBy $ char '/'
  pat <- parseRe --many1 parseChar
  flags <- parseFlags
  spaces -- crucial for Parsec.Token parsers
  return $ flags (RegexpLit pos pat)
          
parseObjectLit:: Stream s Identity Char => ExpressionParser s
parseObjectLit :: forall s. Stream s Identity Char => ExpressionParser s
parseObjectLit =
  let parseProp :: ParsecT s ParserState Identity (Prop SourcePos, ParsedExpression)
parseProp = do
        -- Parses a string, identifier or integer as the property name.  I
        -- apologize for the abstruse style, but it really does make the code
        -- much shorter.
        name <- (ParsedExpression -> Prop SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity (Prop SourcePos)
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (\(StringLit SourcePos
p String
s) -> SourcePos -> String -> Prop SourcePos
forall a. a -> String -> Prop a
PropString SourcePos
p String
s) ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseStringLit
            ParsecT s ParserState Identity (Prop SourcePos)
-> ParsecT s ParserState Identity (Prop SourcePos)
-> ParsecT s ParserState Identity (Prop SourcePos)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (SourcePos -> Id SourcePos -> Prop SourcePos)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity (Id SourcePos)
-> ParsecT s ParserState Identity (Prop SourcePos)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> Id SourcePos -> Prop SourcePos
forall a. a -> Id a -> Prop a
PropId ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition ParsecT s ParserState Identity (Id SourcePos)
forall s. Stream s Identity Char => Parser s (Id SourcePos)
identifier
            ParsecT s ParserState Identity (Prop SourcePos)
-> ParsecT s ParserState Identity (Prop SourcePos)
-> ParsecT s ParserState Identity (Prop SourcePos)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> (SourcePos -> Integer -> Prop SourcePos)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity Integer
-> ParsecT s ParserState Identity (Prop SourcePos)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> Integer -> Prop SourcePos
forall a. a -> Integer -> Prop a
PropNum ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition (Parser s (Either Line Double)
forall s. Stream s Identity Char => Parser s (Either Line Double)
parseNumber Parser s (Either Line Double)
-> (Either Line Double -> ParsecT s ParserState Identity Integer)
-> ParsecT s ParserState Identity Integer
forall a b.
ParsecT s ParserState Identity a
-> (a -> ParsecT s ParserState Identity b)
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Either Line Double -> ParsecT s ParserState Identity Integer
forall {a} {s} {m :: * -> *} {t} {a} {b} {u}.
(Integral a, Stream s m t, Num a) =>
Either a b -> ParsecT s u m a
toInt)
        colon
        val <- assignExpr
        return (name,val)
      toInt :: Either a b -> ParsecT s u m a
toInt Either a b
eid = case Either a b
eid of
        Left a
i -> a -> ParsecT s u m a
forall a. a -> ParsecT s u m a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> ParsecT s u m a) -> a -> ParsecT s u m a
forall a b. (a -> b) -> a -> b
$ a -> a
forall a b. (Integral a, Num b) => a -> b
fromIntegral a
i
        -- Note, the spec actually allows floats in property names.
        -- This is left for legacy reasons and will be fixed in 1.0
        Right b
d-> String -> ParsecT s u m a
forall s (m :: * -> *) t u a.
Stream s m t =>
String -> ParsecT s u m a
unexpected String
"Floating point number in property name"
    in do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
          props <- braces (parseProp `sepEndBy` comma) <?> "object literal"
          return $ ObjectLit pos props

--{{{ Parsing numbers.  From pg. 17-18 of ECMA-262.
hex :: Stream s Identity Char => Parser s (Either Int Double)
hex :: forall s. Stream s Identity Char => Parser s (Either Line Double)
hex = do s <- Parser s String
forall s. Stream s Identity Char => Parser s String
hexIntLit
         Left <$> wrapReadS Numeric.readHex s

decimal :: Stream s Identity Char => Parser s (Either Int Double)
decimal :: forall s. Stream s Identity Char => Parser s (Either Line Double)
decimal = do (s, i) <- Parser s (String, Bool)
forall s. Stream s Identity Char => Parser s (String, Bool)
decLit
             if i then Left <$> wrapReadS readDec s
                  else Right <$> wrapReadS readFloat s

wrapReadS :: ReadS a -> String -> Parser s a
wrapReadS :: forall a s. ReadS a -> String -> Parser s a
wrapReadS ReadS a
r String
s = case ReadS a
r String
s of
  [(a
a, String
"")] -> a -> Parser s a
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return a
a
  [(a, String)]
_         -> String -> Parser s a
forall a. String -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail String
"Bad parse: could not convert a string to a Haskell value"

parseNumber:: Stream s Identity Char => Parser s (Either Int Double) 
parseNumber :: forall s. Stream s Identity Char => Parser s (Either Line Double)
parseNumber = Parser s (Either Line Double)
forall s. Stream s Identity Char => Parser s (Either Line Double)
hex Parser s (Either Line Double)
-> Parser s (Either Line Double) -> Parser s (Either Line Double)
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> Parser s (Either Line Double)
forall s. Stream s Identity Char => Parser s (Either Line Double)
decimal

parseNumLit:: Stream s Identity Char => ExpressionParser s
parseNumLit :: forall s. Stream s Identity Char => ExpressionParser s
parseNumLit = do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
                 eid <- lexeme $ parseNumber
                 notFollowedBy identifierStart <?> "whitespace"
                 return $ case eid of
                   Left Line
i -> SourcePos -> Line -> ParsedExpression
forall a. a -> Line -> Expression a
IntLit SourcePos
pos Line
i
                   Right Double
d-> SourcePos -> Double -> ParsedExpression
forall a. a -> Double -> Expression a
NumLit SourcePos
pos Double
d

------------------------------------------------------------------------------
-- Position Helper
------------------------------------------------------------------------------

withPos :: (SourcePos -> t -> b) -> ParsecT s u m t -> ParsecT s u m b
withPos SourcePos -> t -> b
cstr ParsecT s u m t
p = do { pos <- ParsecT s u m SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition; e <- p; return $ cstr pos e }

-------------------------------------------------------------------------------
-- Compound Expression Parsers
-------------------------------------------------------------------------------

dotRef :: ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
dotRef ParsedExpression
e = (String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"." Parser s ()
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (SourcePos -> Id SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity (Id SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall {m :: * -> *} {t} {b} {s} {u}.
Monad m =>
(SourcePos -> t -> b) -> ParsecT s u m t -> ParsecT s u m b
withPos SourcePos -> Id SourcePos -> ParsedExpression
cstr ParsecT s ParserState Identity (Id SourcePos)
forall s. Stream s Identity Char => Parser s (Id SourcePos)
identifier) ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"property.ref"
    where cstr :: SourcePos -> Id SourcePos -> ParsedExpression
cstr SourcePos
pos = SourcePos -> ParsedExpression -> Id SourcePos -> ParsedExpression
forall a. a -> Expression a -> Id a -> Expression a
DotRef SourcePos
pos ParsedExpression
e

funcApp :: ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
funcApp ParsedExpression
e = ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s a. Stream s Identity Char => Parser s a -> Parser s a
parens ((SourcePos -> [ParsedExpression] -> ParsedExpression)
-> ParsecT s ParserState Identity [ParsedExpression]
-> ParsecT s ParserState Identity ParsedExpression
forall {m :: * -> *} {t} {b} {s} {u}.
Monad m =>
(SourcePos -> t -> b) -> ParsecT s u m t -> ParsecT s u m b
withPos SourcePos -> [ParsedExpression] -> ParsedExpression
cstr (ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
assignExpr ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity [ParsedExpression]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy` ParsecT s ParserState Identity String
forall s. Stream s Identity Char => Parser s String
comma)) 
         ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?>String
"(function application)"
    where cstr :: SourcePos -> [ParsedExpression] -> ParsedExpression
cstr SourcePos
pos = SourcePos
-> ParsedExpression -> [ParsedExpression] -> ParsedExpression
forall a. a -> Expression a -> [Expression a] -> Expression a
CallExpr SourcePos
pos ParsedExpression
e

bracketRef :: ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
bracketRef ParsedExpression
e = ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s a. Stream s Identity Char => Parser s a -> Parser s a
brackets ((SourcePos -> ParsedExpression -> ParsedExpression)
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall {m :: * -> *} {t} {b} {s} {u}.
Monad m =>
(SourcePos -> t -> b) -> ParsecT s u m t -> ParsecT s u m b
withPos SourcePos -> ParsedExpression -> ParsedExpression
cstr ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseExpression) ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"[property-ref]"
    where cstr :: SourcePos -> ParsedExpression -> ParsedExpression
cstr SourcePos
pos = SourcePos
-> ParsedExpression -> ParsedExpression -> ParsedExpression
forall a. a -> Expression a -> Expression a -> Expression a
BracketRef SourcePos
pos ParsedExpression
e

-------------------------------------------------------------------------------
-- Expression Parsers
-------------------------------------------------------------------------------

parseParenExpr:: Stream s Identity Char => ExpressionParser s
parseParenExpr :: forall s. Stream s Identity Char => ExpressionParser s
parseParenExpr = Parser s ParsedExpression -> Parser s ParsedExpression
forall s a. Stream s Identity Char => Parser s a -> Parser s a
parens Parser s ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseListExpr

-- everything above expect functions
parseExprForNew :: Stream s Identity Char => ExpressionParser s
parseExprForNew :: forall s. Stream s Identity Char => ExpressionParser s
parseExprForNew = ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseThisRef ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseNullLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseBoolLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseStringLit 
  ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseArrayLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseParenExpr ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseNewExpr ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseNumLit 
  ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseRegexpLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseObjectLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseVarRef

-- all the expression parsers defined above
parseSimpleExpr' :: Stream s Identity Char => ExpressionParser s
parseSimpleExpr' :: forall s. Stream s Identity Char => ExpressionParser s
parseSimpleExpr' = ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseThisRef ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseNullLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseBoolLit 
  ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseStringLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseArrayLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseParenExpr
  ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseFuncExpr ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseNumLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseRegexpLit ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseObjectLit
  ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseVarRef

parseNewExpr :: Stream s Identity Char => ExpressionParser s
parseNewExpr :: forall s. Stream s Identity Char => ExpressionParser s
parseNewExpr =
  (do pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
      reserved "new"
      constructor <- parseSimpleExprForNew Nothing -- right-associativity
      arguments <- try (parens (assignExpr `sepBy` comma)) <|> return []
      return (NewExpr pos constructor arguments)) ExpressionParser s -> ExpressionParser s -> ExpressionParser s
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>
  ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseSimpleExpr'

parseSimpleExpr :: Maybe ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
parseSimpleExpr (Just ParsedExpression
e) = ((ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
dotRef ParsedExpression
e ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
funcApp ParsedExpression
e ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
bracketRef ParsedExpression
e) ParsecT s ParserState Identity ParsedExpression
-> (ParsedExpression
    -> ParsecT s ParserState Identity ParsedExpression)
-> ParsecT s ParserState Identity ParsedExpression
forall a b.
ParsecT s ParserState Identity a
-> (a -> ParsecT s ParserState Identity b)
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
                            Maybe ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
parseSimpleExpr (Maybe ParsedExpression
 -> ParsecT s ParserState Identity ParsedExpression)
-> (ParsedExpression -> Maybe ParsedExpression)
-> ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsedExpression -> Maybe ParsedExpression
forall a. a -> Maybe a
Just)  
                        ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ParsedExpression
e
parseSimpleExpr Maybe ParsedExpression
Nothing = do
  e <- ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseNewExpr ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"expression (3)"
  parseSimpleExpr (Just e)

parseSimpleExprForNew :: Stream s Identity Char
                      =>(Maybe ParsedExpression) -> ExpressionParser s
parseSimpleExprForNew :: forall s.
Stream s Identity Char =>
Maybe ParsedExpression -> ExpressionParser s
parseSimpleExprForNew (Just ParsedExpression
e) = ((ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
dotRef ParsedExpression
e ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
bracketRef ParsedExpression
e) ParsecT s ParserState Identity ParsedExpression
-> (ParsedExpression
    -> ParsecT s ParserState Identity ParsedExpression)
-> ParsecT s ParserState Identity ParsedExpression
forall a b.
ParsecT s ParserState Identity a
-> (a -> ParsecT s ParserState Identity b)
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>=
                                  Maybe ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s.
Stream s Identity Char =>
Maybe ParsedExpression -> ExpressionParser s
parseSimpleExprForNew (Maybe ParsedExpression
 -> ParsecT s ParserState Identity ParsedExpression)
-> (ParsedExpression -> Maybe ParsedExpression)
-> ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ParsedExpression -> Maybe ParsedExpression
forall a. a -> Maybe a
Just)
                              ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|> ParsedExpression -> ParsecT s ParserState Identity ParsedExpression
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ParsedExpression
e
parseSimpleExprForNew Maybe ParsedExpression
Nothing = do
  e <- ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parseNewExpr ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"expression (3)"
  parseSimpleExprForNew (Just e)
    
--}}}

makeInfixExpr :: String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
str InfixOp
constr = ParsecT
  s
  ParserState
  Identity
  (ParsedExpression -> ParsedExpression -> ParsedExpression)
-> Assoc -> Operator s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m (a -> a -> a) -> Assoc -> Operator s u m a
Infix ParsecT
  s
  ParserState
  Identity
  (ParsedExpression -> ParsedExpression -> ParsedExpression)
forall s.
Stream s Identity Char =>
Parser s (ParsedExpression -> ParsedExpression -> ParsedExpression)
parser Assoc
AssocLeft where
  parser:: Stream s Identity Char
        => Parser s (Expression SourcePos -> Expression SourcePos -> Expression SourcePos)
  parser :: forall s.
Stream s Identity Char =>
Parser s (ParsedExpression -> ParsedExpression -> ParsedExpression)
parser = do
    pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
    reservedOp str
    return (InfixExpr pos constr)  -- points-free, returns a function


-- apparently, expression tables can't handle immediately-nested prefixes
parsePrefixedExpr :: Stream s Identity Char => ExpressionParser s
parsePrefixedExpr :: forall s. Stream s Identity Char => ExpressionParser s
parsePrefixedExpr = do
  pos <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  op <- optionMaybe $ (reservedOp "!" >> return PrefixLNot) <|> 
                      (reservedOp "~" >> return PrefixBNot) <|>
                      (try (lexeme $ char '-' >> notFollowedBy (char '-')) >>
                       return PrefixMinus) <|>
                      (try (lexeme $ char '+' >> notFollowedBy (char '+')) >>
                       return PrefixPlus) <|>
                      (reserved "typeof" >> return PrefixTypeof) <|>
                      (reserved "void" >> return PrefixVoid) <|>
                      (reserved "delete" >> return PrefixDelete)
  case op of
    Maybe PrefixOp
Nothing -> ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
unaryAssignExpr
    Just PrefixOp
op -> do
      innerExpr <- ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parsePrefixedExpr
      return (PrefixExpr pos op innerExpr)

exprTable:: Stream s Identity Char => [[Operator s ParserState Identity ParsedExpression]]
exprTable :: forall s.
Stream s Identity Char =>
[[Operator s ParserState Identity ParsedExpression]]
exprTable = 
  [ [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"*" InfixOp
OpMul
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"/" InfixOp
OpDiv
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"%" InfixOp
OpMod
    ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"+" InfixOp
OpAdd
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"-" InfixOp
OpSub
    ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"<<" InfixOp
OpLShift
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
">>" InfixOp
OpSpRShift
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
">>>" InfixOp
OpZfRShift
    ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"<" InfixOp
OpLT
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"<=" InfixOp
OpLEq
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
">" InfixOp
OpGT
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
">=" InfixOp
OpGEq
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"instanceof" InfixOp
OpInstanceof
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"in" InfixOp
OpIn
    ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"==" InfixOp
OpEq
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"!=" InfixOp
OpNEq
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"===" InfixOp
OpStrictEq
    , String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"!==" InfixOp
OpStrictNEq
    ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"&" InfixOp
OpBAnd ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"^" InfixOp
OpBXor ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"|" InfixOp
OpBOr ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"&&" InfixOp
OpLAnd ]
  , [ String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
forall {s}.
Stream s Identity Char =>
String
-> InfixOp -> Operator s ParserState Identity ParsedExpression
makeInfixExpr String
"||" InfixOp
OpLOr ]
  ]

parseExpression' :: Stream s Identity Char => ExpressionParser s
parseExpression' :: forall s. Stream s Identity Char => ExpressionParser s
parseExpression' = 
  OperatorTable s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s (m :: * -> *) t u a.
Stream s m t =>
OperatorTable s u m a -> ParsecT s u m a -> ParsecT s u m a
buildExpressionParser OperatorTable s ParserState Identity ParsedExpression
forall s.
Stream s Identity Char =>
[[Operator s ParserState Identity ParsedExpression]]
exprTable ParsecT s ParserState Identity ParsedExpression
forall s. Stream s Identity Char => ExpressionParser s
parsePrefixedExpr ParsecT s ParserState Identity ParsedExpression
-> String -> ParsecT s ParserState Identity ParsedExpression
forall s u (m :: * -> *) a.
ParsecT s u m a -> String -> ParsecT s u m a
<?> String
"simple expression"

asLValue :: Stream s Identity Char
         => SourcePos
         -> Expression SourcePos 
         -> Parser s (LValue SourcePos)
asLValue :: forall s.
Stream s Identity Char =>
SourcePos -> ParsedExpression -> Parser s (LValue SourcePos)
asLValue SourcePos
p' ParsedExpression
e = case ParsedExpression
e of
  VarRef SourcePos
p (Id SourcePos
_ String
x) -> LValue SourcePos -> Parser s (LValue SourcePos)
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SourcePos -> String -> LValue SourcePos
forall a. a -> String -> LValue a
LVar SourcePos
p String
x)
  DotRef SourcePos
p ParsedExpression
e (Id SourcePos
_ String
x) -> LValue SourcePos -> Parser s (LValue SourcePos)
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SourcePos -> ParsedExpression -> String -> LValue SourcePos
forall a. a -> Expression a -> String -> LValue a
LDot SourcePos
p ParsedExpression
e String
x)
  BracketRef SourcePos
p ParsedExpression
e1 ParsedExpression
e2 -> LValue SourcePos -> Parser s (LValue SourcePos)
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return (SourcePos
-> ParsedExpression -> ParsedExpression -> LValue SourcePos
forall a. a -> Expression a -> Expression a -> LValue a
LBracket SourcePos
p ParsedExpression
e1 ParsedExpression
e2)
  ParsedExpression
otherwise -> String -> Parser s (LValue SourcePos)
forall a. String -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. MonadFail m => String -> m a
fail (String -> Parser s (LValue SourcePos))
-> String -> Parser s (LValue SourcePos)
forall a b. (a -> b) -> a -> b
$ String
"expected a left-value at " String -> String -> String
forall a. [a] -> [a] -> [a]
++ SourcePos -> String
forall a. Show a => a -> String
show SourcePos
p'

lvalue :: Stream s Identity Char => Parser s (LValue SourcePos)
lvalue :: forall s. Stream s Identity Char => Parser s (LValue SourcePos)
lvalue = do
  p <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  e <- parseSimpleExpr Nothing
  asLValue p e

unaryAssignExpr :: Stream s Identity Char => ExpressionParser s
unaryAssignExpr :: forall s. Stream s Identity Char => ExpressionParser s
unaryAssignExpr = do
  p <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  let prefixInc = do
        String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"++"
        (LValue SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity (LValue SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SourcePos -> UnaryAssignOp -> LValue SourcePos -> ParsedExpression
forall a. a -> UnaryAssignOp -> LValue a -> Expression a
UnaryAssignExpr SourcePos
p UnaryAssignOp
PrefixInc) ParsecT s ParserState Identity (LValue SourcePos)
forall s. Stream s Identity Char => Parser s (LValue SourcePos)
lvalue
  let prefixDec = do
        String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"--"
        (LValue SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity (LValue SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SourcePos -> UnaryAssignOp -> LValue SourcePos -> ParsedExpression
forall a. a -> UnaryAssignOp -> LValue a -> Expression a
UnaryAssignExpr SourcePos
p UnaryAssignOp
PrefixDec) ParsecT s ParserState Identity (LValue SourcePos)
forall s. Stream s Identity Char => Parser s (LValue SourcePos)
lvalue
  let postfixInc ParsedExpression
e = do
        String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"++"
        (LValue SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity (LValue SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SourcePos -> UnaryAssignOp -> LValue SourcePos -> ParsedExpression
forall a. a -> UnaryAssignOp -> LValue a -> Expression a
UnaryAssignExpr SourcePos
p UnaryAssignOp
PostfixInc) (SourcePos
-> ParsedExpression
-> ParsecT s ParserState Identity (LValue SourcePos)
forall s.
Stream s Identity Char =>
SourcePos -> ParsedExpression -> Parser s (LValue SourcePos)
asLValue SourcePos
p ParsedExpression
e)
  let postfixDec ParsedExpression
e = do
        String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"--"
        (LValue SourcePos -> ParsedExpression)
-> ParsecT s ParserState Identity (LValue SourcePos)
-> ParsecT s ParserState Identity ParsedExpression
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM (SourcePos -> UnaryAssignOp -> LValue SourcePos -> ParsedExpression
forall a. a -> UnaryAssignOp -> LValue a -> Expression a
UnaryAssignExpr SourcePos
p UnaryAssignOp
PostfixDec) (SourcePos
-> ParsedExpression
-> ParsecT s ParserState Identity (LValue SourcePos)
forall s.
Stream s Identity Char =>
SourcePos -> ParsedExpression -> Parser s (LValue SourcePos)
asLValue SourcePos
p ParsedExpression
e)
  let other = do
        e <- Maybe ParsedExpression
-> ParsecT s ParserState Identity ParsedExpression
forall s.
Stream s Identity Char =>
Maybe ParsedExpression -> ExpressionParser s
parseSimpleExpr Maybe ParsedExpression
forall a. Maybe a
Nothing
        postfixInc e <|> postfixDec e <|> return e
  prefixInc <|> prefixDec <|> other

parseTernaryExpr':: Stream s Identity Char
                 => Parser s (ParsedExpression,ParsedExpression)
parseTernaryExpr' :: forall s.
Stream s Identity Char =>
Parser s (ParsedExpression, ParsedExpression)
parseTernaryExpr' = do
    String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"?"
    l <- ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
assignExpr
    colon
    r <- assignExpr
    return (l,r)

parseTernaryExpr:: Stream s Identity Char => ExpressionParser s
parseTernaryExpr :: forall s. Stream s Identity Char => ExpressionParser s
parseTernaryExpr = do
  e <- ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseExpression'
  e' <- optionMaybe parseTernaryExpr'
  case e' of
    Maybe (ParsedExpression, ParsedExpression)
Nothing -> ParsedExpression -> ExpressionParser s
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ParsedExpression
e
    Just (ParsedExpression
l,ParsedExpression
r) -> do p <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
                     return $ CondExpr p e l r

assignOp :: Stream s Identity Char => Parser s AssignOp
assignOp :: forall s. Stream s Identity Char => Parser s AssignOp
assignOp = (String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssign)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"+=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignAdd)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"-=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignSub)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"*=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignMul)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"/=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignDiv)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"%=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignMod)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"<<=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignLShift)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
">>=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignSpRShift)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
">>>=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignZfRShift)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"&=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignBAnd)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"^=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignBXor)
        ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall s u (m :: * -> *) a.
ParsecT s u m a -> ParsecT s u m a -> ParsecT s u m a
<|>(String -> Parser s ()
forall s. Stream s Identity Char => String -> Parser s ()
reservedOp String
"|=" Parser s ()
-> ParsecT s ParserState Identity AssignOp
-> ParsecT s ParserState Identity AssignOp
forall a b.
ParsecT s ParserState Identity a
-> ParsecT s ParserState Identity b
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> AssignOp -> ParsecT s ParserState Identity AssignOp
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return AssignOp
OpAssignBOr)

assignExpr :: Stream s Identity Char => ExpressionParser s
assignExpr :: forall s. Stream s Identity Char => ExpressionParser s
assignExpr = do
  p <- ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition
  lhs <- parseTernaryExpr
  let assign = do
        op <- Parser s AssignOp
forall s. Stream s Identity Char => Parser s AssignOp
assignOp
        lhs <- asLValue p lhs
        rhs <- assignExpr
        return (AssignExpr p op lhs rhs)
  assign <|> return lhs

parseExpression:: Stream s Identity Char => ExpressionParser s
parseExpression :: forall s. Stream s Identity Char => ExpressionParser s
parseExpression = ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseListExpr

-- | A parser that parses ECMAScript expressions
expression :: Stream s Identity Char => Parser s (Expression SourcePos)
expression :: forall s. Stream s Identity Char => ExpressionParser s
expression = ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
parseExpression

parseListExpr :: Stream s Identity Char => ExpressionParser s
parseListExpr :: forall s. Stream s Identity Char => ExpressionParser s
parseListExpr = ExpressionParser s
forall s. Stream s Identity Char => ExpressionParser s
assignExpr ExpressionParser s
-> ParsecT s ParserState Identity String
-> ParsecT s ParserState Identity [ParsedExpression]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy1` ParsecT s ParserState Identity String
forall s. Stream s Identity Char => Parser s String
comma ParsecT s ParserState Identity [ParsedExpression]
-> ([ParsedExpression] -> ExpressionParser s) -> ExpressionParser s
forall a b.
ParsecT s ParserState Identity a
-> (a -> ParsecT s ParserState Identity b)
-> ParsecT s ParserState Identity b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[ParsedExpression]
exprs ->
  case [ParsedExpression]
exprs of
    [ParsedExpression
expr] -> ParsedExpression -> ExpressionParser s
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return ParsedExpression
expr
    [ParsedExpression]
es     -> (SourcePos -> [ParsedExpression] -> ParsedExpression)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity [ParsedExpression]
-> ExpressionParser s
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> [ParsedExpression] -> ParsedExpression
forall a. a -> [Expression a] -> Expression a
ListExpr ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition ([ParsedExpression]
-> ParsecT s ParserState Identity [ParsedExpression]
forall a. a -> ParsecT s ParserState Identity a
forall (m :: * -> *) a. Monad m => a -> m a
return [ParsedExpression]
es)

parseScript:: Stream s Identity Char => Parser s (JavaScript SourcePos)
parseScript :: forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
parseScript = do
  Parser s ()
forall s. Stream s Identity Char => Parser s ()
whiteSpace
  (SourcePos -> [ParsedStatement] -> JavaScript SourcePos)
-> ParsecT s ParserState Identity SourcePos
-> ParsecT s ParserState Identity [ParsedStatement]
-> ParsecT s ParserState Identity (JavaScript SourcePos)
forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 SourcePos -> [ParsedStatement] -> JavaScript SourcePos
forall a. a -> [Statement a] -> JavaScript a
Script ParsecT s ParserState Identity SourcePos
forall (m :: * -> *) s u. Monad m => ParsecT s u m SourcePos
getPosition (StatementParser s
forall s. Stream s Identity Char => StatementParser s
parseStatement StatementParser s
-> Parser s () -> ParsecT s ParserState Identity [ParsedStatement]
forall s (m :: * -> *) t u a sep.
Stream s m t =>
ParsecT s u m a -> ParsecT s u m sep -> ParsecT s u m [a]
`sepBy` Parser s ()
forall s. Stream s Identity Char => Parser s ()
whiteSpace)

-- | A parser that parses an ECMAScript program.
program :: Stream s Identity Char => Parser s (JavaScript SourcePos)
program :: forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
program = Parser s (JavaScript SourcePos)
forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
parseScript
  
-- | Parse from a stream given a parser, same as 'Text.Parsec.parse'
-- in Parsec. We can use this to parse expressions or statements alone,
-- not just whole programs.
parse :: Stream s Identity Char
      => Parser s a -- ^ The parser to use
      -> SourceName -- ^ Name of the source file
      -> s -- ^ the stream to parse, usually a 'String'
      -> Either ParseError a
parse :: forall s a.
Stream s Identity Char =>
Parser s a -> String -> s -> Either ParseError a
parse Parser s a
p = Parser s a -> ParserState -> String -> s -> Either ParseError a
forall s t u a.
Stream s Identity t =>
Parsec s u a -> u -> String -> s -> Either ParseError a
runParser Parser s a
p ParserState
initialParserState

-- | A convenience function that takes a 'String' and tries to parse
-- it as an ECMAScript program:
--
-- > parseFromString = parse program ""
parseFromString :: String -- ^ JavaScript source to parse
                  -> Either ParseError (JavaScript SourcePos)
parseFromString :: String -> Either ParseError (JavaScript SourcePos)
parseFromString = Parser String (JavaScript SourcePos)
-> String -> String -> Either ParseError (JavaScript SourcePos)
forall s a.
Stream s Identity Char =>
Parser s a -> String -> s -> Either ParseError a
parse Parser String (JavaScript SourcePos)
forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
program String
""

-- | A convenience function that takes a filename and tries to parse
-- the file contents an ECMAScript program, it fails with an error
-- message if it can't.
parseFromFile :: (MonadIO m, MonadError String m) => String -- ^ file name
                -> m (JavaScript SourcePos)
parseFromFile :: forall (m :: * -> *).
(MonadIO m, MonadError String m) =>
String -> m (JavaScript SourcePos)
parseFromFile String
fname =
  IO String -> m String
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO String
readFile String
fname) m String
-> (String -> m (JavaScript SourcePos)) -> m (JavaScript SourcePos)
forall a b. m a -> (a -> m b) -> m b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \String
source ->
  case Parser String (JavaScript SourcePos)
-> String -> String -> Either ParseError (JavaScript SourcePos)
forall s a.
Stream s Identity Char =>
Parser s a -> String -> s -> Either ParseError a
parse Parser String (JavaScript SourcePos)
forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
program String
fname String
source of
    Left ParseError
err -> String -> m (JavaScript SourcePos)
forall a. String -> m a
forall e (m :: * -> *) a. MonadError e m => e -> m a
throwError (String -> m (JavaScript SourcePos))
-> String -> m (JavaScript SourcePos)
forall a b. (a -> b) -> a -> b
$ ParseError -> String
forall a. Show a => a -> String
show ParseError
err
    Right JavaScript SourcePos
js -> JavaScript SourcePos -> m (JavaScript SourcePos)
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return JavaScript SourcePos
js

-- | Read a JavaScript program from file an parse it into a list of
-- statements
parseJavaScriptFromFile :: MonadIO m => String -- ^ file name
                        -> m [Statement SourcePos]
parseJavaScriptFromFile :: forall (m :: * -> *). MonadIO m => String -> m [ParsedStatement]
parseJavaScriptFromFile String
filename = do
  chars <- IO String -> m String
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO String -> m String) -> IO String -> m String
forall a b. (a -> b) -> a -> b
$ String -> IO String
readFile String
filename
  case parse parseScript filename chars of
    Left ParseError
err               -> IO [ParsedStatement] -> m [ParsedStatement]
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [ParsedStatement] -> m [ParsedStatement])
-> IO [ParsedStatement] -> m [ParsedStatement]
forall a b. (a -> b) -> a -> b
$ IOError -> IO [ParsedStatement]
forall e a. (HasCallStack, Exception e) => e -> IO a
throwIO (IOError -> IO [ParsedStatement])
-> IOError -> IO [ParsedStatement]
forall a b. (a -> b) -> a -> b
$ String -> IOError
userError (String -> IOError) -> String -> IOError
forall a b. (a -> b) -> a -> b
$ ParseError -> String
forall a. Show a => a -> String
show ParseError
err
    Right (Script SourcePos
_ [ParsedStatement]
stmts) -> [ParsedStatement] -> m [ParsedStatement]
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return [ParsedStatement]
stmts

-- | Parse a JavaScript program from a string
parseScriptFromString :: String -- ^ source file name
                      -> String -- ^ JavaScript source to parse
                      -> Either ParseError (JavaScript SourcePos)
parseScriptFromString :: String -> String -> Either ParseError (JavaScript SourcePos)
parseScriptFromString = Parser String (JavaScript SourcePos)
-> String -> String -> Either ParseError (JavaScript SourcePos)
forall s a.
Stream s Identity Char =>
Parser s a -> String -> s -> Either ParseError a
parse Parser String (JavaScript SourcePos)
forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
parseScript

-- | Parse a JavaScript source string into a list of statements
parseString :: String -- ^ JavaScript source
            -> [Statement SourcePos]
parseString :: String -> [ParsedStatement]
parseString String
str = case Parser String (JavaScript SourcePos)
-> String -> String -> Either ParseError (JavaScript SourcePos)
forall s a.
Stream s Identity Char =>
Parser s a -> String -> s -> Either ParseError a
parse Parser String (JavaScript SourcePos)
forall s. Stream s Identity Char => Parser s (JavaScript SourcePos)
parseScript String
"" String
str of
  Left ParseError
err -> String -> [ParsedStatement]
forall a. HasCallStack => String -> a
error (ParseError -> String
forall a. Show a => a -> String
show ParseError
err)
  Right (Script SourcePos
_ [ParsedStatement]
stmts) -> [ParsedStatement]
stmts