From 28aaad30f6e50ff058bfb460143d50babadae8d8 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 20:35:43 -0500 Subject: [PATCH 1/9] Fix typos --- src/Language/JavaScript/Parser.hs | 2 -- src/Language/JavaScript/Parser/AST.hs | 2 +- src/Language/JavaScript/Parser/Grammar7.y | 6 +++--- test/Test/Language/Javascript/StatementParser.hs | 1 - 4 files changed, 4 insertions(+), 7 deletions(-) diff --git a/src/Language/JavaScript/Parser.hs b/src/Language/JavaScript/Parser.hs index a813bc9..80394ec 100644 --- a/src/Language/JavaScript/Parser.hs +++ b/src/Language/JavaScript/Parser.hs @@ -40,5 +40,3 @@ import Language.JavaScript.Parser.SrcLocation import Language.JavaScript.Pretty.Printer -- EOF - - diff --git a/src/Language/JavaScript/Parser/AST.hs b/src/Language/JavaScript/Parser/AST.hs index 53e6b31..9c6b55e 100644 --- a/src/Language/JavaScript/Parser/AST.hs +++ b/src/Language/JavaScript/Parser/AST.hs @@ -233,7 +233,7 @@ data JSCommaTrailingList a deriving (Data, Eq, Show, Typeable) -- ----------------------------------------------------------------------------- --- | Show the AST elements stipped of their JSAnnot data. +-- | Show the AST elements stripped of their JSAnnot data. -- Strip out the location info showStripped :: JSAST -> String diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index 1d4b2b9..b5c1ff7 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -498,9 +498,9 @@ Elision : Comma { [AST.JSArrayComma $1] {- 'Elision1' -} } -- { PropertyNameAndValueList } -- { PropertyNameAndValueList , } ObjectLiteral :: { AST.JSExpression } -ObjectLiteral : LBrace RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone AST.JSLNil) $2 {- 'ObjectLiteal1' -} } - | LBrace PropertyNameandValueList RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone $2) $3 {- 'ObjectLiteal2' -} } - | LBrace PropertyNameandValueList Comma RBrace { AST.JSObjectLiteral $1 (AST.JSCTLComma $2 $3) $4 {- 'ObjectLiteal3' -} } +ObjectLiteral : LBrace RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone AST.JSLNil) $2 {- 'ObjectLiteral1' -} } + | LBrace PropertyNameandValueList RBrace { AST.JSObjectLiteral $1 (AST.JSCTLNone $2) $3 {- 'ObjectLiteral2' -} } + | LBrace PropertyNameandValueList Comma RBrace { AST.JSObjectLiteral $1 (AST.JSCTLComma $2 $3) $4 {- 'ObjectLiteral3' -} } -- ::= ':' -- | ',' ':' diff --git a/test/Test/Language/Javascript/StatementParser.hs b/test/Test/Language/Javascript/StatementParser.hs index e27addf..1431cbc 100644 --- a/test/Test/Language/Javascript/StatementParser.hs +++ b/test/Test/Language/Javascript/StatementParser.hs @@ -101,4 +101,3 @@ testStatementParser = describe "Parse statements:" $ do testStmt :: String -> String testStmt str = showStrippedMaybe (parseUsing parseStatement str "src") - From d4f2b6dfdb4eb4b948ee9dc1e8c02ed2d8f36c0d Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sun, 18 Nov 2018 00:12:27 -0500 Subject: [PATCH 2/9] Flip test condition This fixes the messaging as LHS is actual and RHS expected test result. --- test/Test/Language/Javascript/RoundTrip.hs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/test/Test/Language/Javascript/RoundTrip.hs b/test/Test/Language/Javascript/RoundTrip.hs index b55efb0..7813be9 100644 --- a/test/Test/Language/Javascript/RoundTrip.hs +++ b/test/Test/Language/Javascript/RoundTrip.hs @@ -101,5 +101,4 @@ testRoundTrip = describe "Roundtrip:" $ do testRT :: String -> Expectation -testRT str = str `shouldBe` renderToString (readJs str) - +testRT str = renderToString (readJs str) `shouldBe` str From 6312561e980bef21018460754776b065045c14be Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 21:24:21 -0500 Subject: [PATCH 3/9] gitignore: Ignore `.stack-work` --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index f9d1730..a39cb33 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,6 @@ /unicode/uc-nl.htm /unicode/uc-pc.htm cabal.sandbox.config + +# stack +/.stack-work/ From e96a43652d4292ccaa9157e5da009b2f6be989dd Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 20:51:13 -0500 Subject: [PATCH 4/9] Fix indentation --- src/Language/JavaScript/Parser/Grammar7.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index b5c1ff7..dc89bfa 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -19,7 +19,7 @@ import qualified Language.JavaScript.Parser.AST as AST -- The name of the generated function to be exported from the module %name parseProgram Program %name parseLiteral LiteralMain -%name parseExpression ExpressionMain +%name parseExpression ExpressionMain %name parseStatement StatementMain %tokentype { Token } From 93308637a348958a32ff07e471b99d7552e03031 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 20:39:44 -0500 Subject: [PATCH 5/9] Parse empty `export` declaration --- language-javascript.cabal | 1 + src/Language/JavaScript/Parser.hs | 1 + src/Language/JavaScript/Parser/AST.hs | 11 ++++++ src/Language/JavaScript/Parser/Grammar7.y | 39 +++++++++++++++++++ src/Language/JavaScript/Parser/Lexer.x | 2 +- src/Language/JavaScript/Parser/Token.hs | 1 + .../Language/Javascript/DeclarationParser.hs | 20 ++++++++++ test/testsuite.hs | 5 ++- 8 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 test/Test/Language/Javascript/DeclarationParser.hs diff --git a/language-javascript.cabal b/language-javascript.cabal index b1900e5..7ff1df5 100644 --- a/language-javascript.cabal +++ b/language-javascript.cabal @@ -78,6 +78,7 @@ Test-Suite testsuite , language-javascript Other-modules: Test.Language.Javascript.ExpressionParser + Test.Language.Javascript.DeclarationParser Test.Language.Javascript.Lexer Test.Language.Javascript.LiteralParser Test.Language.Javascript.Minify diff --git a/src/Language/JavaScript/Parser.hs b/src/Language/JavaScript/Parser.hs index 80394ec..9ae3983 100644 --- a/src/Language/JavaScript/Parser.hs +++ b/src/Language/JavaScript/Parser.hs @@ -17,6 +17,7 @@ module Language.JavaScript.Parser , JSTryCatch (..) , JSTryFinally (..) , JSStatement (..) + , JSDeclaration (..) , JSSwitchParts (..) , JSAST(..) diff --git a/src/Language/JavaScript/Parser/AST.hs b/src/Language/JavaScript/Parser/AST.hs index 9c6b55e..3155842 100644 --- a/src/Language/JavaScript/Parser/AST.hs +++ b/src/Language/JavaScript/Parser/AST.hs @@ -10,6 +10,7 @@ module Language.JavaScript.Parser.AST , JSTryCatch (..) , JSTryFinally (..) , JSStatement (..) + , JSDeclaration (..) , JSBlock (..) , JSSwitchParts (..) , JSAST (..) @@ -44,6 +45,7 @@ data JSAnnot data JSAST = JSAstProgram ![JSStatement] !JSAnnot -- ^source elements, tailing whitespace | JSAstStatement !JSStatement !JSAnnot + | JSAstDeclaration !JSDeclaration !JSAnnot | JSAstExpression !JSExpression !JSAnnot | JSAstLiteral !JSExpression !JSAnnot deriving (Data, Eq, Show, Typeable) @@ -76,6 +78,10 @@ data JSStatement | JSWith !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement !JSSemi -- ^with,lb,expr,rb,stmt list deriving (Data, Eq, Show, Typeable) +data JSDeclaration + = JSExport !JSAnnot !(Maybe JSExpression) !JSSemi -- ^export,expr + deriving (Data, Eq, Show, Typeable) + data JSExpression -- | Terminals = JSIdentifier !JSAnnot !String @@ -239,6 +245,7 @@ data JSCommaTrailingList a showStripped :: JSAST -> String showStripped (JSAstProgram xs _) = "JSAstProgram " ++ ss xs showStripped (JSAstStatement s _) = "JSAstStatement (" ++ ss s ++ ")" +showStripped (JSAstDeclaration s _) = "JSAstDeclaration (" ++ ss s ++ ")" showStripped (JSAstExpression e _) = "JSAstExpression (" ++ ss e ++ ")" showStripped (JSAstLiteral s _) = "JSAstLiteral (" ++ ss s ++ ")" @@ -308,6 +315,10 @@ instance ShowStripped JSExpression where ss (JSVarInitExpression x1 x2) = "JSVarInitExpression (" ++ ss x1 ++ ") " ++ ss x2 ss (JSSpreadExpression _ x1) = "JSSpreadExpression (" ++ ss x1 ++ ")" +instance ShowStripped JSDeclaration where + ss (JSExport _ Nothing _) = "JSExport" + ss (JSExport _ (Just x1) _) = "JSExport (" ++ (ss x1) ++ ")" + instance ShowStripped JSTryCatch where ss (JSCatch _ _lb x1 _rb x3) = "JSCatch (" ++ ss x1 ++ "," ++ ss x3 ++ ")" ss (JSCatchIf _ _lb x1 _ ex _rb x3) = "JSCatch (" ++ ss x1 ++ ") if " ++ ss ex ++ " (" ++ ss x3 ++ ")" diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index dc89bfa..6359846 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -3,6 +3,7 @@ module Language.JavaScript.Parser.Grammar7 ( parseProgram , parseStatement + , parseDeclaration , parseExpression , parseLiteral ) where @@ -21,6 +22,7 @@ import qualified Language.JavaScript.Parser.AST as AST %name parseLiteral LiteralMain %name parseExpression ExpressionMain %name parseStatement StatementMain +%name parseDeclaration DeclarationMain %tokentype { Token } %error { parseError } @@ -93,6 +95,7 @@ import qualified Language.JavaScript.Parser.AST as AST 'do' { DoToken {} } 'else' { ElseToken {} } 'enum' { EnumToken {} } + 'export' { ExportToken {} } 'false' { FalseToken {} } 'finally' { FinallyToken {} } 'for' { ForToken {} } @@ -305,6 +308,9 @@ Let : 'let' { mkJSAnnot $1 } Const :: { AST.JSAnnot } Const : 'const' { mkJSAnnot $1 } +Export :: { AST.JSAnnot } +Export : 'export' { mkJSAnnot $1 } + If :: { AST.JSAnnot } If : 'if' { mkJSAnnot $1 } @@ -437,6 +443,7 @@ IdentifierName : Identifier {$1} | '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" } @@ -1145,6 +1152,36 @@ Program :: { AST.JSAST } Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } | Eof { AST.JSAstProgram [] $1 {- 'Program2' -} } + +Declaration :: { AST.JSDeclaration } +Declaration : ExportDeclaration { $1 {- 'Declaration1' -} } + +-- ExportDeclaration : See 15.2.3 +-- export * FromClause ; +-- export ExportClause FromClause ; +-- export ExportClause ; +-- export VariableStatement +-- export Declaration +-- export default HoistableDeclaration[Default] +-- export default ClassDeclaration[Default] +-- export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; +ExportDeclaration :: { AST.JSDeclaration } +ExportDeclaration : Export ExportClause AutoSemi { AST.JSExport $1 $2 $3 {- 'ExportDeclaration' -} } + +-- ExportClause : +-- { } +-- { ExportsList } +-- { ExportsList , } +ExportClause :: { Maybe AST.JSExpression } +ExportClause : LBrace RBrace { Nothing {- 'ExportClause1' -} } + +-- ExportsList : +-- ExportSpecifier +-- ExportsList , ExportSpecifier +-- ExportSpecifier : +-- IdentifierName +-- IdentifierName as IdentifierName + -- For debugging/other entry points LiteralMain :: { AST.JSAST } LiteralMain : Literal Eof { AST.JSAstLiteral $1 $2 {- 'LiteralMain' -} } @@ -1155,6 +1192,8 @@ ExpressionMain : Expression Eof { AST.JSAstExpression $1 $2 {- 'ExpressionMa StatementMain :: { AST.JSAST } StatementMain : StatementNoEmpty Eof { AST.JSAstStatement $1 $2 {- 'StatementMain' -} } +DeclarationMain :: { AST.JSAST } +DeclarationMain : Declaration Eof { AST.JSAstDeclaration $1 $2 {- 'DeclarationMain' -} } { diff --git a/src/Language/JavaScript/Parser/Lexer.x b/src/Language/JavaScript/Parser/Lexer.x index 723c21b..be05253 100644 --- a/src/Language/JavaScript/Parser/Lexer.x +++ b/src/Language/JavaScript/Parser/Lexer.x @@ -563,7 +563,7 @@ keywordNames = -- ( "code", FutureToken ) **** not any more -- ( "const", FutureToken ) **** an actual token, used in productions -- enum **** an actual token, used in productions - , ( "export", FutureToken ) + , ( "export", ExportToken ) , ( "extends", FutureToken ) , ( "import", FutureToken ) diff --git a/src/Language/JavaScript/Parser/Token.hs b/src/Language/JavaScript/Parser/Token.hs index b2f7c4d..9b847b5 100644 --- a/src/Language/JavaScript/Parser/Token.hs +++ b/src/Language/JavaScript/Parser/Token.hs @@ -88,6 +88,7 @@ data Token | VoidToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | WhileToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | WithToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } + | ExportToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } -- Future reserved words | FutureToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } -- Needed, not sure what they are though. diff --git a/test/Test/Language/Javascript/DeclarationParser.hs b/test/Test/Language/Javascript/DeclarationParser.hs new file mode 100644 index 0000000..ece0dc1 --- /dev/null +++ b/test/Test/Language/Javascript/DeclarationParser.hs @@ -0,0 +1,20 @@ +module Test.Language.Javascript.DeclarationParser + ( testDeclarationParser + ) where + + +import Test.Hspec + +import Language.JavaScript.Parser +import Language.JavaScript.Parser.Grammar7 +import Language.JavaScript.Parser.Parser + + +testDeclarationParser :: Spec +testDeclarationParser = describe "Parse declarations:" $ do + it "export" $ do + testDecl "export {}" `shouldBe` "Right (JSAstDeclaration (JSExport))" + testDecl "export {};" `shouldBe` "Right (JSAstDeclaration (JSExport))" + +testDecl :: String -> String +testDecl str = showStrippedMaybe (parseUsing parseDeclaration str "src") diff --git a/test/testsuite.hs b/test/testsuite.hs index 7ba14d2..d8e3bb9 100644 --- a/test/testsuite.hs +++ b/test/testsuite.hs @@ -5,9 +5,10 @@ import Test.Hspec import Test.Hspec.Runner +import Test.Language.Javascript.DeclarationParser +import Test.Language.Javascript.ExpressionParser import Test.Language.Javascript.Lexer import Test.Language.Javascript.LiteralParser -import Test.Language.Javascript.ExpressionParser import Test.Language.Javascript.Minify import Test.Language.Javascript.ProgramParser import Test.Language.Javascript.RoundTrip @@ -28,9 +29,9 @@ testAll = do testLiteralParser testExpressionParser testStatementParser + testDeclarationParser testProgramParser testRoundTrip testMinifyExpr testMinifyStmt testMinifyProg - From f082ec6241690ead75acb12c7a9eb99650312c38 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 21:23:43 -0500 Subject: [PATCH 6/9] Merge `JSDeclaration` with `JSStatement` --- language-javascript.cabal | 1 - src/Language/JavaScript/Parser.hs | 1 - src/Language/JavaScript/Parser/AST.hs | 16 ++++----------- src/Language/JavaScript/Parser/Grammar7.y | 12 ++--------- src/Language/JavaScript/Parser/Lexer.x | 2 +- .../Language/Javascript/DeclarationParser.hs | 20 ------------------- .../Language/Javascript/StatementParser.hs | 5 +++++ test/testsuite.hs | 2 -- 8 files changed, 12 insertions(+), 47 deletions(-) delete mode 100644 test/Test/Language/Javascript/DeclarationParser.hs diff --git a/language-javascript.cabal b/language-javascript.cabal index 7ff1df5..b1900e5 100644 --- a/language-javascript.cabal +++ b/language-javascript.cabal @@ -78,7 +78,6 @@ Test-Suite testsuite , language-javascript Other-modules: Test.Language.Javascript.ExpressionParser - Test.Language.Javascript.DeclarationParser Test.Language.Javascript.Lexer Test.Language.Javascript.LiteralParser Test.Language.Javascript.Minify diff --git a/src/Language/JavaScript/Parser.hs b/src/Language/JavaScript/Parser.hs index 9ae3983..80394ec 100644 --- a/src/Language/JavaScript/Parser.hs +++ b/src/Language/JavaScript/Parser.hs @@ -17,7 +17,6 @@ module Language.JavaScript.Parser , JSTryCatch (..) , JSTryFinally (..) , JSStatement (..) - , JSDeclaration (..) , JSSwitchParts (..) , JSAST(..) diff --git a/src/Language/JavaScript/Parser/AST.hs b/src/Language/JavaScript/Parser/AST.hs index 3155842..2696b44 100644 --- a/src/Language/JavaScript/Parser/AST.hs +++ b/src/Language/JavaScript/Parser/AST.hs @@ -10,7 +10,6 @@ module Language.JavaScript.Parser.AST , JSTryCatch (..) , JSTryFinally (..) , JSStatement (..) - , JSDeclaration (..) , JSBlock (..) , JSSwitchParts (..) , JSAST (..) @@ -45,7 +44,6 @@ data JSAnnot data JSAST = JSAstProgram ![JSStatement] !JSAnnot -- ^source elements, tailing whitespace | JSAstStatement !JSStatement !JSAnnot - | JSAstDeclaration !JSDeclaration !JSAnnot | JSAstExpression !JSExpression !JSAnnot | JSAstLiteral !JSExpression !JSAnnot deriving (Data, Eq, Show, Typeable) @@ -73,13 +71,10 @@ data JSStatement | JSSwitch !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSAnnot ![JSSwitchParts] !JSAnnot !JSSemi -- ^switch,lb,expr,rb,caseblock,autosemi | JSThrow !JSAnnot !JSExpression !JSSemi -- ^throw val autosemi | JSTry !JSAnnot !JSBlock ![JSTryCatch] !JSTryFinally -- ^try,block,catches,finally - | JSVariable !JSAnnot !(JSCommaList JSExpression) !JSSemi -- ^var|const, decl, autosemi + | JSVariable !JSAnnot !(JSCommaList JSExpression) !JSSemi -- ^var, decl, autosemi | JSWhile !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement -- ^while,lb,expr,rb,stmt | JSWith !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement !JSSemi -- ^with,lb,expr,rb,stmt list - deriving (Data, Eq, Show, Typeable) - -data JSDeclaration - = JSExport !JSAnnot !(Maybe JSExpression) !JSSemi -- ^export,expr + | JSExport !JSAnnot !(Maybe JSExpression) !JSSemi -- ^export,expr deriving (Data, Eq, Show, Typeable) data JSExpression @@ -245,7 +240,6 @@ data JSCommaTrailingList a showStripped :: JSAST -> String showStripped (JSAstProgram xs _) = "JSAstProgram " ++ ss xs showStripped (JSAstStatement s _) = "JSAstStatement (" ++ ss s ++ ")" -showStripped (JSAstDeclaration s _) = "JSAstDeclaration (" ++ ss s ++ ")" showStripped (JSAstExpression e _) = "JSAstExpression (" ++ ss e ++ ")" showStripped (JSAstLiteral s _) = "JSAstLiteral (" ++ ss s ++ ")" @@ -283,6 +277,8 @@ instance ShowStripped JSStatement where ss (JSVariable _ xs _as) = "JSVariable " ++ ss xs ss (JSWhile _ _lb x1 _rb x2) = "JSWhile (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")" ss (JSWith _ _lb x1 _rb x _) = "JSWith (" ++ ss x1 ++ ") (" ++ ss x ++ ")" + ss (JSExport _ Nothing _) = "JSExport" + ss (JSExport _ (Just x1) _) = "JSExport (" ++ (ss x1) ++ ")" instance ShowStripped JSExpression where ss (JSArrayLiteral _lb xs _rb) = "JSArrayLiteral " ++ ss xs @@ -315,10 +311,6 @@ instance ShowStripped JSExpression where ss (JSVarInitExpression x1 x2) = "JSVarInitExpression (" ++ ss x1 ++ ") " ++ ss x2 ss (JSSpreadExpression _ x1) = "JSSpreadExpression (" ++ ss x1 ++ ")" -instance ShowStripped JSDeclaration where - ss (JSExport _ Nothing _) = "JSExport" - ss (JSExport _ (Just x1) _) = "JSExport (" ++ (ss x1) ++ ")" - instance ShowStripped JSTryCatch where ss (JSCatch _ _lb x1 _rb x3) = "JSCatch (" ++ ss x1 ++ "," ++ ss x3 ++ ")" ss (JSCatchIf _ _lb x1 _ ex _rb x3) = "JSCatch (" ++ ss x1 ++ ") if " ++ ss ex ++ " (" ++ ss x3 ++ ")" diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index 6359846..d6467d2 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -3,7 +3,6 @@ module Language.JavaScript.Parser.Grammar7 ( parseProgram , parseStatement - , parseDeclaration , parseExpression , parseLiteral ) where @@ -22,7 +21,6 @@ import qualified Language.JavaScript.Parser.AST as AST %name parseLiteral LiteralMain %name parseExpression ExpressionMain %name parseStatement StatementMain -%name parseDeclaration DeclarationMain %tokentype { Token } %error { parseError } @@ -894,6 +892,7 @@ StatementNoEmpty : StatementBlock { $1 {- 'StatementNoEmpty1' -} } | ThrowStatement { $1 {- 'StatementNoEmpty13' -} } | TryStatement { $1 {- 'StatementNoEmpty14' -} } | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} } + | ExportDeclaration { $1 {- 'StatementNoEmpty16' -} } StatementBlock :: { AST.JSStatement } @@ -1152,10 +1151,6 @@ Program :: { AST.JSAST } Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } | Eof { AST.JSAstProgram [] $1 {- 'Program2' -} } - -Declaration :: { AST.JSDeclaration } -Declaration : ExportDeclaration { $1 {- 'Declaration1' -} } - -- ExportDeclaration : See 15.2.3 -- export * FromClause ; -- export ExportClause FromClause ; @@ -1165,7 +1160,7 @@ Declaration : ExportDeclaration { $1 {- 'Declaration1' -} } -- export default HoistableDeclaration[Default] -- export default ClassDeclaration[Default] -- export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; -ExportDeclaration :: { AST.JSDeclaration } +ExportDeclaration :: { AST.JSStatement } ExportDeclaration : Export ExportClause AutoSemi { AST.JSExport $1 $2 $3 {- 'ExportDeclaration' -} } -- ExportClause : @@ -1192,9 +1187,6 @@ ExpressionMain : Expression Eof { AST.JSAstExpression $1 $2 {- 'ExpressionMa StatementMain :: { AST.JSAST } StatementMain : StatementNoEmpty Eof { AST.JSAstStatement $1 $2 {- 'StatementMain' -} } -DeclarationMain :: { AST.JSAST } -DeclarationMain : Declaration Eof { AST.JSAstDeclaration $1 $2 {- 'DeclarationMain' -} } - { -- Need this type while build the AST, but is not actually part of the AST. diff --git a/src/Language/JavaScript/Parser/Lexer.x b/src/Language/JavaScript/Parser/Lexer.x index be05253..5d1c453 100644 --- a/src/Language/JavaScript/Parser/Lexer.x +++ b/src/Language/JavaScript/Parser/Lexer.x @@ -517,6 +517,7 @@ keywordNames = , ( "else", ElseToken ) , ( "enum", EnumToken ) -- not a keyword, nominally a future reserved word, but actually in use + , ( "export", ExportToken ) , ( "false", FalseToken ) -- boolean literal @@ -563,7 +564,6 @@ keywordNames = -- ( "code", FutureToken ) **** not any more -- ( "const", FutureToken ) **** an actual token, used in productions -- enum **** an actual token, used in productions - , ( "export", ExportToken ) , ( "extends", FutureToken ) , ( "import", FutureToken ) diff --git a/test/Test/Language/Javascript/DeclarationParser.hs b/test/Test/Language/Javascript/DeclarationParser.hs deleted file mode 100644 index ece0dc1..0000000 --- a/test/Test/Language/Javascript/DeclarationParser.hs +++ /dev/null @@ -1,20 +0,0 @@ -module Test.Language.Javascript.DeclarationParser - ( testDeclarationParser - ) where - - -import Test.Hspec - -import Language.JavaScript.Parser -import Language.JavaScript.Parser.Grammar7 -import Language.JavaScript.Parser.Parser - - -testDeclarationParser :: Spec -testDeclarationParser = describe "Parse declarations:" $ do - it "export" $ do - testDecl "export {}" `shouldBe` "Right (JSAstDeclaration (JSExport))" - testDecl "export {};" `shouldBe` "Right (JSAstDeclaration (JSExport))" - -testDecl :: String -> String -testDecl str = showStrippedMaybe (parseUsing parseDeclaration str "src") diff --git a/test/Test/Language/Javascript/StatementParser.hs b/test/Test/Language/Javascript/StatementParser.hs index 1431cbc..e5c7022 100644 --- a/test/Test/Language/Javascript/StatementParser.hs +++ b/test/Test/Language/Javascript/StatementParser.hs @@ -16,6 +16,11 @@ testStatementParser = describe "Parse statements:" $ do testStmt "x" `shouldBe` "Right (JSAstStatement (JSIdentifier 'x'))" testStmt "null" `shouldBe` "Right (JSAstStatement (JSLiteral 'null'))" testStmt "true?1:2" `shouldBe` "Right (JSAstStatement (JSExpressionTernary (JSLiteral 'true',JSDecimal '1',JSDecimal '2')))" + + it "export" $ do + testStmt "export {}" `shouldBe` "Right (JSAstStatement (JSExport))" + testStmt "export {};" `shouldBe` "Right (JSAstStatement (JSExport))" + it "block" $ do testStmt "{}" `shouldBe` "Right (JSAstStatement (JSStatementBlock []))" testStmt "{x=1}" `shouldBe` "Right (JSAstStatement (JSStatementBlock [JSOpAssign ('=',JSIdentifier 'x',JSDecimal '1')]))" diff --git a/test/testsuite.hs b/test/testsuite.hs index d8e3bb9..8f6ccba 100644 --- a/test/testsuite.hs +++ b/test/testsuite.hs @@ -5,7 +5,6 @@ import Test.Hspec import Test.Hspec.Runner -import Test.Language.Javascript.DeclarationParser import Test.Language.Javascript.ExpressionParser import Test.Language.Javascript.Lexer import Test.Language.Javascript.LiteralParser @@ -29,7 +28,6 @@ testAll = do testLiteralParser testExpressionParser testStatementParser - testDeclarationParser testProgramParser testRoundTrip testMinifyExpr From eb2b798f8ceaa3cf9fb6d28380d7714f46a6fee8 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sat, 17 Nov 2018 22:39:25 -0500 Subject: [PATCH 7/9] Parse export lists and variable statements --- src/Language/JavaScript/Parser/AST.hs | 30 +++++++++++++--- src/Language/JavaScript/Parser/Grammar7.y | 36 +++++++++++++------ src/Language/JavaScript/Parser/Lexer.x | 3 +- src/Language/JavaScript/Parser/Token.hs | 1 + src/Language/JavaScript/Pretty/Printer.hs | 12 ++++++- src/Language/JavaScript/Process/Minify.hs | 9 +++++ test/Test/Language/Javascript/Minify.hs | 7 ++++ test/Test/Language/Javascript/RoundTrip.hs | 3 ++ .../Language/Javascript/StatementParser.hs | 7 ++-- 9 files changed, 89 insertions(+), 19 deletions(-) diff --git a/src/Language/JavaScript/Parser/AST.hs b/src/Language/JavaScript/Parser/AST.hs index 2696b44..f8dbbda 100644 --- a/src/Language/JavaScript/Parser/AST.hs +++ b/src/Language/JavaScript/Parser/AST.hs @@ -10,6 +10,8 @@ module Language.JavaScript.Parser.AST , JSTryCatch (..) , JSTryFinally (..) , JSStatement (..) + , JSExportBody (..) + , JSExportSpecifier (..) , JSBlock (..) , JSSwitchParts (..) , JSAST (..) @@ -74,7 +76,7 @@ data JSStatement | JSVariable !JSAnnot !(JSCommaList JSExpression) !JSSemi -- ^var, decl, autosemi | JSWhile !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement -- ^while,lb,expr,rb,stmt | JSWith !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement !JSSemi -- ^with,lb,expr,rb,stmt list - | JSExport !JSAnnot !(Maybe JSExpression) !JSSemi -- ^export,expr + | JSExport !JSAnnot !JSExportBody !JSSemi -- ^export, body, autosemi deriving (Data, Eq, Show, Typeable) data JSExpression @@ -113,6 +115,7 @@ data JSExpression data JSBinOp = JSBinOpAnd !JSAnnot + | JSBinOpAs !JSAnnot | JSBinOpBitAnd !JSAnnot | JSBinOpBitOr !JSAnnot | JSBinOpBitXor !JSAnnot @@ -169,6 +172,16 @@ data JSAssignOp | JSBwOrAssign !JSAnnot deriving (Data, Eq, Show, Typeable) +data JSExportBody + = JSExportStatement !JSStatement + | JSExportClause !JSAnnot !(Maybe (JSCommaList JSExportSpecifier)) !JSAnnot -- ^lb,body,rb + deriving (Data, Eq, Show, Typeable) + +data JSExportSpecifier + = JSExportSpecifier !JSIdent + | JSExportSpecifierAs !JSIdent !JSBinOp !JSIdent + deriving (Data, Eq, Show, Typeable) + data JSTryCatch = JSCatch !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSBlock -- ^catch,lb,ident,rb,block | JSCatchIf !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSExpression !JSAnnot !JSBlock -- ^catch,lb,ident,if,expr,rb,block @@ -247,7 +260,6 @@ showStripped (JSAstLiteral s _) = "JSAstLiteral (" ++ ss s ++ ")" class ShowStripped a where ss :: a -> String - instance ShowStripped JSStatement where ss (JSStatementBlock _ xs _ _) = "JSStatementBlock " ++ ss xs ss (JSBreak _ JSIdentNone s) = "JSBreak" ++ commaIf (ss s) @@ -277,8 +289,7 @@ instance ShowStripped JSStatement where ss (JSVariable _ xs _as) = "JSVariable " ++ ss xs ss (JSWhile _ _lb x1 _rb x2) = "JSWhile (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")" ss (JSWith _ _lb x1 _rb x _) = "JSWith (" ++ ss x1 ++ ") (" ++ ss x ++ ")" - ss (JSExport _ Nothing _) = "JSExport" - ss (JSExport _ (Just x1) _) = "JSExport (" ++ (ss x1) ++ ")" + ss (JSExport _ b _) = "JSExport (" ++ ss b ++ ")" instance ShowStripped JSExpression where ss (JSArrayLiteral _lb xs _rb) = "JSArrayLiteral " ++ ss xs @@ -311,6 +322,15 @@ instance ShowStripped JSExpression where ss (JSVarInitExpression x1 x2) = "JSVarInitExpression (" ++ ss x1 ++ ") " ++ ss x2 ss (JSSpreadExpression _ x1) = "JSSpreadExpression (" ++ ss x1 ++ ")" +instance ShowStripped JSExportBody where + ss (JSExportStatement x1) = "JSExportStatement (" ++ ss x1 ++ ")" + ss (JSExportClause _ Nothing _) = "JSExportClause ()" + ss (JSExportClause _ (Just x1) _) = "JSExportClause (" ++ ss x1 ++ ")" + +instance ShowStripped JSExportSpecifier where + ss (JSExportSpecifier x1) = "JSExportSpecifier (" ++ ss x1 ++ ")" + ss (JSExportSpecifierAs x1 _ x2) = "JSExportSpecifierAs (" ++ ss x1 ++ "," ++ ss x2 ++ ")" + instance ShowStripped JSTryCatch where ss (JSCatch _ _lb x1 _rb x3) = "JSCatch (" ++ ss x1 ++ "," ++ ss x3 ++ ")" ss (JSCatchIf _ _lb x1 _ ex _rb x3) = "JSCatch (" ++ ss x1 ++ ") if " ++ ss ex ++ " (" ++ ss x3 ++ ")" @@ -345,6 +365,7 @@ instance ShowStripped JSSwitchParts where instance ShowStripped JSBinOp where ss (JSBinOpAnd _) = "'&&'" + ss (JSBinOpAs _) = "'as'" ss (JSBinOpBitAnd _) = "'&'" ss (JSBinOpBitOr _) = "'|'" ss (JSBinOpBitXor _) = "'^'" @@ -440,6 +461,7 @@ commaIf xs = ',' : xs deAnnot :: JSBinOp -> JSBinOp deAnnot (JSBinOpAnd _) = JSBinOpAnd JSNoAnnot +deAnnot (JSBinOpAs _) = JSBinOpAs JSNoAnnot deAnnot (JSBinOpBitAnd _) = JSBinOpBitAnd JSNoAnnot deAnnot (JSBinOpBitOr _) = JSBinOpBitOr JSNoAnnot deAnnot (JSBinOpBitXor _) = JSBinOpBitXor JSNoAnnot diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index d6467d2..a4dc1dc 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -81,6 +81,7 @@ import qualified Language.JavaScript.Parser.AST as AST '(' { LeftParenToken {} } ')' { RightParenToken {} } + 'as' { AsToken {} } 'autosemi' { AutoSemiToken {} } 'break' { BreakToken {} } 'case' { CaseToken {} } @@ -245,6 +246,9 @@ Ge : '>=' { AST.JSBinOpGe (mkJSAnnot $1) } Gt :: { AST.JSBinOp } Gt : '>' { AST.JSBinOpGt (mkJSAnnot $1) } +As :: { AST.JSBinOp } +As : 'as' { AST.JSBinOpAs (mkJSAnnot $1) } + In :: { AST.JSBinOp } In : 'in' { AST.JSBinOpIn (mkJSAnnot $1) } @@ -430,6 +434,7 @@ Identifier : 'ident' { AST.JSIdentifier (mkJSAnnot $1) (tokenLiteral $1) } -- 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" } @@ -1152,30 +1157,39 @@ Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } | Eof { AST.JSAstProgram [] $1 {- 'Program2' -} } -- ExportDeclaration : See 15.2.3 --- export * FromClause ; --- export ExportClause FromClause ; --- export ExportClause ; --- export VariableStatement --- export Declaration --- export default HoistableDeclaration[Default] --- export default ClassDeclaration[Default] --- export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; +-- [ ] export * FromClause ; +-- [ ] export ExportClause FromClause ; +-- [x] export ExportClause ; +-- [x] export VariableStatement +-- [ ] export Declaration +-- [ ] export default HoistableDeclaration[Default] +-- [ ] export default ClassDeclaration[Default] +-- [ ] export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; ExportDeclaration :: { AST.JSStatement } -ExportDeclaration : Export ExportClause AutoSemi { AST.JSExport $1 $2 $3 {- 'ExportDeclaration' -} } +ExportDeclaration : Export ExportClause AutoSemi { AST.JSExport $1 $2 $3 {- 'ExportDeclaration1' -} } + | Export VariableStatement AutoSemi { AST.JSExport $1 (AST.JSExportStatement $2) $3 {- 'ExportDeclaration2' -} } -- ExportClause : -- { } -- { ExportsList } -- { ExportsList , } -ExportClause :: { Maybe AST.JSExpression } -ExportClause : LBrace RBrace { Nothing {- 'ExportClause1' -} } +ExportClause :: { AST.JSExportBody } +ExportClause : LBrace RBrace { AST.JSExportClause $1 Nothing $2 {- 'ExportClause1' -} } + | LBrace ExportsList RBrace { AST.JSExportClause $1 (Just $2) $3 {- 'ExportClause2' -} } -- ExportsList : -- ExportSpecifier -- ExportsList , ExportSpecifier +ExportsList :: { AST.JSCommaList AST.JSExportSpecifier } +ExportsList : ExportSpecifier { AST.JSLOne $1 {- 'ExportsList1' -} } + | ExportsList Comma ExportSpecifier { AST.JSLCons $1 $2 $3 {- 'ExportsList2' -} } + -- ExportSpecifier : -- IdentifierName -- IdentifierName as IdentifierName +ExportSpecifier :: { AST.JSExportSpecifier } +ExportSpecifier : IdentifierName { AST.JSExportSpecifier (identName $1) {- 'ExportSpecifier1' -} } + | IdentifierName As IdentifierName { AST.JSExportSpecifierAs (identName $1) $2 (identName $3) {- 'ExportSpecifier2' -} } -- For debugging/other entry points LiteralMain :: { AST.JSAST } diff --git a/src/Language/JavaScript/Parser/Lexer.x b/src/Language/JavaScript/Parser/Lexer.x index 5d1c453..863fabd 100644 --- a/src/Language/JavaScript/Parser/Lexer.x +++ b/src/Language/JavaScript/Parser/Lexer.x @@ -503,7 +503,8 @@ keywords = Map.fromList keywordNames keywordNames :: [(String, TokenPosn -> String -> [CommentAnnotation] -> Token)] keywordNames = - [ ( "break", BreakToken ) + [ ( "as", AsToken ) + , ( "break", BreakToken ) , ( "case", CaseToken ) , ( "catch", CatchToken ) diff --git a/src/Language/JavaScript/Parser/Token.hs b/src/Language/JavaScript/Parser/Token.hs index 9b847b5..4a5a97c 100644 --- a/src/Language/JavaScript/Parser/Token.hs +++ b/src/Language/JavaScript/Parser/Token.hs @@ -56,6 +56,7 @@ data Token -- ^ Literal: Regular Expression -- Keywords + | AsToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | BreakToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | CaseToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } | CatchToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] } diff --git a/src/Language/JavaScript/Pretty/Printer.hs b/src/Language/JavaScript/Pretty/Printer.hs index fd9dc89..33a23a5 100644 --- a/src/Language/JavaScript/Pretty/Printer.hs +++ b/src/Language/JavaScript/Pretty/Printer.hs @@ -138,6 +138,7 @@ instance RenderJS [JSExpression] where instance RenderJS JSBinOp where (|>) pacc (JSBinOpAnd annot) = pacc |> annot |> "&&" + (|>) pacc (JSBinOpAs annot) = pacc |> annot |> "as" (|>) pacc (JSBinOpBitAnd annot) = pacc |> annot |> "&" (|>) pacc (JSBinOpBitOr annot) = pacc |> annot |> "|" (|>) pacc (JSBinOpBitXor annot) = pacc |> annot |> "^" @@ -238,6 +239,7 @@ instance RenderJS JSStatement where (|>) pacc (JSVariable annot xs s) = pacc |> annot |> "var" |> xs |> s (|>) pacc (JSWhile annot alp x1 arp x2) = pacc |> annot |> "while" |> alp |> "(" |> x1 |> arp |> ")" |> x2 (|>) pacc (JSWith annot alp x1 arp x s) = pacc |> annot |> "with" |> alp |> "(" |> x1 |> arp |> ")" |> x |> s + (|>) pacc (JSExport annot b s) = pacc |> annot |> "export" |> b |> s instance RenderJS [JSStatement] where (|>) = foldl' (|>) @@ -265,6 +267,15 @@ instance RenderJS JSArrayElement where instance RenderJS [JSArrayElement] where (|>) = foldl' (|>) +instance RenderJS JSExportBody where + (|>) pacc (JSExportStatement s) = pacc |> " " |> s + (|>) pacc (JSExportClause alb Nothing arb) = pacc |> alb |> "{}" |> arb + (|>) pacc (JSExportClause alb (Just s) arb) = pacc |> alb |> "{" |> s |> "}" |> arb + +instance RenderJS JSExportSpecifier where + (|>) pacc (JSExportSpecifier i) = pacc |> i + (|>) pacc (JSExportSpecifierAs x1 as x2) = pacc |> x1 |> as |> x2 + instance RenderJS a => RenderJS (JSCommaList a) where (|>) pacc (JSLCons pl a i) = pacc |> pl |> a |> "," |> i (|>) pacc (JSLOne i) = pacc |> i @@ -287,4 +298,3 @@ instance RenderJS JSVarInitializer where (|>) pacc JSVarInitNone = pacc -- EOF - diff --git a/src/Language/JavaScript/Process/Minify.hs b/src/Language/JavaScript/Process/Minify.hs index f4babe3..cb82e05 100644 --- a/src/Language/JavaScript/Process/Minify.hs +++ b/src/Language/JavaScript/Process/Minify.hs @@ -64,6 +64,7 @@ fixStmt a _ (JSTry _ b tc tf) = JSTry a (fixEmpty b) (map fixEmpty tc) (fixEmpty fixStmt a s (JSVariable _ ss _) = JSVariable a (fixVarList ss) s fixStmt a s (JSWhile _ _ e _ st) = JSWhile a emptyAnnot (fixEmpty e) emptyAnnot (fixStmt a s st) fixStmt a s (JSWith _ _ e _ st _) = JSWith a emptyAnnot (fixEmpty e) emptyAnnot (fixStmtE noSemi st) s +fixStmt a s (JSExport _ b _) = JSExport a (fixEmpty b) s fixIfElseBlock :: JSAnnot -> JSSemi -> JSStatement -> JSStatement @@ -209,6 +210,7 @@ normalizeToSQ str = instance MinifyJS JSBinOp where fix _ (JSBinOpAnd _) = JSBinOpAnd emptyAnnot + fix a (JSBinOpAs _) = JSBinOpAs a fix _ (JSBinOpBitAnd _) = JSBinOpBitAnd emptyAnnot fix _ (JSBinOpBitOr _) = JSBinOpBitOr emptyAnnot fix _ (JSBinOpBitXor _) = JSBinOpBitXor emptyAnnot @@ -265,6 +267,13 @@ instance MinifyJS JSAssignOp where fix a (JSBwXorAssign _) = JSBwXorAssign a fix a (JSBwOrAssign _) = JSBwOrAssign a +instance MinifyJS JSExportBody where + fix a (JSExportStatement s) = JSExportStatement (fixStmt a noSemi s) + fix _ (JSExportClause _ x1 _) = JSExportClause emptyAnnot (fixEmpty <$> x1) emptyAnnot + +instance MinifyJS JSExportSpecifier where + fix _ (JSExportSpecifier x1) = JSExportSpecifier (fixEmpty x1) + fix _ (JSExportSpecifierAs x1 as x2) = JSExportSpecifierAs (fixEmpty x1) (fixSpace as) (fixSpace x2) instance MinifyJS JSTryCatch where fix a (JSCatch _ _ x1 _ x3) = JSCatch a emptyAnnot (fixEmpty x1) emptyAnnot (fixEmpty x3) diff --git a/test/Test/Language/Javascript/Minify.hs b/test/Test/Language/Javascript/Minify.hs index 2e63b7e..136fe82 100644 --- a/test/Test/Language/Javascript/Minify.hs +++ b/test/Test/Language/Javascript/Minify.hs @@ -148,6 +148,13 @@ testMinifyStmt = describe "Minify statements:" $ do minifyStmt " { ; e = 1 } " `shouldBe` "e=1" minifyStmt " { { } ; f = 1 ; { } ; } ; " `shouldBe` "f=1" + it "export" $ do + minifyStmt " export { } ; " `shouldBe` "export{}" + minifyStmt " export { a } ; " `shouldBe` "export{a}" + minifyStmt " export { a, b } ; " `shouldBe` "export{a,b}" + minifyStmt " export { a, b as c , d } ; " `shouldBe` "export{a,b as c,d}" + minifyStmt " export const a = 1 ; " `shouldBe` "export const a=1" + it "if" $ do minifyStmt " if ( 1 ) return ; " `shouldBe` "if(1)return" minifyStmt " if ( 1 ) ; " `shouldBe` "if(1);" diff --git a/test/Test/Language/Javascript/RoundTrip.hs b/test/Test/Language/Javascript/RoundTrip.hs index 7813be9..f4135f5 100644 --- a/test/Test/Language/Javascript/RoundTrip.hs +++ b/test/Test/Language/Javascript/RoundTrip.hs @@ -98,6 +98,9 @@ testRoundTrip = describe "Roundtrip:" $ do testRT "switch (x) {default:break;}" testRT "switch (x) {default:\ncase 1:break;}" testRT "var x=1;let y=2;" + -- modules + testRT "export {};" + testRT "export { a, X as B, c}" testRT :: String -> Expectation diff --git a/test/Test/Language/Javascript/StatementParser.hs b/test/Test/Language/Javascript/StatementParser.hs index e5c7022..85cc511 100644 --- a/test/Test/Language/Javascript/StatementParser.hs +++ b/test/Test/Language/Javascript/StatementParser.hs @@ -18,8 +18,11 @@ testStatementParser = describe "Parse statements:" $ do testStmt "true?1:2" `shouldBe` "Right (JSAstStatement (JSExpressionTernary (JSLiteral 'true',JSDecimal '1',JSDecimal '2')))" it "export" $ do - testStmt "export {}" `shouldBe` "Right (JSAstStatement (JSExport))" - testStmt "export {};" `shouldBe` "Right (JSAstStatement (JSExport))" + testStmt "export {}" `shouldBe` "Right (JSAstStatement (JSExport (JSExportClause ())))" + testStmt "export {};" `shouldBe` "Right (JSAstStatement (JSExport (JSExportClause ())))" + testStmt "export const a = 1;" `shouldBe` "Right (JSAstStatement (JSExport (JSExportStatement (JSConstant (JSVarInitExpression (JSIdentifier 'a') [JSDecimal '1'])))))" + testStmt "export { a };" `shouldBe` "Right (JSAstStatement (JSExport (JSExportClause ((JSExportSpecifier (JSIdentifier 'a'))))))" + testStmt "export { X as Y };" `shouldBe` "Right (JSAstStatement (JSExport (JSExportClause ((JSExportSpecifierAs (JSIdentifier 'X',JSIdentifier 'Y'))))))" it "block" $ do testStmt "{}" `shouldBe` "Right (JSAstStatement (JSStatementBlock []))" From 4fe6f05376b990cf84e43961e135285084f539b6 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sun, 18 Nov 2018 00:35:52 -0500 Subject: [PATCH 8/9] :art: Improve line length --- src/Language/JavaScript/Parser/Grammar7.y | 24 +++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y index a4dc1dc..321a6ae 100644 --- a/src/Language/JavaScript/Parser/Grammar7.y +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -1166,30 +1166,38 @@ Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } -- [ ] export default ClassDeclaration[Default] -- [ ] export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; ExportDeclaration :: { AST.JSStatement } -ExportDeclaration : Export ExportClause AutoSemi { AST.JSExport $1 $2 $3 {- 'ExportDeclaration1' -} } - | Export VariableStatement AutoSemi { AST.JSExport $1 (AST.JSExportStatement $2) $3 {- 'ExportDeclaration2' -} } +ExportDeclaration : Export ExportClause AutoSemi + { AST.JSExport $1 $2 $3 {- 'ExportDeclaration1' -} } + | Export VariableStatement AutoSemi + { AST.JSExport $1 (AST.JSExportStatement $2) $3 {- 'ExportDeclaration2' -} } -- ExportClause : -- { } -- { ExportsList } -- { ExportsList , } ExportClause :: { AST.JSExportBody } -ExportClause : LBrace RBrace { AST.JSExportClause $1 Nothing $2 {- 'ExportClause1' -} } - | LBrace ExportsList RBrace { AST.JSExportClause $1 (Just $2) $3 {- 'ExportClause2' -} } +ExportClause : LBrace RBrace + { AST.JSExportClause $1 Nothing $2 {- 'ExportClause1' -} } + | LBrace ExportsList RBrace + { AST.JSExportClause $1 (Just $2) $3 {- 'ExportClause2' -} } -- ExportsList : -- ExportSpecifier -- ExportsList , ExportSpecifier ExportsList :: { AST.JSCommaList AST.JSExportSpecifier } -ExportsList : ExportSpecifier { AST.JSLOne $1 {- 'ExportsList1' -} } - | ExportsList Comma ExportSpecifier { AST.JSLCons $1 $2 $3 {- 'ExportsList2' -} } +ExportsList : ExportSpecifier + { AST.JSLOne $1 {- 'ExportsList1' -} } + | ExportsList Comma ExportSpecifier + { AST.JSLCons $1 $2 $3 {- 'ExportsList2' -} } -- ExportSpecifier : -- IdentifierName -- IdentifierName as IdentifierName ExportSpecifier :: { AST.JSExportSpecifier } -ExportSpecifier : IdentifierName { AST.JSExportSpecifier (identName $1) {- 'ExportSpecifier1' -} } - | IdentifierName As IdentifierName { AST.JSExportSpecifierAs (identName $1) $2 (identName $3) {- 'ExportSpecifier2' -} } +ExportSpecifier : IdentifierName + { AST.JSExportSpecifier (identName $1) {- 'ExportSpecifier1' -} } + | IdentifierName As IdentifierName + { AST.JSExportSpecifierAs (identName $1) $2 (identName $3) {- 'ExportSpecifier2' -} } -- For debugging/other entry points LiteralMain :: { AST.JSAST } From 580990e04b1f5d4d5a18d3b070738009188a4a69 Mon Sep 17 00:00:00 2001 From: Daniel Gasienica Date: Sun, 18 Nov 2018 01:44:20 -0500 Subject: [PATCH 9/9] Update copyright --- language-javascript.cabal | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/language-javascript.cabal b/language-javascript.cabal index b1900e5..b18afb1 100644 --- a/language-javascript.cabal +++ b/language-javascript.cabal @@ -9,7 +9,9 @@ License: BSD3 License-file: LICENSE Author: Alan Zimmerman Maintainer: Erik de Castro Lopo -Copyright: (c) 2010-2015 Alan Zimmerman, 2015 Erik de Castro Lopo +Copyright: (c) 2010-2015 Alan Zimmerman + (c) 2015-2018 Erik de Castro Lopo + (c) 2018 Daniel Gasienica Category: Language Build-type: Simple homepage: https://github.com/erikd/language-javascript