packages feed

language-javascript 0.6.0.13 → 0.6.0.14

raw patch · 15 files changed

+629/−97 lines, 15 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ Language.JavaScript.Parser: JSClass :: !JSAnnot -> !JSIdent -> !JSClassHeritage -> !JSAnnot -> ![JSClassElement] -> !JSAnnot -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser: JSClassExpression :: !JSAnnot -> !JSIdent -> !JSClassHeritage -> !JSAnnot -> ![JSClassElement] -> !JSAnnot -> JSExpression
+ Language.JavaScript.Parser: JSForConst :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser: JSForConstIn :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSExpression -> !JSBinOp -> !JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser: JSForConstOf :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSExpression -> !JSBinOp -> !JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser: JSGenerator :: !JSAnnot -> !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser: JSGeneratorExpression :: !JSAnnot -> !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSExpression
+ Language.JavaScript.Parser: JSTemplateLiteral :: !Maybe JSExpression -> !JSAnnot -> !String -> ![JSTemplatePart] -> JSExpression
+ Language.JavaScript.Parser: JSYieldExpression :: !JSAnnot -> !Maybe JSExpression -> JSExpression
+ Language.JavaScript.Parser: JSYieldFromExpression :: !JSAnnot -> !JSAnnot -> !JSExpression -> JSExpression
+ Language.JavaScript.Parser.AST: JSClass :: !JSAnnot -> !JSIdent -> !JSClassHeritage -> !JSAnnot -> ![JSClassElement] -> !JSAnnot -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser.AST: JSClassExpression :: !JSAnnot -> !JSIdent -> !JSClassHeritage -> !JSAnnot -> ![JSClassElement] -> !JSAnnot -> JSExpression
+ Language.JavaScript.Parser.AST: JSClassInstanceMethod :: !JSMethodDefinition -> JSClassElement
+ Language.JavaScript.Parser.AST: JSClassSemi :: !JSAnnot -> JSClassElement
+ Language.JavaScript.Parser.AST: JSClassStaticMethod :: !JSAnnot -> !JSMethodDefinition -> JSClassElement
+ Language.JavaScript.Parser.AST: JSExtends :: !JSAnnot -> !JSExpression -> JSClassHeritage
+ Language.JavaScript.Parser.AST: JSExtendsNone :: JSClassHeritage
+ Language.JavaScript.Parser.AST: JSForConst :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser.AST: JSForConstIn :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSExpression -> !JSBinOp -> !JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser.AST: JSForConstOf :: !JSAnnot -> !JSAnnot -> !JSAnnot -> !JSExpression -> !JSBinOp -> !JSExpression -> !JSAnnot -> !JSStatement -> JSStatement
+ Language.JavaScript.Parser.AST: JSGenerator :: !JSAnnot -> !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser.AST: JSGeneratorExpression :: !JSAnnot -> !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSExpression
+ Language.JavaScript.Parser.AST: JSGeneratorMethodDefinition :: !JSAnnot -> !JSPropertyName -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSMethodDefinition
+ Language.JavaScript.Parser.AST: JSImportDeclarationBare :: !JSAnnot -> !String -> !JSSemi -> JSImportDeclaration
+ Language.JavaScript.Parser.AST: JSMethodDefinition :: !JSPropertyName -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSMethodDefinition
+ Language.JavaScript.Parser.AST: JSObjectMethod :: !JSMethodDefinition -> JSObjectProperty
+ Language.JavaScript.Parser.AST: JSPropertyComputed :: !JSAnnot -> !JSExpression -> !JSAnnot -> JSPropertyName
+ Language.JavaScript.Parser.AST: JSPropertyIdentRef :: !JSAnnot -> !String -> JSObjectProperty
+ Language.JavaScript.Parser.AST: JSTemplateLiteral :: !Maybe JSExpression -> !JSAnnot -> !String -> ![JSTemplatePart] -> JSExpression
+ Language.JavaScript.Parser.AST: JSTemplatePart :: !JSExpression -> !JSAnnot -> !String -> JSTemplatePart
+ Language.JavaScript.Parser.AST: JSYieldExpression :: !JSAnnot -> !Maybe JSExpression -> JSExpression
+ Language.JavaScript.Parser.AST: JSYieldFromExpression :: !JSAnnot -> !JSAnnot -> !JSExpression -> JSExpression
+ Language.JavaScript.Parser.AST: data JSClassElement
+ Language.JavaScript.Parser.AST: data JSClassHeritage
+ Language.JavaScript.Parser.AST: data JSMethodDefinition
+ Language.JavaScript.Parser.AST: data JSTemplatePart
+ Language.JavaScript.Parser.AST: instance Data.Data.Data Language.JavaScript.Parser.AST.JSClassElement
+ Language.JavaScript.Parser.AST: instance Data.Data.Data Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Parser.AST: instance Data.Data.Data Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Parser.AST: instance Data.Data.Data Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Parser.AST: instance GHC.Classes.Eq Language.JavaScript.Parser.AST.JSClassElement
+ Language.JavaScript.Parser.AST: instance GHC.Classes.Eq Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Parser.AST: instance GHC.Classes.Eq Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Parser.AST: instance GHC.Classes.Eq Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Parser.AST: instance GHC.Show.Show Language.JavaScript.Parser.AST.JSClassElement
+ Language.JavaScript.Parser.AST: instance GHC.Show.Show Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Parser.AST: instance GHC.Show.Show Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Parser.AST: instance GHC.Show.Show Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Parser.AST: instance Language.JavaScript.Parser.AST.ShowStripped Language.JavaScript.Parser.AST.JSClassElement
+ Language.JavaScript.Parser.AST: instance Language.JavaScript.Parser.AST.ShowStripped Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Parser.AST: instance Language.JavaScript.Parser.AST.ShowStripped Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Parser.AST: instance Language.JavaScript.Parser.AST.ShowStripped Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Parser.Lexer: ClassToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: ExtendsToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: NoSubstitutionTemplateToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: StaticToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: SuperToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: TemplateHeadToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: TemplateMiddleToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: TemplateTailToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: YieldToken :: !TokenPosn -> !String -> ![CommentAnnotation] -> Token
+ Language.JavaScript.Parser.Lexer: setInTemplate :: Bool -> Alex ()
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS Language.JavaScript.Parser.AST.JSClassElement
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS [Language.JavaScript.Parser.AST.JSClassElement]
+ Language.JavaScript.Pretty.Printer: instance Language.JavaScript.Pretty.Printer.RenderJS [Language.JavaScript.Parser.AST.JSTemplatePart]
+ Language.JavaScript.Process.Minify: instance Language.JavaScript.Process.Minify.MinifyJS Language.JavaScript.Parser.AST.JSClassHeritage
+ Language.JavaScript.Process.Minify: instance Language.JavaScript.Process.Minify.MinifyJS Language.JavaScript.Parser.AST.JSMethodDefinition
+ Language.JavaScript.Process.Minify: instance Language.JavaScript.Process.Minify.MinifyJS Language.JavaScript.Parser.AST.JSTemplatePart
+ Language.JavaScript.Process.Minify: instance Language.JavaScript.Process.Minify.MinifyJS [Language.JavaScript.Parser.AST.JSClassElement]
- Language.JavaScript.Parser: JSFunction :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSIdent -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser: JSFunction :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
- Language.JavaScript.Parser: JSFunctionExpression :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSIdent -> !JSAnnot -> !JSBlock -> JSExpression
+ Language.JavaScript.Parser: JSFunctionExpression :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSExpression
- Language.JavaScript.Parser.AST: JSFunction :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSIdent -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
+ Language.JavaScript.Parser.AST: JSFunction :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> !JSSemi -> JSStatement
- Language.JavaScript.Parser.AST: JSFunctionExpression :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSIdent -> !JSAnnot -> !JSBlock -> JSExpression
+ Language.JavaScript.Parser.AST: JSFunctionExpression :: !JSAnnot -> !JSIdent -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSExpression
- Language.JavaScript.Parser.AST: JSParenthesizedArrowParameterList :: !JSAnnot -> !JSCommaList JSIdent -> !JSAnnot -> JSArrowParameterList
+ Language.JavaScript.Parser.AST: JSParenthesizedArrowParameterList :: !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> JSArrowParameterList
- Language.JavaScript.Parser.AST: JSPropertyAccessor :: !JSAccessor -> !JSPropertyName -> !JSAnnot -> ![JSExpression] -> !JSAnnot -> !JSBlock -> JSObjectProperty
+ Language.JavaScript.Parser.AST: JSPropertyAccessor :: !JSAccessor -> !JSPropertyName -> !JSAnnot -> !JSCommaList JSExpression -> !JSAnnot -> !JSBlock -> JSMethodDefinition

Files

ChangeLog.md view
@@ -1,5 +1,20 @@ # ChangeLog for `language-javascript` +## 0.6.0.13 -- 2019-09-29+++ Add support for (Ryan Hendrickson):+  - Destructuring in var declarations+  - `const` in for statements+  - ES6 property shorthand syntax+  - Template literals+  - Computed property names+  - Bare import declarations+  - Exotic parameter syntaxes+  - Generators and `yield`+  - Method definitions+  - classes+ `- super` keyword+ ## 0.6.0.13 -- 2019-06-17  + Add support for (Cyril Sobierajewicz):
language-javascript.cabal view
@@ -1,5 +1,5 @@ Name:                language-javascript-Version:             0.6.0.13+Version:             0.6.0.14 Synopsis:            Parser for JavaScript Description:         Parses Javascript into an Abstract Syntax Tree (AST).  Initially intended as frontend to hjsmin.                      .
src/Language/JavaScript/Parser/AST.hs view
@@ -17,12 +17,16 @@     , JSPropertyName (..)     , JSObjectPropertyList     , JSAccessor (..)+    , JSMethodDefinition (..)     , JSIdent (..)     , JSVarInitializer (..)     , JSArrayElement (..)     , JSCommaList (..)     , JSCommaTrailingList (..)     , JSArrowParameterList (..)+    , JSTemplatePart (..)+    , JSClassHeritage (..)+    , JSClassElement (..)      -- Modules     , JSModuleItem (..)@@ -72,7 +76,7 @@  data JSImportDeclaration     = JSImportDeclaration !JSImportClause !JSFromClause !JSSemi -- ^imports, module, semi-    -- | JSImportDeclarationBare -- ^ module, semi+    | JSImportDeclarationBare !JSAnnot !String !JSSemi -- ^module, module, semi     deriving (Data, Eq, Show, Typeable)  data JSImportClause@@ -126,6 +130,7 @@     = JSStatementBlock !JSAnnot ![JSStatement] !JSAnnot !JSSemi     -- ^lbrace, stmts, rbrace, autosemi     | JSBreak !JSAnnot !JSIdent !JSSemi        -- ^break,optional identifier, autosemi     | JSLet   !JSAnnot !(JSCommaList JSExpression) !JSSemi -- ^const, decl, autosemi+    | JSClass !JSAnnot !JSIdent !JSClassHeritage !JSAnnot ![JSClassElement] !JSAnnot !JSSemi -- ^class, name, optional extends clause, lb, body, rb, autosemi     | JSConstant !JSAnnot !(JSCommaList JSExpression) !JSSemi -- ^const, decl, autosemi     | JSContinue !JSAnnot !JSIdent !JSSemi     -- ^continue, optional identifier,autosemi     | JSDoWhile !JSAnnot !JSStatement !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSSemi -- ^do,stmt,while,lb,expr,rb,autosemi@@ -136,9 +141,13 @@     | JSForLet !JSAnnot !JSAnnot !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSStatement -- ^for,lb,var,vardecl,semi,expr,semi,expr,rb,stmt     | JSForLetIn !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt     | JSForLetOf !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt+    | JSForConst !JSAnnot !JSAnnot !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSStatement -- ^for,lb,var,vardecl,semi,expr,semi,expr,rb,stmt+    | JSForConstIn !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt+    | JSForConstOf !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt     | JSForOf !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,expr,in,expr,rb,stmt     | JSForVarOf !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt-    | JSFunction !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSIdent) !JSAnnot !JSBlock !JSSemi  -- ^fn,name, lb,parameter list,rb,block,autosemi+    | JSFunction !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock !JSSemi  -- ^fn,name, lb,parameter list,rb,block,autosemi+    | JSGenerator !JSAnnot !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock !JSSemi  -- ^fn,*,name, lb,parameter list,rb,block,autosemi     | JSIf !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement -- ^if,(,expr,),stmt     | JSIfElse !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement !JSAnnot !JSStatement -- ^if,(,expr,),stmt,else,rest     | JSLabelled !JSIdent !JSAnnot !JSStatement -- ^identifier,colon,stmt@@ -171,13 +180,15 @@     | JSCallExpression !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot  -- ^expr, bl, args, rb     | JSCallExpressionDot !JSExpression !JSAnnot !JSExpression  -- ^expr, dot, expr     | JSCallExpressionSquare !JSExpression !JSAnnot !JSExpression !JSAnnot  -- ^expr, [, expr, ]+    | JSClassExpression !JSAnnot !JSIdent !JSClassHeritage !JSAnnot ![JSClassElement] !JSAnnot -- ^class, optional identifier, optional extends clause, lb, body, rb     | JSCommaExpression !JSExpression !JSAnnot !JSExpression          -- ^expression components     | JSExpressionBinary !JSExpression !JSBinOp !JSExpression -- ^lhs, op, rhs     | JSExpressionParen !JSAnnot !JSExpression !JSAnnot -- ^lb,expression,rb     | JSExpressionPostfix !JSExpression !JSUnaryOp -- ^expression, operator     | JSExpressionTernary !JSExpression !JSAnnot !JSExpression !JSAnnot !JSExpression -- ^cond, ?, trueval, :, falseval     | JSArrowExpression !JSArrowParameterList !JSAnnot !JSStatement -- ^parameter list,arrow,block`-    | JSFunctionExpression !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSIdent) !JSAnnot !JSBlock -- ^fn,name,lb, parameter list,rb,block`+    | JSFunctionExpression !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock -- ^fn,name,lb, parameter list,rb,block`+    | JSGeneratorExpression !JSAnnot !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock -- ^fn,*,name,lb, parameter list,rb,block`     | JSMemberDot !JSExpression !JSAnnot !JSExpression -- ^firstpart, dot, name     | JSMemberExpression !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot -- expr, lb, args, rb     | JSMemberNew !JSAnnot !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot -- ^new, name, lb, args, rb@@ -185,13 +196,16 @@     | JSNewExpression !JSAnnot !JSExpression -- ^new, expr     | JSObjectLiteral !JSAnnot !JSObjectPropertyList !JSAnnot -- ^lbrace contents rbrace     | JSSpreadExpression !JSAnnot !JSExpression+    | JSTemplateLiteral !(Maybe JSExpression) !JSAnnot !String ![JSTemplatePart] -- ^optional tag, lquot, head, parts     | JSUnaryExpression !JSUnaryOp !JSExpression     | JSVarInitExpression !JSExpression !JSVarInitializer -- ^identifier, initializer+    | JSYieldExpression !JSAnnot !(Maybe JSExpression) -- ^yield, optional expr+    | JSYieldFromExpression !JSAnnot !JSAnnot !JSExpression -- ^yield, *, expr     deriving (Data, Eq, Show, Typeable)  data JSArrowParameterList     = JSUnparenthesizedArrowParameter !JSIdent-    | JSParenthesizedArrowParameterList !JSAnnot !(JSCommaList JSIdent) !JSAnnot+    | JSParenthesizedArrowParameterList !JSAnnot !(JSCommaList JSExpression) !JSAnnot     deriving (Data, Eq, Show, Typeable)  data JSBinOp@@ -278,14 +292,22 @@     deriving (Data, Eq, Show, Typeable)  data JSObjectProperty-    = JSPropertyAccessor !JSAccessor !JSPropertyName !JSAnnot ![JSExpression] !JSAnnot !JSBlock -- ^(get|set), name, lb, params, rb, block-    | JSPropertyNameandValue !JSPropertyName !JSAnnot ![JSExpression] -- ^name, colon, value+    = JSPropertyNameandValue !JSPropertyName !JSAnnot ![JSExpression] -- ^name, colon, value+    | JSPropertyIdentRef !JSAnnot !String+    | JSObjectMethod !JSMethodDefinition     deriving (Data, Eq, Show, Typeable) +data JSMethodDefinition+    = JSMethodDefinition !JSPropertyName !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock -- name, lb, params, rb, block+    | JSGeneratorMethodDefinition !JSAnnot !JSPropertyName !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock -- ^*, name, lb, params, rb, block+    | JSPropertyAccessor !JSAccessor !JSPropertyName !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSBlock -- ^get/set, name, lb, params, rb, block+    deriving (Data, Eq, Show, Typeable)+ data JSPropertyName     = JSPropertyIdent !JSAnnot !String     | JSPropertyString !JSAnnot !String     | JSPropertyNumber !JSAnnot !String+    | JSPropertyComputed !JSAnnot !JSExpression !JSAnnot -- ^lb, expr, rb     deriving (Data, Eq, Show, Typeable)  type JSObjectPropertyList = JSCommaTrailingList JSObjectProperty@@ -317,6 +339,21 @@     | JSCTLNone !(JSCommaList a) -- ^list     deriving (Data, Eq, Show, Typeable) +data JSTemplatePart+    = JSTemplatePart !JSExpression !JSAnnot !String -- ^expr, rb, suffix+    deriving (Data, Eq, Show, Typeable)++data JSClassHeritage+    = JSExtends !JSAnnot !JSExpression+    | JSExtendsNone+    deriving (Data, Eq, Show, Typeable)++data JSClassElement+    = JSClassInstanceMethod !JSMethodDefinition+    | JSClassStaticMethod !JSAnnot !JSMethodDefinition+    | JSClassSemi !JSAnnot+    deriving (Data, Eq, Show, Typeable)+ -- ----------------------------------------------------------------------------- -- | Show the AST elements stripped of their JSAnnot data. @@ -336,6 +373,7 @@     ss (JSStatementBlock _ xs _ _) = "JSStatementBlock " ++ ss xs     ss (JSBreak _ JSIdentNone s) = "JSBreak" ++ commaIf (ss s)     ss (JSBreak _ (JSIdentName _ n) s) = "JSBreak " ++ singleQuote n ++ commaIf (ss s)+    ss (JSClass _ n h _lb xs _rb _) = "JSClass " ++ ssid n ++ " (" ++ ss h ++ ") " ++ ss xs     ss (JSContinue _ JSIdentNone s) = "JSContinue" ++ commaIf (ss s)     ss (JSContinue _ (JSIdentName _ n) s) = "JSContinue " ++ singleQuote n ++ commaIf (ss s)     ss (JSConstant _ xs _as) = "JSConstant " ++ ss xs@@ -347,9 +385,13 @@     ss (JSForLet _ _lb _v x1s _s1 x2s _s2 x3s _rb x4) = "JSForLet " ++ ss x1s ++ " " ++ ss x2s ++ " " ++ ss x3s ++ " (" ++ ss x4 ++ ")"     ss (JSForLetIn _ _lb _v x1 _i x2 _rb x3) = "JSForLetIn (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"     ss (JSForLetOf _ _lb _v x1 _i x2 _rb x3) = "JSForLetOf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"+    ss (JSForConst _ _lb _v x1s _s1 x2s _s2 x3s _rb x4) = "JSForConst " ++ ss x1s ++ " " ++ ss x2s ++ " " ++ ss x3s ++ " (" ++ ss x4 ++ ")"+    ss (JSForConstIn _ _lb _v x1 _i x2 _rb x3) = "JSForConstIn (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"+    ss (JSForConstOf _ _lb _v x1 _i x2 _rb x3) = "JSForConstOf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"     ss (JSForOf _ _lb x1s _i x2 _rb x3) = "JSForOf " ++ ss x1s ++ " (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"     ss (JSForVarOf _ _lb _v x1 _i x2 _rb x3) = "JSForVarOf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"     ss (JSFunction _ n _lb pl _rb x3 _) = "JSFunction " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")"+    ss (JSGenerator _ _ n _lb pl _rb x3 _) = "JSGenerator " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")"     ss (JSIf _ _lb x1 _rb x2) = "JSIf (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")"     ss (JSIfElse _ _lb x1 _rb x2 _e x3) = "JSIfElse (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")"     ss (JSLabelled x1 _c x2) = "JSLabelled (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")"@@ -373,6 +415,7 @@     ss (JSCallExpression ex _ xs _) = "JSCallExpression ("++ ss ex ++ ",JSArguments " ++ ss xs ++ ")"     ss (JSCallExpressionDot ex _os xs) = "JSCallExpressionDot (" ++ ss ex ++ "," ++ ss xs ++ ")"     ss (JSCallExpressionSquare ex _os xs _cs) = "JSCallExpressionSquare (" ++ ss ex ++ "," ++ ss xs ++ ")"+    ss (JSClassExpression _ n h _lb xs _rb) = "JSClassExpression " ++ ssid n ++ " (" ++ ss h ++ ") " ++ ss xs     ss (JSDecimal _ s) = "JSDecimal " ++ singleQuote s     ss (JSCommaExpression l _ r) = "JSExpression [" ++ ss l ++ "," ++ ss r ++ "]"     ss (JSExpressionBinary x2 op x3) = "JSExpressionBinary (" ++ ss op ++ "," ++ ss x2 ++ "," ++ ss x3 ++ ")"@@ -380,7 +423,8 @@     ss (JSExpressionPostfix xs op) = "JSExpressionPostfix (" ++ ss op ++ "," ++ ss xs ++ ")"     ss (JSExpressionTernary x1 _q x2 _c x3) = "JSExpressionTernary (" ++ ss x1 ++ "," ++ ss x2 ++ "," ++ ss x3 ++ ")"     ss (JSArrowExpression ps _ e) = "JSArrowExpression (" ++ ss ps ++ ") => " ++ ss e-    ss (JSFunctionExpression _ n _lb pl _rb x3) = "JSFunctionExpression " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ "))"+    ss (JSFunctionExpression _ n _lb pl _rb x3) = "JSFunctionExpression " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")"+    ss (JSGeneratorExpression _ _ n _lb pl _rb x3) = "JSGeneratorExpression " ++ ssid n ++ " " ++ ss pl ++ " (" ++ ss x3 ++ ")"     ss (JSHexInteger _ s) = "JSHexInteger " ++ singleQuote s     ss (JSOctal _ s) = "JSOctal " ++ singleQuote s     ss (JSIdentifier _ s) = "JSIdentifier " ++ singleQuote s@@ -396,7 +440,12 @@     ss (JSStringLiteral _ s) = "JSStringLiteral " ++ s     ss (JSUnaryExpression op x) = "JSUnaryExpression (" ++ ss op ++ "," ++ ss x ++ ")"     ss (JSVarInitExpression x1 x2) = "JSVarInitExpression (" ++ ss x1 ++ ") " ++ ss x2+    ss (JSYieldExpression _ Nothing) = "JSYieldExpression ()"+    ss (JSYieldExpression _ (Just x)) = "JSYieldExpression (" ++ ss x ++ ")"+    ss (JSYieldFromExpression _ _ x) = "JSYieldFromExpression (" ++ ss x ++ ")"     ss (JSSpreadExpression _ x1) = "JSSpreadExpression (" ++ ss x1 ++ ")"+    ss (JSTemplateLiteral Nothing _ s ps) = "JSTemplateLiteral (()," ++ singleQuote s ++ "," ++ ss ps ++ ")"+    ss (JSTemplateLiteral (Just t) _ s ps) = "JSTemplateLiteral ((" ++ ss t ++ ")," ++ singleQuote s ++ "," ++ ss ps ++ ")"  instance ShowStripped JSArrowParameterList where     ss (JSUnparenthesizedArrowParameter x) = ss x@@ -409,6 +458,7 @@  instance ShowStripped JSImportDeclaration where     ss (JSImportDeclaration imp from _) = "JSImportDeclaration (" ++ ss imp ++ "," ++ ss from ++ ")"+    ss (JSImportDeclarationBare _ m _) = "JSImportDeclarationBare (" ++ singleQuote m ++ ")"  instance ShowStripped JSImportClause where     ss (JSImportClauseDefault x) = "JSImportClauseDefault (" ++ ss x ++ ")"@@ -456,12 +506,19 @@  instance ShowStripped JSObjectProperty where     ss (JSPropertyNameandValue x1 _colon x2s) = "JSPropertyNameandValue (" ++ ss x1 ++ ") " ++ ss x2s+    ss (JSPropertyIdentRef _ s) = "JSPropertyIdentRef " ++ singleQuote s+    ss (JSObjectMethod m) = ss m++instance ShowStripped JSMethodDefinition where+    ss (JSMethodDefinition x1 _lb1 x2s _rb1 x3) = "JSMethodDefinition (" ++ ss x1 ++ ") " ++ ss x2s ++ " (" ++ ss x3 ++ ")"     ss (JSPropertyAccessor s x1 _lb1 x2s _rb1 x3) = "JSPropertyAccessor " ++ ss s ++ " (" ++ ss x1 ++ ") " ++ ss x2s ++ " (" ++ ss x3 ++ ")"+    ss (JSGeneratorMethodDefinition _ x1 _lb1 x2s _rb1 x3) = "JSGeneratorMethodDefinition (" ++ ss x1 ++ ") " ++ ss x2s ++ " (" ++ ss x3 ++ ")"  instance ShowStripped JSPropertyName where     ss (JSPropertyIdent _ s) = "JSIdentifier " ++ singleQuote s     ss (JSPropertyString _ s) = "JSIdentifier " ++ singleQuote s     ss (JSPropertyNumber _ s) = "JSIdentifier " ++ singleQuote s+    ss (JSPropertyComputed _ x _) = "JSPropertyComputed (" ++ ss x ++ ")"  instance ShowStripped JSAccessor where     ss (JSAccessorGet _) = "JSAccessorGet"@@ -536,6 +593,18 @@ instance ShowStripped JSArrayElement where     ss (JSArrayElement e) = ss e     ss (JSArrayComma _) = "JSComma"++instance ShowStripped JSTemplatePart where+    ss (JSTemplatePart e _ s) = "(" ++ ss e ++ "," ++ singleQuote s ++ ")"++instance ShowStripped JSClassHeritage where+    ss JSExtendsNone = ""+    ss (JSExtends _ x) = ss x++instance ShowStripped JSClassElement where+    ss (JSClassInstanceMethod m) = ss m+    ss (JSClassStaticMethod _ m) = "JSClassStaticMethod (" ++ ss m ++ ")"+    ss (JSClassSemi _) = "JSClassSemi"  instance ShowStripped a => ShowStripped (JSCommaList a) where     ss xs = "(" ++ commaJoin (map ss $ fromCommaList xs) ++ ")"
src/Language/JavaScript/Parser/Grammar7.y view
@@ -9,6 +9,7 @@     ) where  import Data.Char+import Data.Functor (($>)) import Language.JavaScript.Parser.Lexer import Language.JavaScript.Parser.ParserMonad import Language.JavaScript.Parser.SrcLocation@@ -88,6 +89,7 @@      'break'      { BreakToken {} }      'case'       { CaseToken {} }      'catch'      { CatchToken {} }+     'class'      { ClassToken {} }      'const'      { ConstToken {} }      'continue'   { ContinueToken {} }      'debugger'   { DebuggerToken {} }@@ -97,6 +99,7 @@      'else'       { ElseToken {} }      'enum'       { EnumToken {} }      'export'     { ExportToken {} }+     'extends'    { ExtendsToken {} }      'false'      { FalseToken {} }      'finally'    { FinallyToken {} }      'for'        { ForToken {} }@@ -113,6 +116,8 @@      'of'         { OfToken {} }      'return'     { ReturnToken {} }      'set'        { SetToken {} }+     'static'     { StaticToken {} }+     'super'      { SuperToken {} }      'switch'     { SwitchToken {} }      'this'       { ThisToken {} }      'throw'      { ThrowToken {} }@@ -123,6 +128,7 @@      'void'       { VoidToken {} }      'while'      { WhileToken {} }      'with'       { WithToken {} }+     'yield'      { YieldToken {} }        'ident'      { IdentifierToken {} }@@ -131,6 +137,10 @@      'octal'      { OctalToken {} }      'string'     { StringToken {} }      'regex'      { RegExToken {} }+     'tmplnosub'  { NoSubstitutionTemplateToken {} }+     'tmplhead'   { TemplateHeadToken {} }+     'tmplmiddle' { TemplateMiddleToken {} }+     'tmpltail'   { TemplateTailToken {} }       'future'     { FutureToken {} } @@ -309,6 +319,58 @@          | '^='     { AST.JSBwXorAssign  (mkJSAnnot $1) }          | '|='     { AST.JSBwOrAssign   (mkJSAnnot $1) } +-- IdentifierName ::                                                        See 7.6+--         IdentifierStart+--         IdentifierName IdentifierPart+-- Note: This production needs to precede the productions for all keyword+-- statements and PrimaryExpression. Contra the Happy documentation, in the+-- case of a reduce/reduce conflict, the *later* rule takes precedence, and+-- the ambiguity of, for example, `{break}` needs to resolve in favor of+-- `break` as a keyword and not as an identifier in property shorthand+-- syntax.+-- TODO: make this include any reserved word too, including future ones+IdentifierName :: { AST.JSExpression }+IdentifierName : Identifier {$1}+             | 'break'      { AST.JSIdentifier (mkJSAnnot $1) "break" }+             | 'case'       { AST.JSIdentifier (mkJSAnnot $1) "case" }+             | 'catch'      { AST.JSIdentifier (mkJSAnnot $1) "catch" }+             | 'class'      { AST.JSIdentifier (mkJSAnnot $1) "class" }+             | 'const'      { AST.JSIdentifier (mkJSAnnot $1) "const" }+             | 'continue'   { AST.JSIdentifier (mkJSAnnot $1) "continue" }+             | 'debugger'   { AST.JSIdentifier (mkJSAnnot $1) "debugger" }+             | 'default'    { AST.JSIdentifier (mkJSAnnot $1) "default" }+             | 'delete'     { AST.JSIdentifier (mkJSAnnot $1) "delete" }+             | 'do'         { AST.JSIdentifier (mkJSAnnot $1) "do" }+             | 'else'       { AST.JSIdentifier (mkJSAnnot $1) "else" }+             | 'enum'       { AST.JSIdentifier (mkJSAnnot $1) "enum" }+             | 'export'     { AST.JSIdentifier (mkJSAnnot $1) "export" }+             | 'extends'    { AST.JSIdentifier (mkJSAnnot $1) "extends" }+             | 'false'      { AST.JSIdentifier (mkJSAnnot $1) "false" }+             | 'finally'    { AST.JSIdentifier (mkJSAnnot $1) "finally" }+             | 'for'        { AST.JSIdentifier (mkJSAnnot $1) "for" }+             | 'function'   { AST.JSIdentifier (mkJSAnnot $1) "function" }+             | 'if'         { AST.JSIdentifier (mkJSAnnot $1) "if" }+             | 'in'         { AST.JSIdentifier (mkJSAnnot $1) "in" }+             | 'instanceof' { AST.JSIdentifier (mkJSAnnot $1) "instanceof" }+             | 'let'        { AST.JSIdentifier (mkJSAnnot $1) "let" }+             | 'new'        { AST.JSIdentifier (mkJSAnnot $1) "new" }+             | 'null'       { AST.JSIdentifier (mkJSAnnot $1) "null" }+             | 'of'         { AST.JSIdentifier (mkJSAnnot $1) "of" }+             | 'return'     { AST.JSIdentifier (mkJSAnnot $1) "return" }+             | 'static'     { AST.JSIdentifier (mkJSAnnot $1) "static" }+             | 'super'      { AST.JSIdentifier (mkJSAnnot $1) "super" }+             | 'switch'     { AST.JSIdentifier (mkJSAnnot $1) "switch" }+             | 'this'       { AST.JSIdentifier (mkJSAnnot $1) "this" }+             | 'throw'      { AST.JSIdentifier (mkJSAnnot $1) "throw" }+             | 'true'       { AST.JSIdentifier (mkJSAnnot $1) "true" }+             | 'try'        { AST.JSIdentifier (mkJSAnnot $1) "try" }+             | 'typeof'     { AST.JSIdentifier (mkJSAnnot $1) "typeof" }+             | 'var'        { AST.JSIdentifier (mkJSAnnot $1) "var" }+             | 'void'       { AST.JSIdentifier (mkJSAnnot $1) "void" }+             | 'while'      { AST.JSIdentifier (mkJSAnnot $1) "while" }+             | 'with'       { AST.JSIdentifier (mkJSAnnot $1) "with" }+             | 'future'     { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) }+ Var :: { AST.JSAnnot } Var : 'var' { mkJSAnnot $1 } @@ -381,7 +443,19 @@ New :: { AST.JSAnnot } New : 'new' { mkJSAnnot $1 } +Class :: { AST.JSAnnot }+Class : 'class' { mkJSAnnot $1 } +Extends :: { AST.JSAnnot }+Extends : 'extends' { mkJSAnnot $1 }++Static :: { AST.JSAnnot }+Static : 'static' { mkJSAnnot $1 }++Super :: { AST.JSExpression }+Super : 'super' { AST.JSLiteral (mkJSAnnot $1) "super" }++ Eof :: { AST.JSAnnot } Eof : 'tail' { mkJSAnnot $1 {- 'Eof' -} } @@ -432,68 +506,46 @@                   | Literal                  { $1 {- 'PrimaryExpression2' -} }                   | ArrayLiteral             { $1 {- 'PrimaryExpression3' -} }                   | ObjectLiteral            { $1 {- 'PrimaryExpression4' -} }-                  | SpreadExpression         { $1 {- 'PrimaryExpression5' -} }+                  | ClassExpression          { $1 }+                  | GeneratorExpression      { $1 }+                  | TemplateLiteral          { mkJSTemplateLiteral Nothing $1 {- 'PrimaryExpression6' -} }                   | LParen Expression RParen { AST.JSExpressionParen $1 $2 $3 }  -- Identifier ::                                                            See 7.6 --         IdentifierName but not ReservedWord--- IdentifierName ::                                                        See 7.6---         IdentifierStart---         IdentifierName IdentifierPart Identifier :: { AST.JSExpression } Identifier : 'ident' { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) }            | 'as'    { AST.JSIdentifier (mkJSAnnot $1) "as" }            | 'get'   { AST.JSIdentifier (mkJSAnnot $1) "get" }            | 'set'   { AST.JSIdentifier (mkJSAnnot $1) "set" }            | 'from'  { AST.JSIdentifier (mkJSAnnot $1) "from" }+           | 'yield' { AST.JSIdentifier (mkJSAnnot $1) "yield" } --- TODO: make this include any reserved word too, including future ones-IdentifierName :: { AST.JSExpression }-IdentifierName : Identifier {$1}-             | 'as'         { AST.JSIdentifier (mkJSAnnot $1) "as" }-             | 'break'      { AST.JSIdentifier (mkJSAnnot $1) "break" }-             | 'case'       { AST.JSIdentifier (mkJSAnnot $1) "case" }-             | 'catch'      { AST.JSIdentifier (mkJSAnnot $1) "catch" }-             | 'const'      { AST.JSIdentifier (mkJSAnnot $1) "const" }-             | 'continue'   { AST.JSIdentifier (mkJSAnnot $1) "continue" }-             | 'debugger'   { AST.JSIdentifier (mkJSAnnot $1) "debugger" }-             | 'default'    { AST.JSIdentifier (mkJSAnnot $1) "default" }-             | 'delete'     { AST.JSIdentifier (mkJSAnnot $1) "delete" }-             | 'do'         { AST.JSIdentifier (mkJSAnnot $1) "do" }-             | 'else'       { AST.JSIdentifier (mkJSAnnot $1) "else" }-             | 'enum'       { AST.JSIdentifier (mkJSAnnot $1) "enum" }-             | 'export'     { AST.JSIdentifier (mkJSAnnot $1) "export" }-             | 'false'      { AST.JSIdentifier (mkJSAnnot $1) "false" }-             | 'finally'    { AST.JSIdentifier (mkJSAnnot $1) "finally" }-             | 'for'        { AST.JSIdentifier (mkJSAnnot $1) "for" }-             | 'function'   { AST.JSIdentifier (mkJSAnnot $1) "function" }-             | 'from'       { AST.JSIdentifier (mkJSAnnot $1) "from" }-             | 'get'        { AST.JSIdentifier (mkJSAnnot $1) "get" }-             | 'if'         { AST.JSIdentifier (mkJSAnnot $1) "if" }-             | 'in'         { AST.JSIdentifier (mkJSAnnot $1) "in" }-             | 'instanceof' { AST.JSIdentifier (mkJSAnnot $1) "instanceof" }-             | 'let'        { AST.JSIdentifier (mkJSAnnot $1) "let" }-             | 'new'        { AST.JSIdentifier (mkJSAnnot $1) "new" }-             | 'null'       { AST.JSIdentifier (mkJSAnnot $1) "null" }-             | 'of'         { AST.JSIdentifier (mkJSAnnot $1) "of" }-             | 'return'     { AST.JSIdentifier (mkJSAnnot $1) "return" }-             | 'set'        { AST.JSIdentifier (mkJSAnnot $1) "set" }-             | 'switch'     { AST.JSIdentifier (mkJSAnnot $1) "switch" }-             | 'this'       { AST.JSIdentifier (mkJSAnnot $1) "this" }-             | 'throw'      { AST.JSIdentifier (mkJSAnnot $1) "throw" }-             | 'true'       { AST.JSIdentifier (mkJSAnnot $1) "true" }-             | 'try'        { AST.JSIdentifier (mkJSAnnot $1) "try" }-             | 'typeof'     { AST.JSIdentifier (mkJSAnnot $1) "typeof" }-             | 'var'        { AST.JSIdentifier (mkJSAnnot $1) "var" }-             | 'void'       { AST.JSIdentifier (mkJSAnnot $1) "void" }-             | 'while'      { AST.JSIdentifier (mkJSAnnot $1) "while" }-             | 'with'       { AST.JSIdentifier (mkJSAnnot $1) "with" }-             | 'future'     { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) }+-- Must follow Identifier; when ambiguous, `yield` as a keyword should take+-- precedence over `yield` as an identifier name.+Yield :: { AST.JSAnnot }+Yield : 'yield' { mkJSAnnot $1 }   SpreadExpression :: { AST.JSExpression }-SpreadExpression : Spread Expression  { AST.JSSpreadExpression $1 $2 {- 'SpreadExpression' -} }+SpreadExpression : Spread AssignmentExpression  { AST.JSSpreadExpression $1 $2 {- 'SpreadExpression' -} } +TemplateLiteral :: { JSUntaggedTemplate }+TemplateLiteral : 'tmplnosub'              { JSUntaggedTemplate (mkJSAnnot $1) (tokenLiteral $1) [] }+                | 'tmplhead' TemplateParts { JSUntaggedTemplate (mkJSAnnot $1) (tokenLiteral $1) $2 }++TemplateParts :: { [AST.JSTemplatePart] }+TemplateParts : TemplateExpression RBrace 'tmplmiddle' TemplateParts { AST.JSTemplatePart $1 $2 ('}' : tokenLiteral $3) : $4 }+              | TemplateExpression RBrace 'tmpltail'                 { AST.JSTemplatePart $1 $2 ('}' : tokenLiteral $3) : [] }++-- This production only exists to ensure that inTemplate is set to True before+-- a tmplmiddle or tmpltail token is lexed. Since the lexer is always one token+-- ahead of the parser, setInTemplate needs to be called during a reduction+-- that is *two* tokens behind tmplmiddle/tmpltail. Accordingly,+-- TemplateExpression is always followed by an RBrace, which is lexed normally.+TemplateExpression :: { AST.JSExpression }+TemplateExpression : Expression {% setInTemplate True \$> $1 }+ -- ArrayLiteral :                                                        See 11.1.4 --        [ Elisionopt ] --        [ ElementList ]@@ -545,16 +597,28 @@ --        PropertyName : AssignmentExpression --        get PropertyName() { FunctionBody } --        set PropertyName( PropertySetParameterList ) { FunctionBody }--- TODO: not clear if get/set are keywords, or just used in a specific context. Puzzling. PropertyAssignment :: { AST.JSObjectProperty } PropertyAssignment : PropertyName Colon AssignmentExpression { AST.JSPropertyNameandValue $1 $2 [$3] }-                   -- Should be "get" in next, but is not a Token-                   | 'get' PropertyName LParen RParen FunctionBody-                       { AST.JSPropertyAccessor (AST.JSAccessorGet (mkJSAnnot $1)) $2 $3 [] $4 $5 }-                   -- Should be "set" in next, but is not a Token-                   | 'set' PropertyName LParen PropertySetParameterList RParen FunctionBody-                       { AST.JSPropertyAccessor (AST.JSAccessorSet (mkJSAnnot $1)) $2 $3 [$4] $5 $6 }+                   | IdentifierName { identifierToProperty $1 }+                   | MethodDefinition { AST.JSObjectMethod $1 } +-- TODO: not clear if get/set are keywords, or just used in a specific context. Puzzling.+MethodDefinition :: { AST.JSMethodDefinition }+MethodDefinition : PropertyName LParen RParen FunctionBody+                     { AST.JSMethodDefinition $1 $2 AST.JSLNil $3 $4 }+                 | PropertyName LParen FormalParameterList RParen FunctionBody+                     { AST.JSMethodDefinition $1 $2 $3 $4 $5 }+                 | '*' PropertyName LParen RParen FunctionBody+                     { AST.JSGeneratorMethodDefinition (mkJSAnnot $1) $2 $3 AST.JSLNil $4 $5 }+                 | '*' PropertyName LParen FormalParameterList RParen FunctionBody+                     { AST.JSGeneratorMethodDefinition (mkJSAnnot $1) $2 $3 $4 $5 $6 }+                 -- Should be "get" in next, but is not a Token+                 | 'get' PropertyName LParen RParen FunctionBody+                     { AST.JSPropertyAccessor (AST.JSAccessorGet (mkJSAnnot $1)) $2 $3 AST.JSLNil $4 $5 }+                 -- Should be "set" in next, but is not a Token+                 | 'set' PropertyName LParen PropertySetParameterList RParen FunctionBody+                     { AST.JSPropertyAccessor (AST.JSAccessorSet (mkJSAnnot $1)) $2 $3 (AST.JSLOne $4) $5 $6 }+ -- PropertyName :                                                        See 11.1.5 --        IdentifierName --        StringLiteral@@ -563,11 +627,12 @@ PropertyName : IdentifierName { propName $1 {- 'PropertyName1' -} }              | StringLiteral  { propName $1 {- 'PropertyName2' -} }              | NumericLiteral { propName $1 {- 'PropertyName3' -} }+             | LSquare AssignmentExpression RSquare { AST.JSPropertyComputed $1 $2 $3 {- 'PropertyName4' -} }  -- PropertySetParameterList :                                            See 11.1.5 --        Identifier PropertySetParameterList :: { AST.JSExpression }-PropertySetParameterList : Identifier { $1 {- 'PropertySetParameterList' -} }+PropertySetParameterList : AssignmentExpression { $1 {- 'PropertySetParameterList' -} }  -- MemberExpression :                                           See 11.2 --        PrimaryExpression@@ -580,6 +645,9 @@                  | FunctionExpression  { $1 {- 'MemberExpression2' -} }                  | MemberExpression LSquare Expression RSquare { AST.JSMemberSquare $1 $2 $3 $4 {- 'MemberExpression3' -} }                  | MemberExpression Dot IdentifierName         { AST.JSMemberDot $1 $2 $3       {- 'MemberExpression4' -} }+                 | MemberExpression TemplateLiteral            { mkJSTemplateLiteral (Just $1) $2 }+                 | Super LSquare Expression RSquare            { AST.JSMemberSquare $1 $2 $3 $4 }+                 | Super Dot IdentifierName                    { AST.JSMemberDot $1 $2 $3 }                  | New MemberExpression Arguments              { mkJSMemberNew $1 $2 $3         {- 'MemberExpression5' -} }  -- NewExpression :                                              See 11.2@@ -597,12 +665,16 @@ CallExpression :: { AST.JSExpression } CallExpression : MemberExpression Arguments                     { mkJSMemberExpression $1 $2 {- 'CallExpression1' -} }+               | Super Arguments+                    { mkJSCallExpression $1 $2 }                | CallExpression Arguments                     { mkJSCallExpression $1 $2 {- 'CallExpression2' -} }                | CallExpression LSquare Expression RSquare                     { AST.JSCallExpressionSquare $1 $2 $3 $4 {- 'CallExpression3' -} }                | CallExpression Dot IdentifierName                     { AST.JSCallExpressionDot $1 $2 $3 {- 'CallExpression4' -} }+               | CallExpression TemplateLiteral+                    { mkJSTemplateLiteral (Just $1) $2 {- 'CallExpression5' -} }  -- Arguments :                                                  See 11.2 --        ()@@ -839,14 +911,17 @@ --        LeftHandSideExpression AssignmentOperator AssignmentExpression AssignmentExpression :: { AST.JSExpression } AssignmentExpression : ConditionalExpression { $1 {- 'AssignmentExpression1' -} }+                     | YieldExpression { $1 }                      | LeftHandSideExpression AssignmentOperator AssignmentExpression                        { AST.JSAssignExpression $1 $2 $3 {- 'AssignmentExpression2' -} }+                     | SpreadExpression { $1 }  -- AssignmentExpressionNoIn :                                                            See 11.13 --        ConditionalExpressionNoIn --        LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn AssignmentExpressionNoIn :: { AST.JSExpression } AssignmentExpressionNoIn : ConditionalExpressionNoIn { $1 {- 'AssignmentExpressionNoIn1' -} }+                         | YieldExpression { $1 }                          | LeftHandSideExpression AssignmentOperator AssignmentExpressionNoIn                            { AST.JSAssignExpression $1 $2 $3 {- 'AssignmentExpressionNoIn1' -} } @@ -958,14 +1033,14 @@ -- VariableDeclaration :                                          See 12.2 --         Identifier Initialiseropt VariableDeclaration :: { AST.JSExpression }-VariableDeclaration : Identifier SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpression1' -} }-                    | Identifier                                   { AST.JSVarInitExpression $1 AST.JSVarInitNone     {- 'JSVarInitExpression2' -} }+VariableDeclaration : PrimaryExpression SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpression1' -} }+                    | Identifier                                          { AST.JSVarInitExpression $1 AST.JSVarInitNone     {- 'JSVarInitExpression2' -} }  -- VariableDeclarationNoIn :                                      See 12.2 --         Identifier InitialiserNoInopt VariableDeclarationNoIn :: { AST.JSExpression }-VariableDeclarationNoIn : Identifier SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpressionInit2' -} }-                        | Identifier                                   { AST.JSVarInitExpression $1 AST.JSVarInitNone     {- 'JSVarInitExpression2' -} }+VariableDeclarationNoIn : PrimaryExpression SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpressionInit2' -} }+                        | Identifier                                          { AST.JSVarInitExpression $1 AST.JSVarInitNone     {- 'JSVarInitExpression2' -} }  -- EmptyStatement :                                                                         See 12.3 --         ;@@ -1024,6 +1099,12 @@                      { AST.JSForOf $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement 10'-} }                    | For LParen Var VariableDeclarationNoIn Of Expression RParen Statement                      { AST.JSForVarOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 11' -} }+                   | For LParen Const VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement+                     { AST.JSForConst $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement 12' -} }+                   | For LParen Const VariableDeclarationNoIn In Expression RParen Statement+                     { AST.JSForConstIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 13' -} }+                   | For LParen Const VariableDeclarationNoIn Of Expression RParen Statement+                     { AST.JSForConstOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 14' -} }  -- ContinueStatement :                                                                      See 12.7 --         continue [no LineTerminator here] Identifieropt ;@@ -1141,12 +1222,9 @@                            { AST.JSArrowExpression $1 $2 $3 }  ArrowParameterList :: { AST.JSArrowParameterList }-ArrowParameterList : Identifier-                      { AST.JSUnparenthesizedArrowParameter (identName $1)     }+ArrowParameterList : PrimaryExpression {%^ toArrowParameterList $1 }                    | LParen RParen                       { AST.JSParenthesizedArrowParameterList $1 AST.JSLNil $2 }-                   | LParen FormalParameterList RParen-                      { AST.JSParenthesizedArrowParameterList $1 $2 $3         }  StatementOrBlock :: { AST.JSStatement } StatementOrBlock : Block MaybeSemi		{ blockToStatement $1 $2 }@@ -1170,7 +1248,39 @@                  | Function LParen FormalParameterList RParen FunctionBody                     { AST.JSFunctionExpression $1 AST.JSIdentNone $2 $3 $4 $5           {- 'LambdaExpression2' -} } +-- GeneratorDeclaration :+--         function * BindingIdentifier ( FormalParameters ) { GeneratorBody }+--         function * ( FormalParameters ) { GeneratorBody }+GeneratorDeclaration :: { AST.JSStatement }+GeneratorDeclaration : NamedGeneratorExpression MaybeSemi  { expressionToStatement $1 $2 } +-- GeneratorExpression :+--         function * BindingIdentifieropt ( FormalParameters ) { GeneratorBody }+-- GeneratorBody :+--         FunctionBody+GeneratorExpression :: { AST.JSExpression }+GeneratorExpression : NamedGeneratorExpression { $1 }+                    | Function '*' LParen RParen FunctionBody+                        { AST.JSGeneratorExpression $1 (mkJSAnnot $2) AST.JSIdentNone $3 AST.JSLNil $4 $5 }+                    | Function '*' LParen FormalParameterList RParen FunctionBody+                        { AST.JSGeneratorExpression $1 (mkJSAnnot $2) AST.JSIdentNone $3 $4 $5 $6 }++NamedGeneratorExpression :: { AST.JSExpression }+NamedGeneratorExpression : Function '*' Identifier LParen RParen FunctionBody+                             { AST.JSGeneratorExpression $1 (mkJSAnnot $2) (identName $3) $4 AST.JSLNil $5 $6 }+                         | Function '*' Identifier LParen FormalParameterList RParen FunctionBody+                             { AST.JSGeneratorExpression $1 (mkJSAnnot $2) (identName $3) $4 $5 $6 $7 }++-- YieldExpression :+--         yield+--         yield [no LineTerminator here] AssignmentExpression+--         yield [no LineTerminator here] * AssignmentExpression+YieldExpression :: { AST.JSExpression }+YieldExpression : Yield { AST.JSYieldExpression $1 Nothing }+                | Yield AssignmentExpression { AST.JSYieldExpression $1 (Just $2) }+                | Yield '*' AssignmentExpression { AST.JSYieldFromExpression $1 (mkJSAnnot $2) $3 }++ IdentifierOpt :: { AST.JSIdent } IdentifierOpt : Identifier { identName $1     {- 'IdentifierOpt1' -} }               |            { AST.JSIdentNone  {- 'IdentifierOpt2' -} }@@ -1178,15 +1288,53 @@ -- FormalParameterList :                                                      See clause 13 --        Identifier --        FormalParameterList , Identifier-FormalParameterList :: { AST.JSCommaList AST.JSIdent }-FormalParameterList : Identifier                            { AST.JSLOne (identName $1)         {- 'FormalParameterList1' -} }-                    | FormalParameterList Comma Identifier  { AST.JSLCons $1 $2 (identName $3)  {- 'FormalParameterList2' -} }+FormalParameterList :: { AST.JSCommaList AST.JSExpression }+FormalParameterList : AssignmentExpression                           { AST.JSLOne $1         {- 'FormalParameterList1' -} }+                    | FormalParameterList Comma AssignmentExpression { AST.JSLCons $1 $2 $3  {- 'FormalParameterList2' -} }  -- FunctionBody :                                                             See clause 13 --        SourceElementsopt FunctionBody :: { AST.JSBlock } FunctionBody : Block                    { $1    {- 'FunctionBody1' -} } +-- ClassDeclaration :+--         class BindingIdentifier ClassTail+--         class ClassTail+-- ClassExpression :+--         class BindingIdentifieropt ClassTail+-- ClassTail :+--         ClassHeritageopt { ClassBodyopt }+ClassDeclaration :: { AST.JSStatement }+ClassDeclaration : Class Identifier ClassHeritage LBrace ClassBody RBrace { AST.JSClass $1 (identName $2) $3 $4 $5 $6 AST.JSSemiAuto }++ClassExpression :: { AST.JSExpression }+ClassExpression : Class Identifier ClassHeritage LBrace ClassBody RBrace { AST.JSClassExpression $1 (identName $2)  $3 $4 $5 $6 }+                | Class            ClassHeritage LBrace ClassBody RBrace { AST.JSClassExpression $1 AST.JSIdentNone $2 $3 $4 $5 }++-- ClassHeritage :+--         extends LeftHandSideExpression+ClassHeritage :: { AST.JSClassHeritage }+ClassHeritage : Extends LeftHandSideExpression { AST.JSExtends $1 $2 }+              |                                { AST.JSExtendsNone }++-- ClassBody :+--         ClassElementList+-- ClassElementList :+--         ClassElement+--         ClassElementList ClassElement+ClassBody :: { [AST.JSClassElement] }+ClassBody :                        { [] }+          | ClassBody ClassElement { $1 ++ [$2] }++-- ClassElement :+--         MethodDefinition+--         static MethodDefinition+--         ;+ClassElement :: { AST.JSClassElement }+ClassElement : MethodDefinition        { AST.JSClassInstanceMethod $1 }+             | Static MethodDefinition { AST.JSClassStaticMethod $1 $2 }+             | Semi                    { AST.JSClassSemi $1 }+ -- Program :                                                                  See clause 14 --        SourceElementsopt @@ -1225,6 +1373,8 @@ ImportDeclaration :: { AST.JSImportDeclaration } ImportDeclaration : ImportClause FromClause AutoSemi                           { AST.JSImportDeclaration $1 $2 $3 }+                  | 'string' AutoSemi+                          { AST.JSImportDeclarationBare (mkJSAnnot $1) (tokenLiteral $1) $2 }  ImportClause :: { AST.JSImportClause } ImportClause : IdentifierName@@ -1270,11 +1420,11 @@ -- [ ]    export Declaration -- [ ]    Declaration : -- [ ]       HoistableDeclaration--- [ ]       ClassDeclaration+-- [x]       ClassDeclaration -- [x]       LexicalDeclaration -- [ ]    HoistableDeclaration : -- [x]       FunctionDeclaration--- [ ]       GeneratorDeclaration+-- [x]       GeneratorDeclaration -- [ ]       AsyncFunctionDeclaration -- [ ]       AsyncGeneratorDeclaration -- [ ]    export default HoistableDeclaration[Default]@@ -1289,6 +1439,10 @@                          { AST.JSExport $1 $2         {- 'ExportDeclaration3' -} }                   | FunctionDeclaration AutoSemi                          { AST.JSExport $1 $2         {- 'ExportDeclaration4' -} }+                  | GeneratorDeclaration AutoSemi+                         { AST.JSExport $1 $2         {- 'ExportDeclaration5' -} }+                  | ClassDeclaration AutoSemi+                         { AST.JSExport $1 $2         {- 'ExportDeclaration6' -} }  -- ExportClause : --           { }@@ -1332,15 +1486,17 @@  -- Need this type while build the AST, but is not actually part of the AST. data JSArguments = JSArguments AST.JSAnnot (AST.JSCommaList AST.JSExpression) AST.JSAnnot    -- ^lb, args, rb-+data JSUntaggedTemplate = JSUntaggedTemplate !AST.JSAnnot !String ![AST.JSTemplatePart] -- lquot, head, parts  blockToStatement :: AST.JSBlock -> AST.JSSemi -> AST.JSStatement blockToStatement (AST.JSBlock a b c) s = AST.JSStatementBlock a b c s  expressionToStatement :: AST.JSExpression -> AST.JSSemi -> AST.JSStatement expressionToStatement (AST.JSFunctionExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSFunction a b c d e f s+expressionToStatement (AST.JSGeneratorExpression a b c@(AST.JSIdentName{}) d e f g) s = AST.JSGenerator a b c d e f g s expressionToStatement (AST.JSAssignExpression lhs op rhs) s = AST.JSAssignStatement lhs op rhs s expressionToStatement (AST.JSMemberExpression e l a r) s = AST.JSMethodCall e l a r s+expressionToStatement (AST.JSClassExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSClass a b c d e f s expressionToStatement exp s = AST.JSExpressionStatement exp s  @@ -1359,6 +1515,9 @@ mkJSAnnot :: Token -> AST.JSAnnot mkJSAnnot a = AST.JSAnnot (tokenSpan a) (tokenComment a) +mkJSTemplateLiteral :: Maybe AST.JSExpression -> JSUntaggedTemplate -> AST.JSExpression+mkJSTemplateLiteral tag (JSUntaggedTemplate a h ps) = AST.JSTemplateLiteral tag a h ps+ -- --------------------------------------------------------------------- -- | mkUnary : The parser detects '+' and '-' as the binary version of these -- operator. This function converts from the binary version to the unary@@ -1380,5 +1539,18 @@ propName (AST.JSOctal a s) = AST.JSPropertyNumber a s propName (AST.JSStringLiteral a s) = AST.JSPropertyString a s propName x = error $ "Cannot convert '" ++ show x ++ "' to a JSPropertyName."++identifierToProperty :: AST.JSExpression -> AST.JSObjectProperty+identifierToProperty (AST.JSIdentifier a s) = AST.JSPropertyIdentRef a s+identifierToProperty x = error $ "Cannot convert '" ++ show x ++ "' to a JSObjectProperty."++toArrowParameterList :: AST.JSExpression -> Token -> Alex AST.JSArrowParameterList+toArrowParameterList (AST.JSIdentifier a s)          = const . return $ AST.JSUnparenthesizedArrowParameter (AST.JSIdentName a s)+toArrowParameterList (AST.JSExpressionParen lb x rb) = const . return $ AST.JSParenthesizedArrowParameterList lb (commasToCommaList x) rb+toArrowParameterList _                               = parseError++commasToCommaList :: AST.JSExpression -> AST.JSCommaList AST.JSExpression+commasToCommaList (AST.JSCommaExpression l c r) = AST.JSLCons (commasToCommaList l) c r+commasToCommaList x = AST.JSLOne x  }
src/Language/JavaScript/Parser/Lexer.x view
@@ -15,6 +15,7 @@     , alexError     , runAlex     , alexTestTokeniser+    , setInTemplate     ) where  import Language.JavaScript.Parser.LexerUtils@@ -187,12 +188,21 @@ @IdentifierPart = @IdentifierStart | $UnicodeCombiningMark | $UnicodeDigit | UnicodeConnectorPunctuation         [\\] @UnicodeEscapeSequence | $ZWNJ | $ZWJ +-- TemplateCharacter ::+--         $ [lookahead ≠ { ]+--         \ EscapeSequence+--         LineContinuation+--         LineTerminatorSequence+--         SourceCharacter but not one of ` or \ or $ or LineTerminator+@TemplateCharacters = (\$* ($any_unicode_char # [\$\\`\{] | \\ $any_unicode_char) | \\ $any_unicode_char | \{)* \$*+ -- ! ------------------------------------------------- Terminals tokens :-  -- State: 0 is regex allowed, 1 is / or /= allowed+-- 2 is a special state for parsing characters inside templates -<0> () ; -- { registerStates lexToken reg divide }+<0> () ; -- { registerStates lexToken reg divide template }  -- Skip Whitespace <reg,divide> $white_char+   { adapt (mkString wsToken) }@@ -246,6 +256,13 @@   +<reg,divide> "`" @TemplateCharacters "`" { adapt (mkString' NoSubstitutionTemplateToken) }+<reg,divide> "`" @TemplateCharacters "${" { adapt (mkString' TemplateHeadToken) }+<template>   @TemplateCharacters "${" { adapt (mkString' TemplateMiddleToken) }+<template>   @TemplateCharacters "`" { adapt (mkString' TemplateTailToken) }+++ -- TODO: Work in SignedInteger  -- DecimalLiteral= {Non Zero Digits}+ '.' {Digit}* ('e' | 'E' ) {Non Zero Digits}+ {Digit}*@@ -372,8 +389,11 @@     lt  <- getLastToken     case lt of         TailToken {} -> alexEOF-        _other ->-            case alexScan inp (classifyToken lt) of+        _other -> do+            isInTmpl <- getInTemplate+            let state = if isInTmpl then template else classifyToken lt+            setInTemplate False -- the inTemplate condition only needs to last for one token+            case alexScan inp state of                 AlexEOF        -> do                     tok <- tailToken                     setLastToken tok@@ -476,6 +496,12 @@ setComment :: [Token] -> Alex () setComment cs = Alex $ \s -> Right (s{alex_ust=(alex_ust s){comment=cs }}, ()) +getInTemplate :: Alex Bool+getInTemplate = Alex $ \s@AlexState{alex_ust=ust} -> Right (s, inTemplate ust)++setInTemplate :: Bool -> Alex ()+setInTemplate it = Alex $ \s -> Right (s{alex_ust=(alex_ust s){inTemplate=it}}, ())+ alexEOF :: Alex Token alexEOF = return (EOFToken tokenPosnEmpty []) @@ -507,6 +533,7 @@     , ( "case", CaseToken )     , ( "catch", CatchToken ) +    , ( "class", ClassToken )     , ( "const", ConstToken ) -- not a keyword, nominally a future reserved word, but actually in use      , ( "continue", ContinueToken )@@ -518,6 +545,7 @@      , ( "enum", EnumToken )  -- not a keyword,  nominally a future reserved word, but actually in use     , ( "export", ExportToken )+    , ( "extends", ExtendsToken )      , ( "false", FalseToken ) -- boolean literal @@ -536,6 +564,8 @@      , ( "of", OfToken )     , ( "return", ReturnToken )+    , ( "static", StaticToken )+    , ( "super", SuperToken )     , ( "switch", SwitchToken )     , ( "this", ThisToken )     , ( "throw", ThrowToken )@@ -546,6 +576,7 @@     , ( "void", VoidToken )     , ( "while", WhileToken )     , ( "with", WithToken )+    , ( "yield", YieldToken )     -- TODO: no idea if these are reserved or not, but they are needed     --       handled in parser, in the Identifier rule     , ( "as", AsToken ) -- not reserved@@ -564,12 +595,12 @@       -- Future Reserved Words-    , ( "class",    FutureToken )+    -- ( "class",    FutureToken ) **** an actual token, used in productions     -- ( "code",    FutureToken ) **** not any more     -- ( "const",   FutureToken ) **** an actual token, used in productions     -- enum                    **** an actual token, used in productions-    , ( "extends",  FutureToken )-    , ( "super",    FutureToken )+    -- ( "extends",  FutureToken ) **** an actual token, used in productions+    -- ( "super",    FutureToken ) **** an actual token, used in productions       -- Strict mode FutureReservedWords@@ -584,9 +615,9 @@     , ( "private",     FutureToken )     , ( "protected",   FutureToken )     , ( "public",      FutureToken )-    , ( "static",      FutureToken )+    -- ( "static",      FutureToken ) **** an actual token, used in productions     -- ( "strict",     FutureToken )  *** not any more-    , ( "yield",       FutureToken)+    -- ( "yield",       FutureToken) **** an actual token, used in productions    ] } 
src/Language/JavaScript/Parser/LexerUtils.hs view
@@ -14,6 +14,7 @@     ( StartCode     , symbolToken     , mkString+    , mkString'     , commentToken     , wsToken     , regExToken@@ -36,6 +37,9 @@  mkString :: (Monad m) => (TokenPosn -> String -> Token) -> TokenPosn -> Int -> String -> m Token mkString toToken loc len str = return (toToken loc (take len str))++mkString' :: (Monad m) => (TokenPosn -> String -> [CommentAnnotation] -> Token) -> TokenPosn -> Int -> String -> m Token+mkString' toToken loc len str = return (toToken loc (take len str) [])  decimalToken :: TokenPosn -> String -> Token decimalToken loc str = DecimalToken loc str []
src/Language/JavaScript/Parser/ParserMonad.hs view
@@ -21,12 +21,14 @@ data AlexUserState = AlexUserState     { previousToken :: !Token   -- ^the previous token     , comment :: [Token]        -- ^the previous comment, if any+    , inTemplate :: Bool        -- ^whether the parser is expecting template characters     }  alexInitUserState :: AlexUserState alexInitUserState = AlexUserState     { previousToken = initToken     , comment = []+    , inTemplate = False     }  initToken :: Token
src/Language/JavaScript/Parser/Token.hs view
@@ -59,6 +59,7 @@     | BreakToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | CaseToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | CatchToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | ClassToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ConstToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | LetToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ContinueToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }@@ -68,6 +69,7 @@     | DoToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ElseToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | EnumToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | ExtendsToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | FalseToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | FinallyToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ForToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }@@ -80,6 +82,8 @@     | NullToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | OfToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ReturnToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | StaticToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | SuperToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | SwitchToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ThisToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ThrowToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }@@ -89,6 +93,7 @@     | VarToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | VoidToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | WhileToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | YieldToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ImportToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | WithToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }     | ExportToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }@@ -152,6 +157,12 @@     | LeftParenToken { tokenSpan :: !TokenPosn, tokenComment :: ![CommentAnnotation]  }     | RightParenToken { tokenSpan :: !TokenPosn, tokenComment :: ![CommentAnnotation]  }     | CondcommentEndToken { tokenSpan :: !TokenPosn, tokenComment :: ![CommentAnnotation]  }++    -- Template literal lexical components+    | NoSubstitutionTemplateToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | TemplateHeadToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | TemplateMiddleToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }+    | TemplateTailToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }      -- Special cases     | AsToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation]  }
src/Language/JavaScript/Pretty/Printer.hs view
@@ -77,20 +77,25 @@     (|>) pacc (JSCallExpression       ex lb xs rb)            = pacc |> ex |> lb |> "(" |> xs |> rb |> ")"     (|>) pacc (JSCallExpressionDot    ex os xs)               = pacc |> ex |> os |> "." |> xs     (|>) pacc (JSCallExpressionSquare ex als xs ars)          = pacc |> ex |> als |> "[" |> xs |> ars |> "]"+    (|>) pacc (JSClassExpression      annot n h lb xs rb)     = pacc |> annot |> "class" |> n |> h |> lb |> "{" |> xs |> rb |> "}"     (|>) pacc (JSCommaExpression      le c re)                = pacc |> le |> c |> "," |> re     (|>) pacc (JSExpressionBinary     lhs op rhs)             = pacc |> lhs |> op |> rhs     (|>) pacc (JSExpressionParen      alp e arp)              = pacc |> alp |> "(" |> e |> arp |> ")"     (|>) pacc (JSExpressionPostfix    xs op)                  = pacc |> xs |> op     (|>) pacc (JSExpressionTernary    cond h v1 c v2)         = pacc |> cond |> h |> "?" |> v1 |> c |> ":" |> v2     (|>) pacc (JSFunctionExpression   annot n lb x2s rb x3)   = pacc |> annot |> "function" |> n |> lb |> "(" |> x2s |> rb |> ")" |> x3+    (|>) pacc (JSGeneratorExpression  annot s n lb x2s rb x3) = pacc |> annot |> "function" |> s |> "*" |> n |> lb |> "(" |> x2s |> rb |> ")" |> x3     (|>) pacc (JSMemberDot            xs dot n)               = pacc |> xs |> "." |> dot |> n     (|>) pacc (JSMemberExpression     e lb a rb)              = pacc |> e |> lb |> "(" |> a |> rb |> ")"     (|>) pacc (JSMemberNew            a lb n rb s)            = pacc |> a |> "new" |> lb |> "(" |> n |> rb |> ")" |> s     (|>) pacc (JSMemberSquare         xs als e ars)           = pacc |> xs |> als |> "[" |> e |> ars |> "]"     (|>) pacc (JSNewExpression        n e)                    = pacc |> n |> "new" |> e     (|>) pacc (JSObjectLiteral        alb xs arb)             = pacc |> alb |> "{" |> xs |> arb |> "}"+    (|>) pacc (JSTemplateLiteral      t a h ps)               = pacc |> t |> a |> h |> ps     (|>) pacc (JSUnaryExpression      op x)                   = pacc |> op |> x     (|>) pacc (JSVarInitExpression    x1 x2)                  = pacc |> x1 |> x2+    (|>) pacc (JSYieldExpression      y x)                    = pacc |> y |> "yield" |> x+    (|>) pacc (JSYieldFromExpression  y s x)                  = pacc |> y |> "yield" |> s |> "*" |> x     (|>) pacc (JSSpreadExpression     a e)                    = pacc |> a |> "..." |> e  instance RenderJS JSArrowParameterList where@@ -220,6 +225,7 @@ instance RenderJS JSStatement where     (|>) pacc (JSStatementBlock alb blk arb s)             = pacc |> alb |> "{" |> blk |> arb |> "}" |> s     (|>) pacc (JSBreak annot mi s)                         = pacc |> annot |> "break" |> mi |> s+    (|>) pacc (JSClass annot n h lb xs rb s)               = pacc |> annot |> "class" |> n |> h |> lb |> "{" |> xs |> rb |> "}" |> s     (|>) pacc (JSContinue annot mi s)                      = pacc |> annot |> "continue" |> mi |> s     (|>) pacc (JSConstant annot xs s)                      = pacc |> annot |> "const" |> xs |> s     (|>) pacc (JSDoWhile ad x1 aw alb x2 arb x3)           = pacc |> ad |> "do" |> x1 |> aw |> "while" |> alb |> "(" |> x2 |> arb |> ")" |> x3@@ -231,9 +237,13 @@     (|>) pacc (JSForLet af alb v x1s s1 x2s s2 x3s arb x4) = pacc |> af |> "for" |> alb |> "(" |> "let" |> v |> x1s |> s1 |> ";" |> x2s |> s2 |> ";" |> x3s |> arb |> ")" |> x4     (|>) pacc (JSForLetIn af alb v x1 i x2 arb x3)         = pacc |> af |> "for" |> alb |> "(" |> "let" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3     (|>) pacc (JSForLetOf af alb v x1 i x2 arb x3)         = pacc |> af |> "for" |> alb |> "(" |> "let" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3+    (|>) pacc (JSForConst af alb v x1s s1 x2s s2 x3s arb x4) = pacc |> af |> "for" |> alb |> "(" |> "const" |> v |> x1s |> s1 |> ";" |> x2s |> s2 |> ";" |> x3s |> arb |> ")" |> x4+    (|>) pacc (JSForConstIn af alb v x1 i x2 arb x3)         = pacc |> af |> "for" |> alb |> "(" |> "const" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3+    (|>) pacc (JSForConstOf af alb v x1 i x2 arb x3)         = pacc |> af |> "for" |> alb |> "(" |> "const" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3     (|>) pacc (JSForOf af alb x1s i x2 arb x3)             = pacc |> af |> "for" |> alb |> "(" |> x1s |> i |> x2 |> arb |> ")" |> x3     (|>) pacc (JSForVarOf af alb v x1 i x2 arb x3)         = pacc |> af |> "for" |> alb |> "(" |> "var" |> v |> x1 |> i |> x2 |> arb |> ")" |> x3     (|>) pacc (JSFunction af n alb x2s arb x3 s)           = pacc |> af |> "function" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s+    (|>) pacc (JSGenerator af as n alb x2s arb x3 s)       = pacc |> af |> "function" |> as |> "*" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s     (|>) pacc (JSIf annot alb x1 arb x2s)                  = pacc |> annot |> "if" |> alb |> "(" |> x1 |> arb |> ")" |> x2s     (|>) pacc (JSIfElse annot alb x1 arb x2s ea x3s)       = pacc |> annot |> "if" |> alb |> "(" |> x1 |> arb |> ")" |> x2s |> ea |> "else" |> x3s     (|>) pacc (JSLabelled l c v)                           = pacc |> l |> c |> ":" |> v@@ -264,13 +274,20 @@     (|>) pacc (JSBlock alb ss arb) = pacc |> alb |> "{" |> ss |> arb |> "}"  instance RenderJS JSObjectProperty where-    (|>) pacc (JSPropertyAccessor     s n alp ps arp b)       = pacc |> s |> n |> alp |> "(" |> ps |> arp |> ")" |> b     (|>) pacc (JSPropertyNameandValue n c vs)                 = pacc |> n |> c |> ":" |> vs+    (|>) pacc (JSPropertyIdentRef     a s)                    = pacc |> a |> s+    (|>) pacc (JSObjectMethod         m)                      = pacc |> m +instance RenderJS JSMethodDefinition where+    (|>) pacc (JSMethodDefinition          n alp ps arp b)   = pacc |> n |> alp |> "(" |> ps |> arp |> ")" |> b+    (|>) pacc (JSGeneratorMethodDefinition s n alp ps arp b) = pacc |> s |> "*" |> n |> alp |> "(" |> ps |> arp |> ")" |> b+    (|>) pacc (JSPropertyAccessor          s n alp ps arp b) = pacc |> s |> n |> alp |> "(" |> ps |> arp |> ")" |> b+ instance RenderJS JSPropertyName where     (|>) pacc (JSPropertyIdent a s)  = pacc |> a |> s     (|>) pacc (JSPropertyString a s) = pacc |> a |> s     (|>) pacc (JSPropertyNumber a s) = pacc |> a |> s+    (|>) pacc (JSPropertyComputed lb x rb) = pacc |> lb |> "[" |> x |> rb |> "]"  instance RenderJS JSAccessor where     (|>) pacc (JSAccessorGet annot) = pacc |> annot |> "get"@@ -285,6 +302,7 @@  instance RenderJS JSImportDeclaration where     (|>) pacc (JSImportDeclaration imp from annot) = pacc |> imp |> from |> annot+    (|>) pacc (JSImportDeclarationBare annot m s) = pacc |> annot |> m |> s  instance RenderJS JSImportClause where     (|>) pacc (JSImportClauseDefault x) = pacc |> x@@ -339,5 +357,23 @@ instance RenderJS JSVarInitializer where     (|>) pacc (JSVarInit a x) = pacc |> a |> "=" |> x     (|>) pacc JSVarInitNone   = pacc++instance RenderJS [JSTemplatePart] where+    (|>) = foldl' (|>)++instance RenderJS JSTemplatePart where+    (|>) pacc (JSTemplatePart e a s) = pacc |> e |> a |> s++instance RenderJS JSClassHeritage where+    (|>) pacc (JSExtends a e) = pacc |> a |> "extends" |> e+    (|>) pacc JSExtendsNone   = pacc++instance RenderJS [JSClassElement] where+    (|>) = foldl' (|>)++instance RenderJS JSClassElement where+    (|>) pacc (JSClassInstanceMethod m) = pacc |> m+    (|>) pacc (JSClassStaticMethod a m) = pacc |> a |> "static" |> m+    (|>) pacc (JSClassSemi a)           = pacc |> a |> ";"  -- EOF
src/Language/JavaScript/Process/Minify.hs view
@@ -41,6 +41,7 @@ fixStmt :: JSAnnot -> JSSemi -> JSStatement -> JSStatement fixStmt a s (JSStatementBlock _lb ss _rb _) = fixStatementBlock a s ss fixStmt a s (JSBreak _ i _) = JSBreak a (fixSpace i) s+fixStmt a s (JSClass _ n h _ ms _ _) = JSClass a (fixSpace n) (fixSpace h) emptyAnnot (fixEmpty ms) emptyAnnot s fixStmt a s (JSConstant _ ss _) = JSConstant a (fixVarList ss) s fixStmt a s (JSContinue _ i _) = JSContinue a (fixSpace i) s fixStmt a s (JSDoWhile _ st _ _ e _ _) = JSDoWhile a (mkStatementBlock noSemi st) emptyAnnot emptyAnnot (fixEmpty e) emptyAnnot s@@ -51,9 +52,13 @@ fixStmt a s (JSForLet _ _ _ el1 _ el2 _ el3 _ st) = JSForLet a emptyAnnot spaceAnnot (fixEmpty el1) emptyAnnot (fixEmpty el2) emptyAnnot (fixEmpty el3) emptyAnnot (fixStmtE s st) fixStmt a s (JSForLetIn _ _ _ e1 op e2 _ st) = JSForLetIn a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSForLetOf _ _ _ e1 op e2 _ st) = JSForLetOf a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st)+fixStmt a s (JSForConst _ _ _ el1 _ el2 _ el3 _ st) = JSForConst a emptyAnnot spaceAnnot (fixEmpty el1) emptyAnnot (fixEmpty el2) emptyAnnot (fixEmpty el3) emptyAnnot (fixStmtE s st)+fixStmt a s (JSForConstIn _ _ _ e1 op e2 _ st) = JSForConstIn a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st)+fixStmt a s (JSForConstOf _ _ _ e1 op e2 _ st) = JSForConstOf a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSForOf _ _ e1 op e2 _ st) = JSForOf a emptyAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSForVarOf _ _ _ e1 op e2 _ st) = JSForVarOf a emptyAnnot spaceAnnot (fixEmpty e1) (fixSpace op) (fixSpace e2) emptyAnnot (fixStmtE s st) fixStmt a s (JSFunction _ n _ ps _ blk _) = JSFunction a (fixSpace n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s+fixStmt a s (JSGenerator _ _ n _ ps _ blk _) = JSGenerator a emptyAnnot (fixEmpty n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s fixStmt a s (JSIf _ _ e _ st) = JSIf a emptyAnnot (fixEmpty e) emptyAnnot (fixIfElseBlock emptyAnnot s st) fixStmt a s (JSIfElse _ _ e _ (JSEmptyStatement _) _ sf) = JSIfElse a emptyAnnot (fixEmpty e) emptyAnnot (JSEmptyStatement emptyAnnot) emptyAnnot (fixStmt spaceAnnot s sf) fixStmt a s (JSIfElse _ _ e _ st _ sf) = JSIfElse a emptyAnnot (fixEmpty e) emptyAnnot (mkStatementBlock noSemi st) emptyAnnot (fixIfElseBlock spaceAnnot s sf)@@ -153,20 +158,25 @@     fix a (JSCallExpression       ex _ xs _)          = JSCallExpression (fix a ex) emptyAnnot (fixEmpty xs) emptyAnnot     fix a (JSCallExpressionDot    ex _ xs)            = JSCallExpressionDot (fix a ex) emptyAnnot (fixEmpty xs)     fix a (JSCallExpressionSquare ex _ xs _)          = JSCallExpressionSquare (fix a ex) emptyAnnot (fixEmpty xs) emptyAnnot+    fix a (JSClassExpression      _ n h _ ms _)       = JSClassExpression a (fixSpace n) (fixSpace h) emptyAnnot (fixEmpty ms) emptyAnnot     fix a (JSCommaExpression      le _ re)            = JSCommaExpression (fix a le) emptyAnnot (fixEmpty re)     fix a (JSExpressionBinary     lhs op rhs)         = fixBinOpExpression a op lhs rhs     fix _ (JSExpressionParen      _ e _)              = JSExpressionParen emptyAnnot (fixEmpty e) emptyAnnot     fix a (JSExpressionPostfix    e op)               = JSExpressionPostfix (fix a e) (fixEmpty op)     fix a (JSExpressionTernary    cond _ v1 _ v2)     = JSExpressionTernary (fix a cond) emptyAnnot (fixEmpty v1) emptyAnnot (fixEmpty v2)     fix a (JSFunctionExpression   _ n _ x2s _ x3)     = JSFunctionExpression a (fixSpace n) emptyAnnot (fixEmpty x2s) emptyAnnot (fixEmpty x3)+    fix a (JSGeneratorExpression  _ _ n _ x2s _ x3)   = JSGeneratorExpression a emptyAnnot (fixEmpty n) emptyAnnot (fixEmpty x2s) emptyAnnot (fixEmpty x3)     fix a (JSMemberDot            xs _ n)             = JSMemberDot (fix a xs) emptyAnnot (fixEmpty n)     fix a (JSMemberExpression     e _ args _)         = JSMemberExpression (fix a e) emptyAnnot (fixEmpty args) emptyAnnot     fix a (JSMemberNew            _ n _ s _)          = JSMemberNew a (fix spaceAnnot n) emptyAnnot (fixEmpty s) emptyAnnot     fix a (JSMemberSquare         xs _ e _)           = JSMemberSquare (fix a xs) emptyAnnot (fixEmpty e) emptyAnnot     fix a (JSNewExpression        _ e)                = JSNewExpression a (fixSpace e)     fix _ (JSObjectLiteral        _ xs _)             = JSObjectLiteral emptyAnnot (fixEmpty xs) emptyAnnot+    fix a (JSTemplateLiteral      t _ s ps)           = JSTemplateLiteral (fmap (fix a) t) emptyAnnot s (map fixEmpty ps)     fix a (JSUnaryExpression      op x)               = let (ta, fop) = fixUnaryOp a op in JSUnaryExpression fop (fix ta x)     fix a (JSVarInitExpression    x1 x2)              = JSVarInitExpression (fix a x1) (fixEmpty x2)+    fix a (JSYieldExpression      _ x)                = JSYieldExpression a (fixSpace x)+    fix a (JSYieldFromExpression  _ _ x)              = JSYieldFromExpression a emptyAnnot (fixEmpty x)     fix a (JSSpreadExpression     _ e)                = JSSpreadExpression a (fixEmpty e)  instance MinifyJS JSArrowParameterList where@@ -289,6 +299,7 @@                     JSImportClauseNamed {} -> emptyAnnot                     JSImportClauseDefaultNameSpace {} -> spaceAnnot                     JSImportClauseDefaultNamed {} -> emptyAnnot+    fix a (JSImportDeclarationBare _ m _) = JSImportDeclarationBare a m noSemi  instance MinifyJS JSImportClause where     fix _ (JSImportClauseDefault n) = JSImportClauseDefault (fixSpace n)@@ -352,13 +363,20 @@   instance MinifyJS JSObjectProperty where-    fix a (JSPropertyAccessor     s n _ ps _ b) = JSPropertyAccessor (fix a s) (fixSpace n) emptyAnnot (map fixEmpty ps) emptyAnnot (fixEmpty b)     fix a (JSPropertyNameandValue n _ vs)       = JSPropertyNameandValue (fix a n) emptyAnnot (map fixEmpty vs)+    fix a (JSPropertyIdentRef     _ s)          = JSPropertyIdentRef a s+    fix a (JSObjectMethod         m)            = JSObjectMethod (fix a m) +instance MinifyJS JSMethodDefinition where+    fix a (JSMethodDefinition          n _ ps _ b)   = JSMethodDefinition                     (fix a n)    emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty b)+    fix _ (JSGeneratorMethodDefinition _ n _ ps _ b) = JSGeneratorMethodDefinition emptyAnnot (fixEmpty n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty b)+    fix a (JSPropertyAccessor          s n _ ps _ b) = JSPropertyAccessor          (fix a s)  (fixSpace n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty b)+ instance MinifyJS JSPropertyName where     fix a (JSPropertyIdent _ s)  = JSPropertyIdent a s     fix a (JSPropertyString _ s) = JSPropertyString a s     fix a (JSPropertyNumber _ s) = JSPropertyNumber a s+    fix _ (JSPropertyComputed _ x _) = JSPropertyComputed emptyAnnot (fixEmpty x) emptyAnnot  instance MinifyJS JSAccessor where     fix a (JSAccessorGet _) = JSAccessorGet a@@ -393,6 +411,22 @@ instance MinifyJS JSVarInitializer where     fix a (JSVarInit _ x) = JSVarInit a (fix emptyAnnot x)     fix _ JSVarInitNone = JSVarInitNone+++instance MinifyJS JSTemplatePart where+    fix _ (JSTemplatePart e _ s) = JSTemplatePart (fixEmpty e) emptyAnnot s+++instance MinifyJS JSClassHeritage where+    fix _ JSExtendsNone = JSExtendsNone+    fix a (JSExtends _ e) = JSExtends a (fixSpace e)+++instance MinifyJS [JSClassElement] where+    fix _ [] = []+    fix a (JSClassInstanceMethod m:t) = JSClassInstanceMethod (fix a m) : fixEmpty t+    fix a (JSClassStaticMethod _ m:t) = JSClassStaticMethod a (fixSpace m) : fixEmpty t+    fix a (JSClassSemi _:t) = fix a t   spaceAnnot :: JSAnnot
test/Test/Language/Javascript/ExpressionParser.hs view
@@ -51,11 +51,20 @@         testExpr "{x:1}"        `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'x') [JSDecimal '1']]))"         testExpr "{x:1,y:2}"    `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'x') [JSDecimal '1'],JSPropertyNameandValue (JSIdentifier 'y') [JSDecimal '2']]))"         testExpr "{x:1,}"       `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'x') [JSDecimal '1'],JSComma]))"+        testExpr "{yield:1}"    `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'yield') [JSDecimal '1']]))"+        testExpr "{x}"          `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyIdentRef 'x']))"+        testExpr "{x,}"         `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyIdentRef 'x',JSComma]))"+        testExpr "{set x([a,b]=y) {this.a=a;this.b=b}}" `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyAccessor JSAccessorSet (JSIdentifier 'x') (JSOpAssign ('=',JSArrayLiteral [JSIdentifier 'a',JSComma,JSIdentifier 'b'],JSIdentifier 'y')) (JSBlock [JSOpAssign ('=',JSMemberDot (JSLiteral 'this',JSIdentifier 'a'),JSIdentifier 'a'),JSSemicolon,JSOpAssign ('=',JSMemberDot (JSLiteral 'this',JSIdentifier 'b'),JSIdentifier 'b')])]))"         testExpr "a={if:1,interface:2}" `shouldBe` "Right (JSAstExpression (JSOpAssign ('=',JSIdentifier 'a',JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'if') [JSDecimal '1'],JSPropertyNameandValue (JSIdentifier 'interface') [JSDecimal '2']])))"         testExpr "a={\n  values: 7,\n}\n"   `shouldBe` "Right (JSAstExpression (JSOpAssign ('=',JSIdentifier 'a',JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'values') [JSDecimal '7'],JSComma])))"-        testExpr "x={get foo() {return 1},set foo(a) {x=a}}" `shouldBe` "Right (JSAstExpression (JSOpAssign ('=',JSIdentifier 'x',JSObjectLiteral [JSPropertyAccessor JSAccessorGet (JSIdentifier 'foo') [] (JSBlock [JSReturn JSDecimal '1' ]),JSPropertyAccessor JSAccessorSet (JSIdentifier 'foo') [JSIdentifier 'a'] (JSBlock [JSOpAssign ('=',JSIdentifier 'x',JSIdentifier 'a')])])))"-        testExpr "{evaluate:evaluate,load:function load(s){if(x)return s;1}}" `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'evaluate') [JSIdentifier 'evaluate'],JSPropertyNameandValue (JSIdentifier 'load') [JSFunctionExpression 'load' (JSIdentifier 's') (JSBlock [JSIf (JSIdentifier 'x') (JSReturn JSIdentifier 's' JSSemicolon),JSDecimal '1']))]]))"+        testExpr "x={get foo() {return 1},set foo(a) {x=a}}" `shouldBe` "Right (JSAstExpression (JSOpAssign ('=',JSIdentifier 'x',JSObjectLiteral [JSPropertyAccessor JSAccessorGet (JSIdentifier 'foo') () (JSBlock [JSReturn JSDecimal '1' ]),JSPropertyAccessor JSAccessorSet (JSIdentifier 'foo') (JSIdentifier 'a') (JSBlock [JSOpAssign ('=',JSIdentifier 'x',JSIdentifier 'a')])])))"+        testExpr "{evaluate:evaluate,load:function load(s){if(x)return s;1}}" `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'evaluate') [JSIdentifier 'evaluate'],JSPropertyNameandValue (JSIdentifier 'load') [JSFunctionExpression 'load' (JSIdentifier 's') (JSBlock [JSIf (JSIdentifier 'x') (JSReturn JSIdentifier 's' JSSemicolon),JSDecimal '1'])]]))"         testExpr "obj = { name : 'A', 'str' : 'B', 123 : 'C', }" `shouldBe` "Right (JSAstExpression (JSOpAssign ('=',JSIdentifier 'obj',JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'name') [JSStringLiteral 'A'],JSPropertyNameandValue (JSIdentifier ''str'') [JSStringLiteral 'B'],JSPropertyNameandValue (JSIdentifier '123') [JSStringLiteral 'C'],JSComma])))"+        testExpr "{[x]:1}"      `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSPropertyNameandValue (JSPropertyComputed (JSIdentifier 'x')) [JSDecimal '1']]))"+        testExpr "{ a(x,y) {}, 'blah blah'() {} }" `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock []),JSMethodDefinition (JSIdentifier ''blah blah'') () (JSBlock [])]))"+        testExpr "{[x]() {}}"   `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSMethodDefinition (JSPropertyComputed (JSIdentifier 'x')) () (JSBlock [])]))"+        testExpr "{*a(x,y) {yield y;}}" `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSGeneratorMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock [JSYieldExpression (JSIdentifier 'y'),JSSemicolon])]))"+        testExpr "{*[x]({y},...z) {}}"  `shouldBe` "Right (JSAstExpression (JSObjectLiteral [JSGeneratorMethodDefinition (JSPropertyComputed (JSIdentifier 'x')) (JSObjectLiteral [JSPropertyIdentRef 'y'],JSSpreadExpression (JSIdentifier 'z')) (JSBlock [])]))"      it "unary expression" $ do         testExpr "delete y" `shouldBe` "Right (JSAstExpression (JSUnaryExpression ('delete',JSIdentifier 'y')))"@@ -120,15 +129,33 @@         testExpr "x|=1"         `shouldBe` "Right (JSAstExpression (JSOpAssign ('|=',JSIdentifier 'x',JSDecimal '1')))"      it "function expression" $ do-        testExpr "function(){}"     `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' () (JSBlock []))))"-        testExpr "function(a){}"    `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSIdentifier 'a') (JSBlock []))))"-        testExpr "function(a,b){}"  `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock []))))"+        testExpr "function(){}"     `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' () (JSBlock [])))"+        testExpr "function(a){}"    `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSIdentifier 'a') (JSBlock [])))"+        testExpr "function(a,b){}"  `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock [])))"+        testExpr "function(...a){}" `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSSpreadExpression (JSIdentifier 'a')) (JSBlock [])))"+        testExpr "function(a=1){}"  `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSOpAssign ('=',JSIdentifier 'a',JSDecimal '1')) (JSBlock [])))"+        testExpr "function([a,b]){}" `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSArrayLiteral [JSIdentifier 'a',JSComma,JSIdentifier 'b']) (JSBlock [])))"+        testExpr "function([a,...b]){}" `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSArrayLiteral [JSIdentifier 'a',JSComma,JSSpreadExpression (JSIdentifier 'b')]) (JSBlock [])))"+        testExpr "function({a,b}){}" `shouldBe` "Right (JSAstExpression (JSFunctionExpression '' (JSObjectLiteral [JSPropertyIdentRef 'a',JSPropertyIdentRef 'b']) (JSBlock [])))"         testExpr "a => {}"          `shouldBe` "Right (JSAstExpression (JSArrowExpression (JSIdentifier 'a') => JSStatementBlock []))"         testExpr "(a) => { a + 2 }" `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSIdentifier 'a')) => JSStatementBlock [JSExpressionBinary ('+',JSIdentifier 'a',JSDecimal '2')]))"         testExpr "(a, b) => {}"     `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSIdentifier 'a',JSIdentifier 'b')) => JSStatementBlock []))"         testExpr "(a, b) => a + b"  `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSIdentifier 'a',JSIdentifier 'b')) => JSExpressionBinary ('+',JSIdentifier 'a',JSIdentifier 'b')))"         testExpr "() => { 42 }"     `shouldBe` "Right (JSAstExpression (JSArrowExpression (()) => JSStatementBlock [JSDecimal '42']))"+        testExpr "(a, ...b) => b"   `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSIdentifier 'a',JSSpreadExpression (JSIdentifier 'b'))) => JSIdentifier 'b'))"+        testExpr "(a,b=1) => a + b" `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSIdentifier 'a',JSOpAssign ('=',JSIdentifier 'b',JSDecimal '1'))) => JSExpressionBinary ('+',JSIdentifier 'a',JSIdentifier 'b')))"+        testExpr "([a,b]) => a + b" `shouldBe` "Right (JSAstExpression (JSArrowExpression ((JSArrayLiteral [JSIdentifier 'a',JSComma,JSIdentifier 'b'])) => JSExpressionBinary ('+',JSIdentifier 'a',JSIdentifier 'b')))" +    it "generator expression" $ do+        testExpr "function*(){}"        `shouldBe` "Right (JSAstExpression (JSGeneratorExpression '' () (JSBlock [])))"+        testExpr "function*(a){}"       `shouldBe` "Right (JSAstExpression (JSGeneratorExpression '' (JSIdentifier 'a') (JSBlock [])))"+        testExpr "function*(a,b){}"     `shouldBe` "Right (JSAstExpression (JSGeneratorExpression '' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock [])))"+        testExpr "function*(a,...b){}"  `shouldBe` "Right (JSAstExpression (JSGeneratorExpression '' (JSIdentifier 'a',JSSpreadExpression (JSIdentifier 'b')) (JSBlock [])))"+        testExpr "function*f(){}"       `shouldBe` "Right (JSAstExpression (JSGeneratorExpression 'f' () (JSBlock [])))"+        testExpr "function*f(a){}"      `shouldBe` "Right (JSAstExpression (JSGeneratorExpression 'f' (JSIdentifier 'a') (JSBlock [])))"+        testExpr "function*f(a,b){}"    `shouldBe` "Right (JSAstExpression (JSGeneratorExpression 'f' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock [])))"+        testExpr "function*f(a,...b){}" `shouldBe` "Right (JSAstExpression (JSGeneratorExpression 'f' (JSIdentifier 'a',JSSpreadExpression (JSIdentifier 'b')) (JSBlock [])))"+     it "member expression" $ do         testExpr "x[y]"         `shouldBe` "Right (JSAstExpression (JSMemberSquare (JSIdentifier 'x',JSIdentifier 'y')))"         testExpr "x[y][z]"      `shouldBe` "Right (JSAstExpression (JSMemberSquare (JSMemberSquare (JSIdentifier 'x',JSIdentifier 'y'),JSIdentifier 'z')))"@@ -145,6 +172,28 @@      it "spread expression" $         testExpr "... x"        `shouldBe` "Right (JSAstExpression (JSSpreadExpression (JSIdentifier 'x')))"++    it "template literal" $ do+        testExpr "``"            `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'``',[])))"+        testExpr "`$`"           `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`$`',[])))"+        testExpr "`$\\n`"        `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`$\\n`',[])))"+        testExpr "`\\${x}`"      `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`\\${x}`',[])))"+        testExpr "`$ {x}`"       `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`$ {x}`',[])))"+        testExpr "`\n\n`"        `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`\n\n`',[])))"+        testExpr "`${x+y} ${z}`" `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`${',[(JSExpressionBinary ('+',JSIdentifier 'x',JSIdentifier 'y'),'} ${'),(JSIdentifier 'z','}`')])))"+        testExpr "`<${x} ${y}>`" `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((),'`<${',[(JSIdentifier 'x','} ${'),(JSIdentifier 'y','}>`')])))"+        testExpr "tag `xyz`"     `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((JSIdentifier 'tag'),'`xyz`',[])))"+        testExpr "tag()`xyz`"    `shouldBe` "Right (JSAstExpression (JSTemplateLiteral ((JSMemberExpression (JSIdentifier 'tag',JSArguments ())),'`xyz`',[])))"++    it "yield" $ do+        testExpr "yield"       `shouldBe` "Right (JSAstExpression (JSYieldExpression ()))"+        testExpr "yield a + b" `shouldBe` "Right (JSAstExpression (JSYieldExpression (JSExpressionBinary ('+',JSIdentifier 'a',JSIdentifier 'b'))))"+        testExpr "yield* g()"  `shouldBe` "Right (JSAstExpression (JSYieldFromExpression (JSMemberExpression (JSIdentifier 'g',JSArguments ()))))"++    it "class expression" $ do+        testExpr "class Foo extends Bar { a(x,y) {} *b() {} }" `shouldBe` "Right (JSAstExpression (JSClassExpression 'Foo' (JSIdentifier 'Bar') [JSMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock []),JSGeneratorMethodDefinition (JSIdentifier 'b') () (JSBlock [])]))"+        testExpr "class { static get [a]() {}; }" `shouldBe` "Right (JSAstExpression (JSClassExpression '' () [JSClassStaticMethod (JSPropertyAccessor JSAccessorGet (JSPropertyComputed (JSIdentifier 'a')) () (JSBlock [])),JSClassSemi]))"+        testExpr "class Foo extends Bar { a(x,y) { super(x); } }" `shouldBe` "Right (JSAstExpression (JSClassExpression 'Foo' (JSIdentifier 'Bar') [JSMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock [JSCallExpression (JSLiteral 'super',JSArguments (JSIdentifier 'x')),JSSemicolon])]))"   testExpr :: String -> String
test/Test/Language/Javascript/Minify.hs view
@@ -41,6 +41,11 @@         minifyExpr " { b : 2 , } " `shouldBe` "{b:2}"         minifyExpr " { c : 3 , d : 4 , } " `shouldBe` "{c:3,d:4}"         minifyExpr " { 'str' : true , 42 : false , } " `shouldBe` "{'str':true,42:false}"+        minifyExpr " { x , } " `shouldBe` "{x}"+        minifyExpr " { [ x + y ] : 1 } " `shouldBe` "{[x+y]:1}"+        minifyExpr " { a ( x, y ) { } } " `shouldBe` "{a(x,y){}}"+        minifyExpr " { [ x + y ] ( ) { } } " `shouldBe` "{[x+y](){}}"+        minifyExpr " { * a ( x, y ) { } } " `shouldBe` "{*a(x,y){}}"      it "parentheses" $ do         minifyExpr " ( 'hello' ) " `shouldBe` "('hello')"@@ -105,13 +110,26 @@         minifyExpr " function ( ) { } " `shouldBe` "function(){}"         minifyExpr " function ( a ) { } " `shouldBe` "function(a){}"         minifyExpr " function ( a , b ) { return a + b ; } " `shouldBe` "function(a,b){return a+b}"+        minifyExpr " function ( a , ...b ) { return b ; } " `shouldBe` "function(a,...b){return b}"+        minifyExpr " function ( a = 1 , b = 2 ) { return a + b ; } " `shouldBe` "function(a=1,b=2){return a+b}"+        minifyExpr " function ( [ a , b ] ) { return b ; } " `shouldBe` "function([a,b]){return b}"+        minifyExpr " function ( { a , b , } ) { return a + b ; } " `shouldBe` "function({a,b}){return a+b}"          minifyExpr "a => {}" `shouldBe` "a=>{}"         minifyExpr "(a) => {}" `shouldBe` "(a)=>{}"         minifyExpr "( a ) => { a + 2 }" `shouldBe` "(a)=>a+2"         minifyExpr "(a, b) => a + b" `shouldBe` "(a,b)=>a+b"         minifyExpr "() => { 42 }" `shouldBe` "()=>42"+        minifyExpr "(a, ...b) => b" `shouldBe` "(a,...b)=>b"+        minifyExpr "(a = 1, b = 2) => a + b" `shouldBe` "(a=1,b=2)=>a+b"+        minifyExpr "( [ a , b ] ) => a + b" `shouldBe` "([a,b])=>a+b"+        minifyExpr "( { a , b , } ) => a + b" `shouldBe` "({a,b})=>a+b" +    it "generator" $ do+        minifyExpr " function * ( ) { } " `shouldBe` "function*(){}"+        minifyExpr " function * ( a ) { yield * a ; } " `shouldBe` "function*(a){yield*a}"+        minifyExpr " function * ( a , b ) { yield a + b ; } " `shouldBe` "function*(a,b){yield a+b}"+     it "calls" $ do         minifyExpr " a ( ) " `shouldBe` "a()"         minifyExpr " b ( ) ( ) " `shouldBe` "b()()"@@ -121,6 +139,7 @@     it "property accessor" $ do         minifyExpr " { get foo ( ) { return x } } " `shouldBe` "{get foo(){return x}}"         minifyExpr " { set foo ( a ) { x = a } } " `shouldBe` "{set foo(a){x=a}}"+        minifyExpr " { set foo ( [ a , b ] ) { x = a } } " `shouldBe` "{set foo([a,b]){x=a}}"      it "string concatenation" $ do         minifyExpr " 'ab' + \"cd\" " `shouldBe` "'abcd'"@@ -136,7 +155,19 @@     it "spread exporession" $         minifyExpr " ... x " `shouldBe` "...x" +    it "template literal" $ do+        minifyExpr " ` a + b + ${ c + d } + ... ` " `shouldBe` "` a + b + ${c+d} + ... `"+        minifyExpr " tagger () ` a + b ` " `shouldBe` "tagger()` a + b `" +    it "class" $ do+        minifyExpr " class   Foo   {\n  a() {\n    return 0;\n  };\n  static [ b ] ( x ) {}\n } " `shouldBe` "class Foo{a(){return 0}static[b](x){}}"+        minifyExpr " class { static get a() { return 0; } static set a(v) {} } " `shouldBe` "class{static get a(){return 0}static set a(v){}}"+        minifyExpr " class   { ; ; ; } " `shouldBe` "class{}"+        minifyExpr " class Foo extends Bar {} " `shouldBe` "class Foo extends Bar{}"+        minifyExpr " class extends (getBase()) {} " `shouldBe` "class extends(getBase()){}"+        minifyExpr " class extends [ Bar1, Bar2 ][getBaseIndex()] {} " `shouldBe` "class extends[Bar1,Bar2][getBaseIndex()]{}"++ testMinifyStmt :: Spec testMinifyStmt = describe "Minify statements:" $ do     forM_ [ "break", "continue", "return" ] $ \kw ->@@ -184,6 +215,9 @@         minifyStmt " for (let x ; y ; z) { } " `shouldBe` "for(let x;y;z){}"         minifyStmt " for ( let x in 5 ) { foo ( x++ ); y ++ ; } ;" `shouldBe` "for(let x in 5){foo(x++);y++}"         minifyStmt " for ( let x of 5 ) { foo ( x++ ); y ++ ; } ;" `shouldBe` "for(let x of 5){foo(x++);y++}"+        minifyStmt " for (const x ; y ; z) { } " `shouldBe` "for(const x;y;z){}"+        minifyStmt " for ( const x in 5 ) { foo ( x ); y ++ ; } ;" `shouldBe` "for(const x in 5){foo(x);y++}"+        minifyStmt " for ( const x of 5 ) { foo ( x ); y ++ ; } ;" `shouldBe` "for(const x of 5){foo(x);y++}"         minifyStmt " for ( x of 5 ) { foo ( x++ ); y ++ ; } ;" `shouldBe` "for(x of 5){foo(x++);y++}"         minifyStmt " for ( var x of 5 ) { foo ( x++ ); y ++ ; } ;" `shouldBe` "for(var x of 5){foo(x++);y++}"     it "labelled" $ do@@ -194,7 +228,16 @@         minifyStmt " function f ( ) { } ; " `shouldBe` "function f(){}"         minifyStmt " function f ( a ) { } ; " `shouldBe` "function f(a){}"         minifyStmt " function f ( a , b ) { return a + b ; } ; " `shouldBe` "function f(a,b){return a+b}"+        minifyStmt " function f ( a , ... b ) { return b ; } ; " `shouldBe` "function f(a,...b){return b}"+        minifyStmt " function f ( a = 1 , b = 2 ) { return a + b ; } ; " `shouldBe` "function f(a=1,b=2){return a+b}"+        minifyStmt " function f ( [ a , b ] ) { return a + b ; } ; " `shouldBe` "function f([a,b]){return a+b}"+        minifyStmt " function f ( { a , b , } ) { return a + b ; } ; " `shouldBe` "function f({a,b}){return a+b}" +    it "generator" $ do+        minifyStmt " function * f ( ) { } ; " `shouldBe` "function*f(){}"+        minifyStmt " function * f ( a ) { yield * a ; } ; " `shouldBe` "function*f(a){yield*a}"+        minifyStmt " function * f ( a , b ) { yield a + b ; } ; " `shouldBe` "function*f(a,b){yield a+b}"+     it "with" $ do         minifyStmt " with ( x ) { } ; " `shouldBe` "with(x){}"         minifyStmt " with ({ first: 'John' }) { foo ('Hello '+first); }" `shouldBe` "with({first:'John'})foo('Hello '+first)"@@ -225,10 +268,16 @@         minifyStmt " var d = 1, x = 2 ; " `shouldBe` "var d=1,x=2"         minifyStmt " let c = 1 ; " `shouldBe` "let c=1"         minifyStmt " let d = 1, x = 2 ; " `shouldBe` "let d=1,x=2"+        minifyStmt " const { a : [ b , c ] } = d; " `shouldBe` "const{a:[b,c]}=d"      it "string concatenation" $         minifyStmt " f (\"ab\"+\"cd\") " `shouldBe` "f('abcd')" +    it "class" $ do+        minifyStmt " class   Foo   {\n  a() {\n    return 0;\n  }\n  static b ( x ) {}\n } " `shouldBe` "class Foo{a(){return 0}static b(x){}}"+        minifyStmt " class Foo extends Bar {} " `shouldBe` "class Foo extends Bar{}"+        minifyStmt " class Foo extends (getBase()) {} " `shouldBe` "class Foo extends(getBase()){}"+        minifyStmt " class Foo extends [ Bar1, Bar2 ][getBaseIndex()] {} " `shouldBe` "class Foo extends[Bar1,Bar2][getBaseIndex()]{}"  testMinifyProg :: Spec testMinifyProg = describe "Minify programs:" $ do@@ -267,6 +316,7 @@         minifyModule "import  def, * as foo  from   \"mod\"  ; " `shouldBe` "import def,* as foo from\"mod\""         minifyModule "import  { baz,  bar as   foo }  from   \"mod\"  ; " `shouldBe` "import{baz,bar as foo}from\"mod\""         minifyModule "import  def, { baz,  bar as   foo }  from   \"mod\"  ; " `shouldBe` "import def,{baz,bar as foo}from\"mod\""+        minifyModule "import     \"mod\"  ; " `shouldBe` "import\"mod\""      it "export" $ do         minifyModule " export { } ; " `shouldBe` "export{}"@@ -276,6 +326,7 @@         minifyModule " export { } from \"mod\" ; " `shouldBe` "export{}from\"mod\""         minifyModule " export const a = 1 ; " `shouldBe` "export const a=1"         minifyModule " export function f () {  } ; " `shouldBe` "export function f(){}"+        minifyModule " export function * f () {  } ; " `shouldBe` "export function*f(){}"  -- ----------------------------------------------------------------------------- -- Minify test helpers.
test/Test/Language/Javascript/ProgramParser.hs view
@@ -73,15 +73,15 @@      it "programs" $ do         testProg "newlines=spaces.match(/\\n/g)" `shouldBe` "Right (JSAstProgram [JSOpAssign ('=',JSIdentifier 'newlines',JSMemberExpression (JSMemberDot (JSIdentifier 'spaces',JSIdentifier 'match'),JSArguments (JSRegEx '/\\n/g')))])"-        testProg "Animal=function(){return this.name};" `shouldBe` "Right (JSAstProgram [JSOpAssign ('=',JSIdentifier 'Animal',JSFunctionExpression '' () (JSBlock [JSReturn JSMemberDot (JSLiteral 'this',JSIdentifier 'name') ]))),JSSemicolon])"-        testProg "$(img).click(function(){alert('clicked!')});" `shouldBe` "Right (JSAstProgram [JSCallExpression (JSCallExpressionDot (JSMemberExpression (JSIdentifier '$',JSArguments (JSIdentifier 'img')),JSIdentifier 'click'),JSArguments (JSFunctionExpression '' () (JSBlock [JSMethodCall (JSIdentifier 'alert',JSArguments (JSStringLiteral 'clicked!'))])))),JSSemicolon])"-        testProg "function() {\nz = function z(o) {\nreturn r;\n};}" `shouldBe` "Right (JSAstProgram [JSFunctionExpression '' () (JSBlock [JSOpAssign ('=',JSIdentifier 'z',JSFunctionExpression 'z' (JSIdentifier 'o') (JSBlock [JSReturn JSIdentifier 'r' JSSemicolon]))),JSSemicolon]))])"-        testProg "function() {\nz = function /*z*/(o) {\nreturn r;\n};}" `shouldBe` "Right (JSAstProgram [JSFunctionExpression '' () (JSBlock [JSOpAssign ('=',JSIdentifier 'z',JSFunctionExpression '' (JSIdentifier 'o') (JSBlock [JSReturn JSIdentifier 'r' JSSemicolon]))),JSSemicolon]))])"+        testProg "Animal=function(){return this.name};" `shouldBe` "Right (JSAstProgram [JSOpAssign ('=',JSIdentifier 'Animal',JSFunctionExpression '' () (JSBlock [JSReturn JSMemberDot (JSLiteral 'this',JSIdentifier 'name') ])),JSSemicolon])"+        testProg "$(img).click(function(){alert('clicked!')});" `shouldBe` "Right (JSAstProgram [JSCallExpression (JSCallExpressionDot (JSMemberExpression (JSIdentifier '$',JSArguments (JSIdentifier 'img')),JSIdentifier 'click'),JSArguments (JSFunctionExpression '' () (JSBlock [JSMethodCall (JSIdentifier 'alert',JSArguments (JSStringLiteral 'clicked!'))]))),JSSemicolon])"+        testProg "function() {\nz = function z(o) {\nreturn r;\n};}" `shouldBe` "Right (JSAstProgram [JSFunctionExpression '' () (JSBlock [JSOpAssign ('=',JSIdentifier 'z',JSFunctionExpression 'z' (JSIdentifier 'o') (JSBlock [JSReturn JSIdentifier 'r' JSSemicolon])),JSSemicolon])])"+        testProg "function() {\nz = function /*z*/(o) {\nreturn r;\n};}" `shouldBe` "Right (JSAstProgram [JSFunctionExpression '' () (JSBlock [JSOpAssign ('=',JSIdentifier 'z',JSFunctionExpression '' (JSIdentifier 'o') (JSBlock [JSReturn JSIdentifier 'r' JSSemicolon])),JSSemicolon])])"         testProg "{zero}\nget;two\n{three\nfour;set;\n{\nsix;{seven;}\n}\n}" `shouldBe` "Right (JSAstProgram [JSStatementBlock [JSIdentifier 'zero'],JSIdentifier 'get',JSSemicolon,JSIdentifier 'two',JSStatementBlock [JSIdentifier 'three',JSIdentifier 'four',JSSemicolon,JSIdentifier 'set',JSSemicolon,JSStatementBlock [JSIdentifier 'six',JSSemicolon,JSStatementBlock [JSIdentifier 'seven',JSSemicolon]]]])"         testProg "{zero}\none1;two\n{three\nfour;five;\n{\nsix;{seven;}\n}\n}" `shouldBe` "Right (JSAstProgram [JSStatementBlock [JSIdentifier 'zero'],JSIdentifier 'one1',JSSemicolon,JSIdentifier 'two',JSStatementBlock [JSIdentifier 'three',JSIdentifier 'four',JSSemicolon,JSIdentifier 'five',JSSemicolon,JSStatementBlock [JSIdentifier 'six',JSSemicolon,JSStatementBlock [JSIdentifier 'seven',JSSemicolon]]]])"         testProg "v = getValue(execute(n[0], x)) in getValue(execute(n[1], x));"   `shouldBe` "Right (JSAstProgram [JSOpAssign ('=',JSIdentifier 'v',JSExpressionBinary ('in',JSMemberExpression (JSIdentifier 'getValue',JSArguments (JSMemberExpression (JSIdentifier 'execute',JSArguments (JSMemberSquare (JSIdentifier 'n',JSDecimal '0'),JSIdentifier 'x')))),JSMemberExpression (JSIdentifier 'getValue',JSArguments (JSMemberExpression (JSIdentifier 'execute',JSArguments (JSMemberSquare (JSIdentifier 'n',JSDecimal '1'),JSIdentifier 'x')))))),JSSemicolon])"         testProg "function Animal(name){if(!name)throw new Error('Must specify an animal name');this.name=name};Animal.prototype.toString=function(){return this.name};o=new Animal(\"bob\");o.toString()==\"bob\""-                                    `shouldBe` "Right (JSAstProgram [JSFunction 'Animal' (JSIdentifier 'name') (JSBlock [JSIf (JSUnaryExpression ('!',JSIdentifier 'name')) (JSThrow (JSMemberNew (JSIdentifier 'Error',JSArguments (JSStringLiteral 'Must specify an animal name')))),JSOpAssign ('=',JSMemberDot (JSLiteral 'this',JSIdentifier 'name'),JSIdentifier 'name')]),JSOpAssign ('=',JSMemberDot (JSMemberDot (JSIdentifier 'Animal',JSIdentifier 'prototype'),JSIdentifier 'toString'),JSFunctionExpression '' () (JSBlock [JSReturn JSMemberDot (JSLiteral 'this',JSIdentifier 'name') ]))),JSSemicolon,JSOpAssign ('=',JSIdentifier 'o',JSMemberNew (JSIdentifier 'Animal',JSArguments (JSStringLiteral \"bob\"))),JSSemicolon,JSExpressionBinary ('==',JSMemberExpression (JSMemberDot (JSIdentifier 'o',JSIdentifier 'toString'),JSArguments ()),JSStringLiteral \"bob\")])"+                                    `shouldBe` "Right (JSAstProgram [JSFunction 'Animal' (JSIdentifier 'name') (JSBlock [JSIf (JSUnaryExpression ('!',JSIdentifier 'name')) (JSThrow (JSMemberNew (JSIdentifier 'Error',JSArguments (JSStringLiteral 'Must specify an animal name')))),JSOpAssign ('=',JSMemberDot (JSLiteral 'this',JSIdentifier 'name'),JSIdentifier 'name')]),JSOpAssign ('=',JSMemberDot (JSMemberDot (JSIdentifier 'Animal',JSIdentifier 'prototype'),JSIdentifier 'toString'),JSFunctionExpression '' () (JSBlock [JSReturn JSMemberDot (JSLiteral 'this',JSIdentifier 'name') ])),JSSemicolon,JSOpAssign ('=',JSIdentifier 'o',JSMemberNew (JSIdentifier 'Animal',JSArguments (JSStringLiteral \"bob\"))),JSSemicolon,JSExpressionBinary ('==',JSMemberExpression (JSMemberDot (JSIdentifier 'o',JSIdentifier 'toString'),JSArguments ()),JSStringLiteral \"bob\")])"   testProg :: String -> String
test/Test/Language/Javascript/RoundTrip.hs view
@@ -39,9 +39,15 @@     it "object literals" $ do         testRT "/*a*/{/*b*/}"         testRT "/*a*/{/*b*/x/*c*/:/*d*/1/*e*/}"+        testRT "/*a*/{/*b*/x/*c*/}"+        testRT "/*a*/{/*b*/of/*c*/}"         testRT "x=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/y/*g*/:/*h*/2/*i*/}"         testRT "x=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/y/*g*/:/*h*/2/*i*/,/*j*/z/*k*/:/*l*/3/*m*/}"         testRT "a=/*a*/{/*b*/x/*c*/:/*d*/1/*e*/,/*f*/}"+        testRT "/*a*/{/*b*/[/*c*/x/*d*/+/*e*/y/*f*/]/*g*/:/*h*/1/*i*/}"+        testRT "/*a*/{/*b*/a/*c*/(/*d*/x/*e*/,/*f*/y/*g*/)/*h*/{/*i*/}/*j*/}"+        testRT "/*a*/{/*b*/[/*c*/x/*d*/+/*e*/y/*f*/]/*g*/(/*h*/)/*i*/{/*j*/}/*k*/}"+        testRT "/*a*/{/*b*/*/*c*/a/*d*/(/*e*/x/*f*/,/*g*/y/*h*/)/*i*/{/*j*/}/*k*/}"      it "miscellaneous" $ do         testRT "/*a*/(/*b*/56/*c*/)"@@ -61,6 +67,7 @@         testRT "/*a*/x/*b*/>=/*c*/y"         testRT "/*a*/x /*b*/instanceof /*c*/y"         testRT "/*a*/x/*b*/=/*c*/{/*d*/get/*e*/ foo/*f*/(/*g*/)/*h*/ {/*i*/return/*j*/ 1/*k*/}/*l*/,/*m*/set/*n*/ foo/*o*/(/*p*/a/*q*/) /*r*/{/*s*/x/*t*/=/*u*/a/*v*/}/*w*/}"+        testRT "x = { set foo(/*a*/[/*b*/a/*c*/,/*d*/b/*e*/]/*f*/=/*g*/y/*h*/) {} }"         testRT "... /*a*/ x"          testRT "a => {}"@@ -68,8 +75,26 @@         testRT "(a, b) => {}"         testRT "(a, b) => a + b"         testRT "() => { 42 }"+        testRT "(...a) => a"+        testRT "(a=1, b=2) => a + b"+        testRT "([a, b]) => a + b"+        testRT "({a, b}) => a + b" +        testRT "function (...a) {}"+        testRT "function (a=1, b=2) {}"+        testRT "function ([a, ...b]) {}"+        testRT "function ({a, b: c}) {}" +        testRT "/*a*/function/*b*/*/*c*/f/*d*/(/*e*/)/*f*/{/*g*/yield/*h*/a/*i*/}/*j*/"+        testRT "function*(a, b) { yield a ; yield b ; }"++        testRT "/*a*/`<${/*b*/x/*c*/}>`/*d*/"+        testRT "`\\${}`"+        testRT "`\n\n`"+        testRT "{}+``"+        -- ^ https://github.com/erikd/language-javascript/issues/104++     it "statement" $ do         testRT "if (1) {}"         testRT "if (1) {} else {}"@@ -87,6 +112,9 @@         testRT "for(let x;y;z){}"         testRT "for(let x in 5){}"         testRT "for(let x of 5){}"+        testRT "for(const x;y;z){}"+        testRT "for(const x in 5){}"+        testRT "for(const x of 5){}"         testRT "for(x of 5){}"         testRT "for(var x of 5){}"         testRT "var x=1;"@@ -105,6 +133,9 @@         testRT "switch (x) {default:break;}"         testRT "switch (x) {default:\ncase 1:break;}"         testRT "var x=1;let y=2;"+        testRT "var [x, y]=z;"+        testRT "let {x: [y]}=z;"+        testRT "let yield=1"      it "module" $ do         testRTModule "import  def  from 'mod'"@@ -121,6 +152,8 @@         testRTModule "export   {}  from \"mod\";"         testRTModule "export const a = 1 ; "         testRTModule "export function f () {  } ; "+        testRTModule "export function * f () {  } ; "+        testRTModule "export   class Foo\nextends Bar\n{ get a () { return 1 ; }  static b ( x,y ) {} ; }   ; "   testRT :: String -> Expectation
test/Test/Language/Javascript/StatementParser.hs view
@@ -54,6 +54,9 @@         testStmt "for(let x;y;z){}"     `shouldBe` "Right (JSAstStatement (JSForLet (JSVarInitExpression (JSIdentifier 'x') ) (JSIdentifier 'y') (JSIdentifier 'z') (JSStatementBlock [])))"         testStmt "for(let x in 5){}"    `shouldBe` "Right (JSAstStatement (JSForLetIn (JSVarInitExpression (JSIdentifier 'x') ) (JSDecimal '5') (JSStatementBlock [])))"         testStmt "for(let x of 5){}"    `shouldBe` "Right (JSAstStatement (JSForLetOf (JSVarInitExpression (JSIdentifier 'x') ) (JSDecimal '5') (JSStatementBlock [])))"+        testStmt "for(const x;y;z){}"   `shouldBe` "Right (JSAstStatement (JSForConst (JSVarInitExpression (JSIdentifier 'x') ) (JSIdentifier 'y') (JSIdentifier 'z') (JSStatementBlock [])))"+        testStmt "for(const x in 5){}"  `shouldBe` "Right (JSAstStatement (JSForConstIn (JSVarInitExpression (JSIdentifier 'x') ) (JSDecimal '5') (JSStatementBlock [])))"+        testStmt "for(const x of 5){}"  `shouldBe` "Right (JSAstStatement (JSForConstOf (JSVarInitExpression (JSIdentifier 'x') ) (JSDecimal '5') (JSStatementBlock [])))"         testStmt "for(x of 5){}"        `shouldBe` "Right (JSAstStatement (JSForOf JSIdentifier 'x' (JSDecimal '5') (JSStatementBlock [])))"         testStmt "for(var x of 5){}"    `shouldBe` "Right (JSAstStatement (JSForVarOf (JSVarInitExpression (JSIdentifier 'x') ) (JSDecimal '5') (JSStatementBlock [])))" @@ -61,6 +64,8 @@         testStmt "var x=1;"         `shouldBe` "Right (JSAstStatement (JSVariable (JSVarInitExpression (JSIdentifier 'x') [JSDecimal '1'])))"         testStmt "const x=1,y=2;"   `shouldBe` "Right (JSAstStatement (JSConstant (JSVarInitExpression (JSIdentifier 'x') [JSDecimal '1'],JSVarInitExpression (JSIdentifier 'y') [JSDecimal '2'])))"         testStmt "let x=1,y=2;"     `shouldBe` "Right (JSAstStatement (JSLet (JSVarInitExpression (JSIdentifier 'x') [JSDecimal '1'],JSVarInitExpression (JSIdentifier 'y') [JSDecimal '2'])))"+        testStmt "var [a,b]=x"      `shouldBe` "Right (JSAstStatement (JSVariable (JSVarInitExpression (JSArrayLiteral [JSIdentifier 'a',JSComma,JSIdentifier 'b']) [JSIdentifier 'x'])))"+        testStmt "const {a:b}=x"    `shouldBe` "Right (JSAstStatement (JSConstant (JSVarInitExpression (JSObjectLiteral [JSPropertyNameandValue (JSIdentifier 'a') [JSIdentifier 'b']]) [JSIdentifier 'x'])))"      it "break" $ do         testStmt "break;"       `shouldBe` "Right (JSAstStatement (JSBreak,JSSemicolon))"@@ -104,6 +109,26 @@         testStmt "try{}catch(a){}catch(b){}finally{}"   `shouldBe` "Right (JSAstStatement (JSTry (JSBlock [],[JSCatch (JSIdentifier 'a',JSBlock []),JSCatch (JSIdentifier 'b',JSBlock [])],JSFinally (JSBlock []))))"         testStmt "try{}catch(a){}catch(b){}"            `shouldBe` "Right (JSAstStatement (JSTry (JSBlock [],[JSCatch (JSIdentifier 'a',JSBlock []),JSCatch (JSIdentifier 'b',JSBlock [])],JSFinally ())))"         testStmt "try{}catch(a if true){}catch(b){}"    `shouldBe` "Right (JSAstStatement (JSTry (JSBlock [],[JSCatch (JSIdentifier 'a') if JSLiteral 'true' (JSBlock []),JSCatch (JSIdentifier 'b',JSBlock [])],JSFinally ())))"++    it "function" $ do+        testStmt "function x(){}"     `shouldBe` "Right (JSAstStatement (JSFunction 'x' () (JSBlock [])))"+        testStmt "function x(a){}"    `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSIdentifier 'a') (JSBlock [])))"+        testStmt "function x(a,b){}"  `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock [])))"+        testStmt "function x(...a){}" `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSSpreadExpression (JSIdentifier 'a')) (JSBlock [])))"+        testStmt "function x(a=1){}"  `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSOpAssign ('=',JSIdentifier 'a',JSDecimal '1')) (JSBlock [])))"+        testStmt "function x([a]){}"  `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSArrayLiteral [JSIdentifier 'a']) (JSBlock [])))"+        testStmt "function x({a}){}"  `shouldBe` "Right (JSAstStatement (JSFunction 'x' (JSObjectLiteral [JSPropertyIdentRef 'a']) (JSBlock [])))"++    it "generator" $ do+        testStmt "function* x(){}"       `shouldBe` "Right (JSAstStatement (JSGenerator 'x' () (JSBlock [])))"+        testStmt "function* x(a){}"      `shouldBe` "Right (JSAstStatement (JSGenerator 'x' (JSIdentifier 'a') (JSBlock [])))"+        testStmt "function* x(a,b){}"    `shouldBe` "Right (JSAstStatement (JSGenerator 'x' (JSIdentifier 'a',JSIdentifier 'b') (JSBlock [])))"+        testStmt "function* x(a,...b){}" `shouldBe` "Right (JSAstStatement (JSGenerator 'x' (JSIdentifier 'a',JSSpreadExpression (JSIdentifier 'b')) (JSBlock [])))"++    it "class" $ do+        testStmt "class Foo extends Bar { a(x,y) {} *b() {} }" `shouldBe` "Right (JSAstStatement (JSClass 'Foo' (JSIdentifier 'Bar') [JSMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock []),JSGeneratorMethodDefinition (JSIdentifier 'b') () (JSBlock [])]))"+        testStmt "class Foo { static get [a]() {}; }" `shouldBe` "Right (JSAstStatement (JSClass 'Foo' () [JSClassStaticMethod (JSPropertyAccessor JSAccessorGet (JSPropertyComputed (JSIdentifier 'a')) () (JSBlock [])),JSClassSemi]))"+        testStmt "class Foo extends Bar { a(x,y) { super[x](y); } }" `shouldBe` "Right (JSAstStatement (JSClass 'Foo' (JSIdentifier 'Bar') [JSMethodDefinition (JSIdentifier 'a') (JSIdentifier 'x',JSIdentifier 'y') (JSBlock [JSMethodCall (JSMemberSquare (JSLiteral 'super',JSIdentifier 'x'),JSArguments (JSIdentifier 'y')),JSSemicolon])]))"   testStmt :: String -> String