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 +15/−0
- language-javascript.cabal +1/−1
- src/Language/JavaScript/Parser/AST.hs +76/−7
- src/Language/JavaScript/Parser/Grammar7.y +241/−69
- src/Language/JavaScript/Parser/Lexer.x +39/−8
- src/Language/JavaScript/Parser/LexerUtils.hs +4/−0
- src/Language/JavaScript/Parser/ParserMonad.hs +2/−0
- src/Language/JavaScript/Parser/Token.hs +11/−0
- src/Language/JavaScript/Pretty/Printer.hs +37/−1
- src/Language/JavaScript/Process/Minify.hs +35/−1
- test/Test/Language/Javascript/ExpressionParser.hs +54/−5
- test/Test/Language/Javascript/Minify.hs +51/−0
- test/Test/Language/Javascript/ProgramParser.hs +5/−5
- test/Test/Language/Javascript/RoundTrip.hs +33/−0
- test/Test/Language/Javascript/StatementParser.hs +25/−0
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