language-javascript 0.7.0.0 → 0.7.1.0
raw patch · 13 files changed
+77/−29 lines, 13 files
Files
- ChangeLog.md +3/−0
- README.md +6/−1
- buildall.sh +0/−8
- language-javascript.cabal +1/−2
- src/Language/JavaScript/Parser/AST.hs +4/−0
- src/Language/JavaScript/Parser/Grammar7.y +39/−15
- src/Language/JavaScript/Parser/Lexer.x +3/−1
- src/Language/JavaScript/Parser/Token.hs +2/−0
- src/Language/JavaScript/Pretty/Printer.hs +5/−1
- src/Language/JavaScript/Process/Minify.hs +4/−0
- test/Test/Language/Javascript/Lexer.hs +3/−0
- test/Test/Language/Javascript/Minify.hs +4/−0
- test/Test/Language/Javascript/ProgramParser.hs +3/−1
ChangeLog.md view
@@ -1,5 +1,8 @@ # ChangeLog for `language-javascript` +## 0.7.1.0 -- 2020-03-22++ Add support for `async` function specifiers and `await` keyword.+ ## 0.7.0.0 -- 2019-10-10 + Add support for (Ryan Hendrickson):
README.md view
@@ -14,7 +14,7 @@ (https://github.com/erikd/language-javascript/tree/master) branch of this github repository. -* 0.6 series : This has a vastly different and improved AST which makes if far+* 0.6 and 0.7 series : This has a vastly different and improved AST which makes if far more difficult to build an non-sensical Javascript AST. This code is in the [new-ast](https://github.com/erikd/language-javascript/tree/new-ast) branch of this github repository.@@ -22,6 +22,11 @@ How to build ------------++Make sure your locale supports UTF-8. For example, on most Unix-like platforms,+you can type:++ export LC_ALL=en_US.UTF-8 Library:
− buildall.sh
@@ -1,8 +0,0 @@-#!/bin/sh--# First run alex on Lexer.x to generate Lexer.hs-#./runalex.sh--# do a clean build of all, including the tests-#cabal clean && cabal configure -fbuildtests && cabal build && cabal haddock-cabal clean && cabal configure --enable-tests && cabal build && cabal test && cabal haddock
language-javascript.cabal view
@@ -1,5 +1,5 @@ Name: language-javascript-Version: 0.7.0.0+Version: 0.7.1.0 Synopsis: Parser for JavaScript Description: Parses Javascript into an Abstract Syntax Tree (AST). Initially intended as frontend to hjsmin. .@@ -19,7 +19,6 @@ Extra-source-files: README.md ChangeLog.md .ghci- buildall.sh test/Unicode.js test/k.js test/unicode.txt
src/Language/JavaScript/Parser/AST.hs view
@@ -146,6 +146,7 @@ | 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+ | JSAsyncFunction !JSAnnot !JSAnnot !JSIdent !JSAnnot !(JSCommaList JSExpression) !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@@ -177,6 +178,7 @@ -- | Non Terminals | JSArrayLiteral !JSAnnot ![JSArrayElement] !JSAnnot -- ^lb, contents, rb | JSAssignExpression !JSExpression !JSAssignOp !JSExpression -- ^lhs, assignop, rhs+ | JSAwaitExpression !JSAnnot !JSExpression -- ^await, expr | JSCallExpression !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot -- ^expr, bl, args, rb | JSCallExpressionDot !JSExpression !JSAnnot !JSExpression -- ^expr, dot, expr | JSCallExpressionSquare !JSExpression !JSAnnot !JSExpression !JSAnnot -- ^expr, [, expr, ]@@ -391,6 +393,7 @@ 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 (JSAsyncFunction _ _ n _lb pl _rb x3 _) = "JSAsyncFunction " ++ 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 ++ ")"@@ -412,6 +415,7 @@ instance ShowStripped JSExpression where ss (JSArrayLiteral _lb xs _rb) = "JSArrayLiteral " ++ ss xs ss (JSAssignExpression lhs op rhs) = "JSOpAssign (" ++ ss op ++ "," ++ ss lhs ++ "," ++ ss rhs ++ ")"+ ss (JSAwaitExpression _ e) = "JSAwaitExpresson " ++ ss e 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 ++ ")"
src/Language/JavaScript/Parser/Grammar7.y view
@@ -86,6 +86,8 @@ 'as' { AsToken {} } 'autosemi' { AutoSemiToken {} }+ 'async' { AsyncToken {} }+ 'await' { AwaitToken {} } 'break' { BreakToken {} } 'case' { CaseToken {} } 'catch' { CatchToken {} }@@ -331,6 +333,8 @@ -- TODO: make this include any reserved word too, including future ones IdentifierName :: { AST.JSExpression } IdentifierName : Identifier {$1}+ | 'async' { AST.JSIdentifier (mkJSAnnot $1) "async" }+ | 'await' { AST.JSIdentifier (mkJSAnnot $1) "await" } | 'break' { AST.JSIdentifier (mkJSAnnot $1) "break" } | 'case' { AST.JSIdentifier (mkJSAnnot $1) "case" } | 'catch' { AST.JSIdentifier (mkJSAnnot $1) "catch" }@@ -407,6 +411,12 @@ Continue :: { AST.JSAnnot } Continue : 'continue' { mkJSAnnot $1 } +Async :: { AST.JSAnnot }+Async : 'async' { mkJSAnnot $1 }++Await :: { AST.JSAnnot }+Await : 'await' { mkJSAnnot $1 }+ Break :: { AST.JSAnnot } Break : 'break' { mkJSAnnot $1 } @@ -657,6 +667,10 @@ NewExpression : MemberExpression { $1 {- 'NewExpression1' -} } | New NewExpression { AST.JSNewExpression $1 $2 {- 'NewExpression2' -} } +AwaitExpression :: { AST.JSExpression }+AwaitExpression+ : Await Expression { AST.JSAwaitExpression $1 $2 }+ -- CallExpression : See 11.2 -- MemberExpression Arguments -- CallExpression Arguments@@ -696,6 +710,7 @@ LeftHandSideExpression :: { AST.JSExpression } LeftHandSideExpression : NewExpression { $1 {- 'LeftHandSideExpression1' -} } | CallExpression { $1 {- 'LeftHandSideExpression12' -} }+ | AwaitExpression { $1 {- 'LeftHandSideExpression13' -} } -- PostfixExpression : See 11.3 -- LeftHandSideExpression@@ -976,22 +991,25 @@ | EmptyStatement { $1 {- 'Statement2' -} } StatementNoEmpty :: { AST.JSStatement }-StatementNoEmpty : StatementBlock { $1 {- 'StatementNoEmpty1' -} }- | VariableStatement { $1 {- 'StatementNoEmpty2' -} }- | ExpressionStatement { $1 {- 'StatementNoEmpty4' -} }- | IfStatement { $1 {- 'StatementNoEmpty5' -} }- | IterationStatement { $1 {- 'StatementNoEmpty6' -} }- | ContinueStatement { $1 {- 'StatementNoEmpty7' -} }- | BreakStatement { $1 {- 'StatementNoEmpty8' -} }- | ReturnStatement { $1 {- 'StatementNoEmpty9' -} }- | WithStatement { $1 {- 'StatementNoEmpty10' -} }- | LabelledStatement { $1 {- 'StatementNoEmpty11' -} }- | SwitchStatement { $1 {- 'StatementNoEmpty12' -} }- | ThrowStatement { $1 {- 'StatementNoEmpty13' -} }- | TryStatement { $1 {- 'StatementNoEmpty14' -} }- | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} }+StatementNoEmpty+ : IfStatement { $1 {- 'StatementNoEmpty5' -} }+ | ContinueStatement { $1 {- 'StatementNoEmpty7' -} }+ | BreakStatement { $1 {- 'StatementNoEmpty8' -} }+ | ReturnStatement { $1 {- 'StatementNoEmpty9' -} }+ | WithStatement { $1 {- 'StatementNoEmpty10' -} }+ | LabelledStatement { $1 {- 'StatementNoEmpty11' -} }+ | SwitchStatement { $1 {- 'StatementNoEmpty12' -} }+ | ThrowStatement { $1 {- 'StatementNoEmpty13' -} }+ | TryStatement { $1 {- 'StatementNoEmpty14' -} }+ | StatementBlock { $1 {- 'StatementNoEmpty1' -} }+ | VariableStatement { $1 {- 'StatementNoEmpty2' -} }+ | IterationStatement { $1 {- 'StatementNoEmpty6' -} }+ | ExpressionStatement { $1 {- 'StatementNoEmpty4' -} }+ | AsyncFunctionStatement { $1 {- 'StatementNoEmpty15' -} }+ | DebuggerStatement { $1 {- 'StatementNoEmpty15' -} } + StatementBlock :: { AST.JSStatement } StatementBlock : Block MaybeSemi { blockToStatement $1 $2 {- 'StatementBlock1' -} } @@ -1208,8 +1226,11 @@ -- FunctionDeclaration : See clause 13 -- function Identifier ( FormalParameterListopt ) { FunctionBody } FunctionDeclaration :: { AST.JSStatement }-FunctionDeclaration : NamedFunctionExpression MaybeSemi { expressionToStatement $1 $2 {- 'FunctionDeclaration1' -} }+FunctionDeclaration : NamedFunctionExpression MaybeSemi { expressionToStatement $1 $2 {- 'FunctionDeclaration1' -} } +AsyncFunctionStatement :: { AST.JSStatement }+AsyncFunctionStatement : Async NamedFunctionExpression MaybeSemi { expressionToAsyncFunction $1 $2 $3 {- 'AsyncFunctionStatement1' -} }+ -- FunctionExpression : See clause 13 -- function Identifieropt ( FormalParameterListopt ) { FunctionBody } FunctionExpression :: { AST.JSExpression }@@ -1499,6 +1520,9 @@ 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 +expressionToAsyncFunction :: AST.JSAnnot -> AST.JSExpression -> AST.JSSemi -> AST.JSStatement+expressionToAsyncFunction aa (AST.JSFunctionExpression a b@(AST.JSIdentName{}) c d e f) s = AST.JSAsyncFunction aa a b c d e f s+expressionToAsyncFunction _aa _exp _s = error "Bad async function." mkJSCallExpression :: AST.JSExpression -> JSArguments -> AST.JSExpression mkJSCallExpression e (JSArguments l arglist r) = AST.JSCallExpression e l arglist r
src/Language/JavaScript/Parser/Lexer.x view
@@ -529,7 +529,9 @@ keywordNames :: [(String, TokenPosn -> String -> [CommentAnnotation] -> Token)] keywordNames =- [ ( "break", BreakToken )+ [ ( "async", AsyncToken )+ , ( "await", AwaitToken )+ , ( "break", BreakToken ) , ( "case", CaseToken ) , ( "catch", CatchToken )
src/Language/JavaScript/Parser/Token.hs view
@@ -56,6 +56,8 @@ -- ^ Literal: Regular Expression -- Keywords+ | AsyncToken { tokenSpan :: !TokenPosn, tokenLiteral :: !String, tokenComment :: ![CommentAnnotation] }+ | AwaitToken { 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] }
src/Language/JavaScript/Pretty/Printer.hs view
@@ -1,5 +1,5 @@ -{-# LANGUAGE FlexibleInstances, NoOverloadedStrings, TypeSynonymInstances #-}+{-# LANGUAGE CPP, FlexibleInstances, NoOverloadedStrings, TypeSynonymInstances #-} module Language.JavaScript.Pretty.Printer ( -- * Printing@@ -10,8 +10,10 @@ import Blaze.ByteString.Builder (Builder, toLazyByteString) import Data.List+#if ! MIN_VERSION_base(4,13,0) import Data.Monoid (mempty) import Data.Semigroup ((<>))+#endif import Data.Text.Lazy (Text) import Language.JavaScript.Parser.AST import Language.JavaScript.Parser.SrcLocation@@ -74,6 +76,7 @@ (|>) pacc (JSArrayLiteral als xs ars) = pacc |> als |> "[" |> xs |> ars |> "]" (|>) pacc (JSArrowExpression xs a x) = pacc |> xs |> a |> "=>" |> x (|>) pacc (JSAssignExpression lhs op rhs) = pacc |> lhs |> op |> rhs+ (|>) pacc (JSAwaitExpression a e) = pacc |> a |> "await" |> e (|>) 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 |> "]"@@ -242,6 +245,7 @@ (|>) 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 (JSAsyncFunction aa af n alb x2s arb x3 s) = pacc |> aa |> "async" |> af |> "function" |> n |> alb |> "(" |> x2s |> arb |> ")" |> x3 |> s (|>) 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
src/Language/JavaScript/Process/Minify.hs view
@@ -5,7 +5,9 @@ minifyJS ) where +#if ! MIN_VERSION_base(4,13,0) import Control.Applicative ((<$>))+#endif import Language.JavaScript.Parser.AST import Language.JavaScript.Parser.SrcLocation@@ -57,6 +59,7 @@ 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 (JSAsyncFunction _ _ n _ ps _ blk _) = JSAsyncFunction a spaceAnnot (fixSpace n) emptyAnnot (fixEmpty ps) emptyAnnot (fixEmpty blk) s 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)@@ -155,6 +158,7 @@ fix _ (JSArrayLiteral _ xs _) = JSArrayLiteral emptyAnnot (map fixEmpty xs) emptyAnnot fix a (JSArrowExpression ps _ ss) = JSArrowExpression (fix a ps) emptyAnnot (fixStmt emptyAnnot noSemi ss) fix a (JSAssignExpression lhs op rhs) = JSAssignExpression (fix a lhs) (fixEmpty op) (fixEmpty rhs)+ fix a (JSAwaitExpression _ ex) = JSAwaitExpression a (fixSpace ex) 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
test/Test/Language/Javascript/Lexer.hs view
@@ -69,6 +69,9 @@ testLex "in\n" `shouldBe` "[InToken,WsToken]" testLex "of\n" `shouldBe` "[OfToken,WsToken]" + it "function" $ do+ testLex "async function\n" `shouldBe` "[AsyncToken,WsToken,FunctionToken,WsToken]"+ testLex :: String -> String testLex str =
test/Test/Language/Javascript/Minify.hs view
@@ -232,6 +232,7 @@ 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}"+ minifyStmt " async function f ( ) { } " `shouldBe` "async function f(){}" it "generator" $ do minifyStmt " function * f ( ) { } ; " `shouldBe` "function*f(){}"@@ -278,6 +279,9 @@ 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()]{}"++ it "miscellaneous" $+ minifyStmt " let r = await p ; " `shouldBe` "let r=await p" testMinifyProg :: Spec testMinifyProg = describe "Minify programs:" $ do
test/Test/Language/Javascript/ProgramParser.hs view
@@ -1,9 +1,11 @@+{-# LANGUAGE CPP #-} module Test.Language.Javascript.ProgramParser ( testProgramParser ) where -+#if ! MIN_VERSION_base(4,13,0) import Control.Applicative ((<$>))+#endif import Test.Hspec import Language.JavaScript.Parser