-- |ECMAScript 3 syntax. /Spec/ refers to the ECMA-262 specification, -- 3rd edition. {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE DeriveFoldable #-} module Language.ECMAScript3.Syntax (JavaScript(..) ,unJavaScript ,Statement(..) ,isIterationStmt ,CaseClause(..) ,CatchClause(..) ,ForInit(..) ,ForInInit(..) ,VarDecl(..) ,Expression(..) ,InfixOp(..) ,AssignOp(..) ,Id(..) ,unId ,PrefixOp(..) ,Prop(..) ,UnaryAssignOp(..) ,LValue (..) ,SourcePos ) where import Text.Parsec.Pos(initialPos,SourcePos) -- used by data JavaScript import Data.Generics(Data,Typeable) import Data.Foldable (Foldable) import Data.Traversable (Traversable) import Data.Default data JavaScript a -- |A script in \ ... \ tags. = Script a [Statement a] deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) instance Default a => Default (JavaScript a) where def = Script def [] -- | extracts statements from a JavaScript type unJavaScript :: JavaScript a -> [Statement a] unJavaScript (Script _ stmts) = stmts instance Default SourcePos where def = initialPos "" data Id a = Id a String deriving (Show,Eq,Ord,Data,Typeable,Functor,Foldable,Traversable) unId :: Id a -> String unId (Id _ s) = s -- | Infix operators: see spec 11.5-11.11 data InfixOp = OpLT -- ^ @<@ | OpLEq -- ^ @<=@ | OpGT -- ^ @>@ | OpGEq -- ^ @>=@ | OpIn -- ^ @in@ | OpInstanceof -- ^ @instanceof@ | OpEq -- ^ @==@ | OpNEq -- ^ @!=@ | OpStrictEq -- ^ @===@ | OpStrictNEq -- ^ @!===@ | OpLAnd -- ^ @&&@ | OpLOr -- ^ @||@ | OpMul -- ^ @*@ | OpDiv -- ^ @/@ | OpMod -- ^ @%@ | OpSub -- ^ @-@ | OpLShift -- ^ @<<@ | OpSpRShift -- ^ @>>@ | OpZfRShift -- ^ @>>>@ | OpBAnd -- ^ @&@ | OpBXor -- ^ @^@ | OpBOr -- ^ @|@ | OpAdd -- ^ @+@ deriving (Show,Data,Typeable,Eq,Ord,Enum) -- | Assignment operators: see spec 11.13 data AssignOp = OpAssign -- ^ simple assignment, @=@ | OpAssignAdd -- ^ @+=@ | OpAssignSub -- ^ @-=@ | OpAssignMul -- ^ @*=@ | OpAssignDiv -- ^ @/=@ | OpAssignMod -- ^ @%=@ | OpAssignLShift -- ^ @<<=@ | OpAssignSpRShift -- ^ @>>=@ | OpAssignZfRShift -- ^ @>>>=@ | OpAssignBAnd -- ^ @&=@ | OpAssignBXor -- ^ @^=@ | OpAssignBOr -- ^ @|=@ deriving (Show,Data,Typeable,Eq,Ord) -- | Unary assignment operators: see spec 11.3, 11.4.4, 11.4.5 data UnaryAssignOp = PrefixInc -- ^ @++x@ | PrefixDec -- ^ @--x@ | PostfixInc -- ^ @x++@ | PostfixDec -- ^ @x--@ deriving (Show, Data, Typeable, Eq, Ord) -- | Prefix operators: see spec 11.4 (excluding 11.4.4, 11.4.5) data PrefixOp = PrefixLNot -- ^ @!@ | PrefixBNot -- ^ @~@ | PrefixPlus -- ^ @+@ | PrefixMinus -- ^ @-@ | PrefixTypeof -- ^ @typeof@ | PrefixVoid -- ^ @void@ | PrefixDelete -- ^ @delete@ deriving (Show,Data,Typeable,Eq,Ord) -- | Property names in an object initializer: see spec 11.1.5 data Prop a = PropId a (Id a) -- ^ property name is an identifier, @foo@ | PropString a String -- ^ property name is a string, @\"foo\"@ | PropNum a Integer -- ^ property name is an integer, @42@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | Left-hand side expressions: see spec 11.2 data LValue a = LVar a String -- ^ variable reference, @foo@ | LDot a (Expression a) String -- ^ @foo.bar@ | LBracket a (Expression a) (Expression a) -- ^ @foo[bar]@ deriving (Show, Eq, Ord, Data, Typeable, Functor,Foldable,Traversable) -- | Expressions, see spec 11 data Expression a = StringLit a String -- ^ @\"foo\"@, spec 11.1.3, 7.8 | RegexpLit a String Bool Bool -- ^ @RegexpLit a regexp global? case_insensitive?@ -- regular -- expression, see spec 11.1.3, 7.8 | NumLit a Double -- ^ @41.99999@, spec 11.1.3, 7.8 | IntLit a Int -- ^ @42@, spec 11.1.3, 7.8 | BoolLit a Bool -- ^ @true@, spec 11.1.3, 7.8 | NullLit a -- ^ @null@, spec 11.1.3, 7.8 | ArrayLit a [Expression a] -- ^ @[1,2,3]@, spec 11.1.4 | ObjectLit a [(Prop a, Expression a)] -- ^ @{foo:\"bar\", baz: 42}@, spec 11.1.5 | ThisRef a -- ^ @this@, spec 11.1.1 | VarRef a (Id a) -- ^ @foo@, spec 11.1.2 | DotRef a (Expression a) (Id a) -- ^ @foo.bar@, spec 11.2.1 | BracketRef a (Expression a) {- container -} (Expression a) {- key -} -- ^ @foo[bar@, spec 11.2.1 | NewExpr a (Expression a) {- constructor -} [Expression a] -- ^ @new foo(bar)@, spec 11.2.2 | PrefixExpr a PrefixOp (Expression a) -- ^ @\@e@, spec 11.4 (excluding 11.4.4, 111.4.5) | UnaryAssignExpr a UnaryAssignOp (LValue a) -- ^ @++x@, @x--@ etc., spec 11.3, 11.4.4, 11.4.5 | InfixExpr a InfixOp (Expression a) (Expression a) -- ^ @e1\@e2@, spec 11.5, 11.6, 11.7, 11.8, 11.9, 11.10, 11.11 | CondExpr a (Expression a) (Expression a) (Expression a) -- ^ @e1 ? e2 : e3@, spec 11.12 | AssignExpr a AssignOp (LValue a) (Expression a) -- ^ @e1 \@=e2@, spec 11.13 | ListExpr a [Expression a] -- ^ @e1, e2@, spec 11.14 | CallExpr a (Expression a) [Expression a] -- ^ @f(x,y,z)@, spec 11.2.3 --funcexprs are optionally named | FuncExpr a (Maybe (Id a)) [Id a] [Statement a] -- ^ @function f (x,y,z) {...}@, spec 11.2.5, 13 deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | Case clauses, spec 12.11 data CaseClause a = CaseClause a (Expression a) [Statement a] -- ^ @case e: stmts;@ | CaseDefault a [Statement a] -- ^ @default: stmts;@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | Catch clause, spec 12.14 data CatchClause a = CatchClause a (Id a) (Statement a) -- ^ @catch (x) {...}@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | A variable declaration, spec 12.2 data VarDecl a = VarDecl a (Id a) (Maybe (Expression a)) -- ^ @var x = e;@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | for initializer, spec 12.6 data ForInit a = NoInit -- ^ empty | VarInit [VarDecl a] -- ^ @var x, y=42@ | ExprInit (Expression a) -- ^ @expr@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | for..in initializer, spec 12.6 data ForInInit a = ForInVar (Id a) -- ^ @var x@ | ForInLVal (LValue a) -- ^ @foo.baz@, @foo[bar]@, @z@ deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | Statements, spec 12. data Statement a = BlockStmt a [Statement a] -- ^ @{stmts}@, spec 12.1 | EmptyStmt a -- ^ @;@, spec 12.3 | ExprStmt a (Expression a) -- ^ @expr;@, spec 12.4 | IfStmt a (Expression a) (Statement a) (Statement a) -- ^ @if (e) stmt@, spec 12.5 | IfSingleStmt a (Expression a) (Statement a) -- ^ @if (e) stmt1 else stmt2@, spec 12.5 | SwitchStmt a (Expression a) [CaseClause a] -- ^ @switch (e) clauses@, spec 12.11 | WhileStmt a (Expression a) (Statement a) -- ^ @while (e) do stmt@, spec 12.6 | DoWhileStmt a (Statement a) (Expression a) -- ^ @do stmt while (e);@, spec 12.6 | BreakStmt a (Maybe (Id a)) -- ^ @break lab;@, spec 12.8 | ContinueStmt a (Maybe (Id a)) -- ^ @continue lab;@, spec 12.7 | LabelledStmt a (Id a) (Statement a) -- ^ @lab: stmt@, spec 12.12 | ForInStmt a (ForInInit a) (Expression a) (Statement a) -- ^ @for (x in o) stmt@, spec 12.6 | ForStmt a (ForInit a) (Maybe (Expression a)) -- test (Maybe (Expression a)) -- increment (Statement a) -- body -- ^ @ForStmt a init test increment body@, @for (init; test, -- increment) body@, spec 12.6 | TryStmt a (Statement a) {-body-} (Maybe (CatchClause a)) (Maybe (Statement a)) {-finally-} -- ^ @try stmt catch(x) stmt finally stmt@, spec 12.14 | ThrowStmt a (Expression a) -- ^ @throw expr;@, spec 12.13 | ReturnStmt a (Maybe (Expression a)) -- ^ @return expr;@, spec 12.9 | WithStmt a (Expression a) (Statement a) -- ^ @with (o) stmt@, spec 12.10 | VarDeclStmt a [VarDecl a] -- ^ @var x, y=42;@, spec 12.2 | FunctionStmt a (Id a) {-name-} [Id a] {-args-} [Statement a] {-body-} -- ^ @function f(x, y, z) {...}@, spec 13 deriving (Show,Data,Typeable,Eq,Ord,Functor,Foldable,Traversable) -- | Returns 'True' if the statement is an /IterationStatement/ -- according to spec 12.6. isIterationStmt :: Statement a -> Bool isIterationStmt s = case s of WhileStmt {} -> True DoWhileStmt {} -> True ForStmt {} -> True ForInStmt {} -> True _ -> False