From f474f4ec9d44e8256a2ec24dd9a4be3f384add0c Mon Sep 17 00:00:00 2001 From: Ilias Tsitsimpis Date: Tue, 16 Jun 2020 10:31:41 +0100 Subject: [PATCH] Import haskell-language-javascript_0.7.1.0.orig.tar.gz [dgit import orig haskell-language-javascript_0.7.1.0.orig.tar.gz] --- .ghci | 5 + ChangeLog.md | 30 + LICENSE | 30 + README.md | 62 + Setup.hs | 2 + language-javascript.cabal | 93 + src/Language/JavaScript/Parser.hs | 44 + src/Language/JavaScript/Parser/AST.hs | 673 +++++++ src/Language/JavaScript/Parser/Grammar7.y | 1580 +++++++++++++++++ src/Language/JavaScript/Parser/Lexer.x | 692 ++++++++ src/Language/JavaScript/Parser/LexerUtils.hs | 63 + src/Language/JavaScript/Parser/ParseError.hs | 45 + src/Language/JavaScript/Parser/Parser.hs | 94 + src/Language/JavaScript/Parser/ParserMonad.hs | 35 + src/Language/JavaScript/Parser/SrcLocation.hs | 21 + src/Language/JavaScript/Parser/Token.hs | 178 ++ src/Language/JavaScript/Pretty/Printer.hs | 383 ++++ src/Language/JavaScript/Process/Minify.hs | 449 +++++ .../Language/Javascript/ExpressionParser.hs | 200 +++ test/Test/Language/Javascript/Lexer.hs | 97 + .../Test/Language/Javascript/LiteralParser.hs | 103 ++ test/Test/Language/Javascript/Minify.hs | 351 ++++ test/Test/Language/Javascript/ModuleParser.hs | 65 + .../Test/Language/Javascript/ProgramParser.hs | 94 + test/Test/Language/Javascript/RoundTrip.hs | 166 ++ .../Language/Javascript/StatementParser.hs | 135 ++ test/Unicode.js | 6 + test/k.js | 1 + test/testsuite.hs | 38 + test/unicode.txt | 30 + 30 files changed, 5765 insertions(+) create mode 100755 .ghci create mode 100755 ChangeLog.md create mode 100644 LICENSE create mode 100755 README.md create mode 100644 Setup.hs create mode 100644 language-javascript.cabal create mode 100644 src/Language/JavaScript/Parser.hs create mode 100644 src/Language/JavaScript/Parser/AST.hs create mode 100644 src/Language/JavaScript/Parser/Grammar7.y create mode 100755 src/Language/JavaScript/Parser/Lexer.x create mode 100644 src/Language/JavaScript/Parser/LexerUtils.hs create mode 100644 src/Language/JavaScript/Parser/ParseError.hs create mode 100644 src/Language/JavaScript/Parser/Parser.hs create mode 100644 src/Language/JavaScript/Parser/ParserMonad.hs create mode 100644 src/Language/JavaScript/Parser/SrcLocation.hs create mode 100644 src/Language/JavaScript/Parser/Token.hs create mode 100644 src/Language/JavaScript/Pretty/Printer.hs create mode 100644 src/Language/JavaScript/Process/Minify.hs create mode 100644 test/Test/Language/Javascript/ExpressionParser.hs create mode 100644 test/Test/Language/Javascript/Lexer.hs create mode 100644 test/Test/Language/Javascript/LiteralParser.hs create mode 100644 test/Test/Language/Javascript/Minify.hs create mode 100644 test/Test/Language/Javascript/ModuleParser.hs create mode 100644 test/Test/Language/Javascript/ProgramParser.hs create mode 100644 test/Test/Language/Javascript/RoundTrip.hs create mode 100644 test/Test/Language/Javascript/StatementParser.hs create mode 100755 test/Unicode.js create mode 100755 test/k.js create mode 100644 test/testsuite.hs create mode 100755 test/unicode.txt diff --git a/.ghci b/.ghci new file mode 100755 index 0000000..14b01ea --- /dev/null +++ b/.ghci @@ -0,0 +1,5 @@ +-- Startup commands for the GHC interpreter +:set -hide-package monads-tf +:set -hide-package monads-fd +:set -i./src +:set -i./dist/build diff --git a/ChangeLog.md b/ChangeLog.md new file mode 100755 index 0000000..d23ae74 --- /dev/null +++ b/ChangeLog.md @@ -0,0 +1,30 @@ +# 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): + - 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): + - Unparenthesized arrow functions of one parameter + - Export from declarations + - Add back support for identifiers named `as` + +## 0.6.0.12 -- 2019-05-03 + ++ Add support for for..of and friends (Franco Bulgarelli) diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..0c03bcc --- /dev/null +++ b/LICENSE @@ -0,0 +1,30 @@ +Copyright (c)2010, Alan Zimmerman + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above + copyright notice, this list of conditions and the following + disclaimer in the documentation and/or other materials provided + with the distribution. + + * Neither the name of Alan Zimmerman nor the names of other + contributors may be used to endorse or promote products derived + from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/README.md b/README.md new file mode 100755 index 0000000..1d7c910 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +Parser for JavaScript +--------------------- + +[![Build Status](https://secure.travis-ci.org/erikd/language-javascript.png?branch=master)](http://travis-ci.org/erikd/language-javascript) + +Based (loosely) on language-python + +Two Versions +------------ + +There are currently two versions: + +* 0.5 series : Is a continuation of the 0.5.X.Y series, from the [master] +(https://github.com/erikd/language-javascript/tree/master) branch of this +github repository. + +* 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. + + +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: + + cabal clean && cabal configure && cabal build + +Tests: + + cabal clean && cabal configure -fbuildtests && cabal build + +Running the tests + + ./dist/build/runtests/runtests + + +To debug the grammar + + happy -iparse.txt -g -a -d src/Language/JavaScript/Parser/Grammar5.y + +This generates src/Language/JavaScript/Parser/Grammar5.hs, delete this +when done with the debug version + + +UTF8/Unicode version +-------------------- + +Alex 3.0 now supports unicode natively, and has been included as a +dependency in the cabal file. + +Note: The generation of the lexical analyser has been separated out, + to remove the install-time dependency on Alex. If any changes + need to be made to the lexer, the Lexer.x source lies in + src-dev, and the runalex.sh script will invoke Alex with the + appropriate directories. diff --git a/Setup.hs b/Setup.hs new file mode 100644 index 0000000..9a994af --- /dev/null +++ b/Setup.hs @@ -0,0 +1,2 @@ +import Distribution.Simple +main = defaultMain diff --git a/language-javascript.cabal b/language-javascript.cabal new file mode 100644 index 0000000..e3eb005 --- /dev/null +++ b/language-javascript.cabal @@ -0,0 +1,93 @@ +Name: language-javascript +Version: 0.7.1.0 +Synopsis: Parser for JavaScript +Description: Parses Javascript into an Abstract Syntax Tree (AST). Initially intended as frontend to hjsmin. + . + Note: Version 0.5.0 breaks compatibility with prior versions, the AST has been reworked to allow + round trip processing of JavaScript. +License: BSD3 +License-file: LICENSE +Author: Alan Zimmerman +Maintainer: Erik de Castro Lopo +Copyright: (c) 2010-2015 Alan Zimmerman + (c) 2015-2019 Erik de Castro Lopo + (c) 2018 Daniel Gasienica +Category: Language +Build-type: Simple +homepage: https://github.com/erikd/language-javascript +bug-reports: https://github.com/erikd/language-javascript/issues +Extra-source-files: README.md + ChangeLog.md + .ghci + test/Unicode.js + test/k.js + test/unicode.txt + src/Language/JavaScript/Parser/Lexer.x + +-- Version requirement upped for test support in later Cabal +Cabal-version: >= 1.9.2 + + +Library + Build-depends: base >= 4 && < 5 + , array >= 0.3 + , mtl >= 1.1 + , containers >= 0.2 + , blaze-builder >= 0.2 + , bytestring >= 0.9.1 + , text >= 1.2 + , utf8-string >= 0.3.7 && < 2 + if !impl(ghc>=8.0) + build-depends: semigroups >= 0.16.1 + + if impl(ghc >= 7.10) + build-tools: happy >= 1.19, alex >= 3.1.4 + else + if impl(ghc >= 7.8) + build-tools: happy >= 1.19, alex >= 3.1 + else + build-tools: happy >= 1.18.5, alex >= 3.0.5 + hs-source-dirs: src + Exposed-modules: Language.JavaScript.Parser + Language.JavaScript.Parser.AST + Language.JavaScript.Parser.Grammar7 + Language.JavaScript.Parser.Lexer + Language.JavaScript.Parser.Parser + Language.JavaScript.Parser.SrcLocation + Language.JavaScript.Pretty.Printer + Language.JavaScript.Process.Minify + Other-modules: Language.JavaScript.Parser.LexerUtils + Language.JavaScript.Parser.ParseError + Language.JavaScript.Parser.ParserMonad + Language.JavaScript.Parser.Token + ghc-options: -Wall -fwarn-tabs + +Test-Suite testsuite + Type: exitcode-stdio-1.0 + Main-is: testsuite.hs + hs-source-dirs: test + ghc-options: -Wall -fwarn-tabs + build-depends: base, Cabal >= 1.9.2 + , QuickCheck >= 2 + , hspec + , array >= 0.3 + , utf8-light >= 0.4 + , containers >= 0.2 + , mtl >= 1.1 + , utf8-string >= 0.3.7 && < 2 + , bytestring >= 0.9.1 + , blaze-builder >= 0.2 + , language-javascript + + Other-modules: Test.Language.Javascript.ExpressionParser + Test.Language.Javascript.Lexer + Test.Language.Javascript.LiteralParser + Test.Language.Javascript.Minify + Test.Language.Javascript.ModuleParser + Test.Language.Javascript.ProgramParser + Test.Language.Javascript.RoundTrip + Test.Language.Javascript.StatementParser + +source-repository head + type: git + location: https://github.com/erikd/language-javascript.git diff --git a/src/Language/JavaScript/Parser.hs b/src/Language/JavaScript/Parser.hs new file mode 100644 index 0000000..750c0ed --- /dev/null +++ b/src/Language/JavaScript/Parser.hs @@ -0,0 +1,44 @@ +module Language.JavaScript.Parser + ( + PA.parse + , PA.parseModule + , PA.readJs + , PA.readJsModule + , PA.parseFile + , PA.parseFileUtf8 + , PA.showStripped + , PA.showStrippedMaybe + -- * AST elements + , JSExpression (..) + , JSAnnot (..) + , JSBinOp (..) + , JSBlock (..) + , JSUnaryOp (..) + , JSSemi (..) + , JSAssignOp (..) + , JSTryCatch (..) + , JSTryFinally (..) + , JSStatement (..) + , JSSwitchParts (..) + , JSAST(..) + + + , CommentAnnotation(..) + -- , ParseError(..) + -- Source locations + , TokenPosn(..) + , tokenPosnEmpty + -- * Pretty Printing + , renderJS + , renderToString + , renderToText + ) where + + +import Language.JavaScript.Parser.AST +import Language.JavaScript.Parser.Token +import qualified Language.JavaScript.Parser.Parser as PA +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 new file mode 100644 index 0000000..3230272 --- /dev/null +++ b/src/Language/JavaScript/Parser/AST.hs @@ -0,0 +1,673 @@ +{-# LANGUAGE DeriveDataTypeable, FlexibleInstances #-} + +module Language.JavaScript.Parser.AST + ( JSExpression (..) + , JSAnnot (..) + , JSBinOp (..) + , JSUnaryOp (..) + , JSSemi (..) + , JSAssignOp (..) + , JSTryCatch (..) + , JSTryFinally (..) + , JSStatement (..) + , JSBlock (..) + , JSSwitchParts (..) + , JSAST (..) + , JSObjectProperty (..) + , JSPropertyName (..) + , JSObjectPropertyList + , JSAccessor (..) + , JSMethodDefinition (..) + , JSIdent (..) + , JSVarInitializer (..) + , JSArrayElement (..) + , JSCommaList (..) + , JSCommaTrailingList (..) + , JSArrowParameterList (..) + , JSTemplatePart (..) + , JSClassHeritage (..) + , JSClassElement (..) + + -- Modules + , JSModuleItem (..) + , JSImportDeclaration (..) + , JSImportClause (..) + , JSFromClause (..) + , JSImportNameSpace (..) + , JSImportsNamed (..) + , JSImportSpecifier (..) + , JSExportDeclaration (..) + , JSExportClause (..) + , JSExportSpecifier (..) + + , binOpEq + , showStripped + ) where + +import Data.Data +import Data.List +import Language.JavaScript.Parser.SrcLocation (TokenPosn (..)) +import Language.JavaScript.Parser.Token + +-- --------------------------------------------------------------------- + +data JSAnnot + = JSAnnot !TokenPosn ![CommentAnnotation] -- ^Annotation: position and comment/whitespace information + | JSAnnotSpace -- ^A single space character + | JSNoAnnot -- ^No annotation + deriving (Data, Eq, Show, Typeable) + + +data JSAST + = JSAstProgram ![JSStatement] !JSAnnot -- ^source elements, trailing whitespace + | JSAstModule ![JSModuleItem] !JSAnnot + | JSAstStatement !JSStatement !JSAnnot + | JSAstExpression !JSExpression !JSAnnot + | JSAstLiteral !JSExpression !JSAnnot + deriving (Data, Eq, Show, Typeable) + +-- Shift AST +-- https://github.com/shapesecurity/shift-spec/blob/83498b92c436180cc0e2115b225a68c08f43c53e/spec.idl#L229-L234 +data JSModuleItem + = JSModuleImportDeclaration !JSAnnot !JSImportDeclaration -- ^import,decl + | JSModuleExportDeclaration !JSAnnot !JSExportDeclaration -- ^export,decl + | JSModuleStatementListItem !JSStatement + deriving (Data, Eq, Show, Typeable) + +data JSImportDeclaration + = JSImportDeclaration !JSImportClause !JSFromClause !JSSemi -- ^imports, module, semi + | JSImportDeclarationBare !JSAnnot !String !JSSemi -- ^module, module, semi + deriving (Data, Eq, Show, Typeable) + +data JSImportClause + = JSImportClauseDefault !JSIdent -- ^default + | JSImportClauseNameSpace !JSImportNameSpace -- ^namespace + | JSImportClauseNamed !JSImportsNamed -- ^named imports + | JSImportClauseDefaultNameSpace !JSIdent !JSAnnot !JSImportNameSpace -- ^default, comma, namespace + | JSImportClauseDefaultNamed !JSIdent !JSAnnot !JSImportsNamed -- ^default, comma, named imports + deriving (Data, Eq, Show, Typeable) + +data JSFromClause + = JSFromClause !JSAnnot !JSAnnot !String -- ^ from, string literal, string literal contents + deriving (Data, Eq, Show, Typeable) + +-- | Import namespace, e.g. '* as whatever' +data JSImportNameSpace + = JSImportNameSpace !JSBinOp !JSAnnot !JSIdent -- ^ *, as, ident + deriving (Data, Eq, Show, Typeable) + +-- | Named imports, e.g. '{ foo, bar, baz as quux }' +data JSImportsNamed + = JSImportsNamed !JSAnnot !(JSCommaList JSImportSpecifier) !JSAnnot -- ^lb, specifiers, rb + deriving (Data, Eq, Show, Typeable) + +-- | +-- Note that this data type is separate from ExportSpecifier because the +-- grammar is slightly different (e.g. in handling of reserved words). +data JSImportSpecifier + = JSImportSpecifier !JSIdent -- ^ident + | JSImportSpecifierAs !JSIdent !JSAnnot !JSIdent -- ^ident, as, ident + deriving (Data, Eq, Show, Typeable) + +data JSExportDeclaration + -- = JSExportAllFrom + = JSExportFrom JSExportClause JSFromClause !JSSemi -- ^exports, module, semi + | JSExportLocals JSExportClause !JSSemi -- ^exports, autosemi + | JSExport !JSStatement !JSSemi -- ^body, autosemi + -- | JSExportDefault + deriving (Data, Eq, Show, Typeable) + +data JSExportClause + = JSExportClause !JSAnnot !(JSCommaList JSExportSpecifier) !JSAnnot -- ^lb, specifiers, rb + deriving (Data, Eq, Show, Typeable) + +data JSExportSpecifier + = JSExportSpecifier !JSIdent -- ^ident + | JSExportSpecifierAs !JSIdent !JSAnnot !JSIdent -- ^ident1, as, ident2 + deriving (Data, Eq, Show, Typeable) + +data JSStatement + = 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 + | JSFor !JSAnnot !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSStatement -- ^for,lb,expr,semi,expr,semi,expr,rb.stmt + | JSForIn !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,expr,in,expr,rb,stmt + | JSForVar !JSAnnot !JSAnnot !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSStatement -- ^for,lb,var,vardecl,semi,expr,semi,expr,rb,stmt + | JSForVarIn !JSAnnot !JSAnnot !JSAnnot !JSExpression !JSBinOp !JSExpression !JSAnnot !JSStatement -- ^for,lb,var,vardecl,in,expr,rb,stmt + | 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 + | 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 + | JSIfElse !JSAnnot !JSAnnot !JSExpression !JSAnnot !JSStatement !JSAnnot !JSStatement -- ^if,(,expr,),stmt,else,rest + | JSLabelled !JSIdent !JSAnnot !JSStatement -- ^identifier,colon,stmt + | JSEmptyStatement !JSAnnot + | JSExpressionStatement !JSExpression !JSSemi + | JSAssignStatement !JSExpression !JSAssignOp !JSExpression !JSSemi -- ^lhs, assignop, rhs, autosemi + | JSMethodCall !JSExpression !JSAnnot !(JSCommaList JSExpression) !JSAnnot !JSSemi + | JSReturn !JSAnnot !(Maybe JSExpression) !JSSemi -- ^optional expression,autosemi + | 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, 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 JSExpression + -- | Terminals + = JSIdentifier !JSAnnot !String + | JSDecimal !JSAnnot !String + | JSLiteral !JSAnnot !String + | JSHexInteger !JSAnnot !String + | JSOctal !JSAnnot !String + | JSStringLiteral !JSAnnot !String + | JSRegEx !JSAnnot !String + + -- | 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, ] + | 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 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 + | JSMemberSquare !JSExpression !JSAnnot !JSExpression !JSAnnot -- ^firstpart, lb, expr, rb + | 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 JSExpression) !JSAnnot + deriving (Data, Eq, Show, Typeable) + +data JSBinOp + = JSBinOpAnd !JSAnnot + | JSBinOpBitAnd !JSAnnot + | JSBinOpBitOr !JSAnnot + | JSBinOpBitXor !JSAnnot + | JSBinOpDivide !JSAnnot + | JSBinOpEq !JSAnnot + | JSBinOpGe !JSAnnot + | JSBinOpGt !JSAnnot + | JSBinOpIn !JSAnnot + | JSBinOpInstanceOf !JSAnnot + | JSBinOpLe !JSAnnot + | JSBinOpLsh !JSAnnot + | JSBinOpLt !JSAnnot + | JSBinOpMinus !JSAnnot + | JSBinOpMod !JSAnnot + | JSBinOpNeq !JSAnnot + | JSBinOpOf !JSAnnot + | JSBinOpOr !JSAnnot + | JSBinOpPlus !JSAnnot + | JSBinOpRsh !JSAnnot + | JSBinOpStrictEq !JSAnnot + | JSBinOpStrictNeq !JSAnnot + | JSBinOpTimes !JSAnnot + | JSBinOpUrsh !JSAnnot + deriving (Data, Eq, Show, Typeable) + +data JSUnaryOp + = JSUnaryOpDecr !JSAnnot + | JSUnaryOpDelete !JSAnnot + | JSUnaryOpIncr !JSAnnot + | JSUnaryOpMinus !JSAnnot + | JSUnaryOpNot !JSAnnot + | JSUnaryOpPlus !JSAnnot + | JSUnaryOpTilde !JSAnnot + | JSUnaryOpTypeof !JSAnnot + | JSUnaryOpVoid !JSAnnot + deriving (Data, Eq, Show, Typeable) + +data JSSemi + = JSSemi !JSAnnot + | JSSemiAuto + deriving (Data, Eq, Show, Typeable) + +data JSAssignOp + = JSAssign !JSAnnot + | JSTimesAssign !JSAnnot + | JSDivideAssign !JSAnnot + | JSModAssign !JSAnnot + | JSPlusAssign !JSAnnot + | JSMinusAssign !JSAnnot + | JSLshAssign !JSAnnot + | JSRshAssign !JSAnnot + | JSUrshAssign !JSAnnot + | JSBwAndAssign !JSAnnot + | JSBwXorAssign !JSAnnot + | JSBwOrAssign !JSAnnot + 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 + deriving (Data, Eq, Show, Typeable) + +data JSTryFinally + = JSFinally !JSAnnot !JSBlock -- ^finally,block + | JSNoFinally + deriving (Data, Eq, Show, Typeable) + +data JSBlock + = JSBlock !JSAnnot ![JSStatement] !JSAnnot -- ^lbrace, stmts, rbrace + deriving (Data, Eq, Show, Typeable) + +data JSSwitchParts + = JSCase !JSAnnot !JSExpression !JSAnnot ![JSStatement] -- ^expr,colon,stmtlist + | JSDefault !JSAnnot !JSAnnot ![JSStatement] -- ^colon,stmtlist + deriving (Data, Eq, Show, Typeable) + +data JSVarInitializer + = JSVarInit !JSAnnot !JSExpression -- ^ assignop, initializer + | JSVarInitNone + deriving (Data, Eq, Show, Typeable) + +data JSObjectProperty + = 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 + +-- | Accessors for JSObjectProperty is either 'get' or 'set'. +data JSAccessor + = JSAccessorGet !JSAnnot + | JSAccessorSet !JSAnnot + deriving (Data, Eq, Show, Typeable) + +data JSIdent + = JSIdentName !JSAnnot !String + | JSIdentNone + deriving (Data, Eq, Show, Typeable) + +data JSArrayElement + = JSArrayElement !JSExpression + | JSArrayComma !JSAnnot + deriving (Data, Eq, Show, Typeable) + +data JSCommaList a + = JSLCons !(JSCommaList a) !JSAnnot !a -- ^head, comma, a + | JSLOne !a -- ^ single element (no comma) + | JSLNil + deriving (Data, Eq, Show, Typeable) + +data JSCommaTrailingList a + = JSCTLComma !(JSCommaList a) !JSAnnot -- ^list, trailing comma + | 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. + +-- Strip out the location info +showStripped :: JSAST -> String +showStripped (JSAstProgram xs _) = "JSAstProgram " ++ ss xs +showStripped (JSAstModule xs _) = "JSAstModule " ++ ss xs +showStripped (JSAstStatement s _) = "JSAstStatement (" ++ ss s ++ ")" +showStripped (JSAstExpression e _) = "JSAstExpression (" ++ ss e ++ ")" +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) + 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 + ss (JSDoWhile _d x1 _w _lb x2 _rb x3) = "JSDoWhile (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" + ss (JSFor _ _lb x1s _s1 x2s _s2 x3s _rb x4) = "JSFor " ++ ss x1s ++ " " ++ ss x2s ++ " " ++ ss x3s ++ " (" ++ ss x4 ++ ")" + ss (JSForIn _ _lb x1s _i x2 _rb x3) = "JSForIn " ++ ss x1s ++ " (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" + ss (JSForVar _ _lb _v x1s _s1 x2s _s2 x3s _rb x4) = "JSForVar " ++ ss x1s ++ " " ++ ss x2s ++ " " ++ ss x3s ++ " (" ++ ss x4 ++ ")" + ss (JSForVarIn _ _lb _v x1 _i x2 _rb x3) = "JSForVarIn (" ++ ss x1 ++ ") (" ++ ss x2 ++ ") (" ++ ss x3 ++ ")" + 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 (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 ++ ")" + ss (JSLabelled x1 _c x2) = "JSLabelled (" ++ ss x1 ++ ") (" ++ ss x2 ++ ")" + ss (JSLet _ xs _as) = "JSLet " ++ ss xs + ss (JSEmptyStatement _) = "JSEmptyStatement" + ss (JSExpressionStatement l s) = ss l ++ (let x = ss s in if not (null x) then ',':x else "") + ss (JSAssignStatement lhs op rhs s) ="JSOpAssign (" ++ ss op ++ "," ++ ss lhs ++ "," ++ ss rhs ++ (let x = ss s in if not (null x) then "),"++x else ")") + ss (JSMethodCall e _ a _ s) = "JSMethodCall (" ++ ss e ++ ",JSArguments " ++ ss a ++ (let x = ss s in if not (null x) then "),"++x else ")") + ss (JSReturn _ (Just me) s) = "JSReturn " ++ ss me ++ " " ++ ss s + ss (JSReturn _ Nothing s) = "JSReturn " ++ ss s + ss (JSSwitch _ _lp x _rp _lb x2 _rb _) = "JSSwitch (" ++ ss x ++ ") " ++ ss x2 + ss (JSThrow _ x _) = "JSThrow (" ++ ss x ++ ")" + ss (JSTry _ xt1 xtc xtf) = "JSTry (" ++ ss xt1 ++ "," ++ ss xtc ++ "," ++ ss xtf ++ ")" + 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 ++ ")" + +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 ++ ")" + 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 ++ ")" + ss (JSExpressionParen _lp x _rp) = "JSExpressionParen (" ++ ss x ++ ")" + 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 (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 + ss (JSLiteral _ []) = "JSLiteral ''" + ss (JSLiteral _ s) = "JSLiteral " ++ singleQuote s + ss (JSMemberDot x1s _d x2 ) = "JSMemberDot (" ++ ss x1s ++ "," ++ ss x2 ++ ")" + ss (JSMemberExpression e _ a _) = "JSMemberExpression (" ++ ss e ++ ",JSArguments " ++ ss a ++ ")" + ss (JSMemberNew _a n _ s _) = "JSMemberNew (" ++ ss n ++ ",JSArguments " ++ ss s ++ ")" + ss (JSMemberSquare x1s _lb x2 _rb) = "JSMemberSquare (" ++ ss x1s ++ "," ++ ss x2 ++ ")" + ss (JSNewExpression _n e) = "JSNewExpression " ++ ss e + ss (JSObjectLiteral _lb xs _rb) = "JSObjectLiteral " ++ ss xs + ss (JSRegEx _ s) = "JSRegEx " ++ singleQuote s + 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 + ss (JSParenthesizedArrowParameterList _ xs _) = ss xs + +instance ShowStripped JSModuleItem where + ss (JSModuleExportDeclaration _ x1) = "JSModuleExportDeclaration (" ++ ss x1 ++ ")" + ss (JSModuleImportDeclaration _ x1) = "JSModuleImportDeclaration (" ++ ss x1 ++ ")" + ss (JSModuleStatementListItem x1) = "JSModuleStatementListItem (" ++ ss x1 ++ ")" + +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 ++ ")" + ss (JSImportClauseNameSpace x) = "JSImportClauseNameSpace (" ++ ss x ++ ")" + ss (JSImportClauseNamed x) = "JSImportClauseNameSpace (" ++ ss x ++ ")" + ss (JSImportClauseDefaultNameSpace x1 _ x2) = "JSImportClauseDefaultNameSpace (" ++ ss x1 ++ "," ++ ss x2 ++ ")" + ss (JSImportClauseDefaultNamed x1 _ x2) = "JSImportClauseDefaultNamed (" ++ ss x1 ++ "," ++ ss x2 ++ ")" + +instance ShowStripped JSFromClause where + ss (JSFromClause _ _ m) = "JSFromClause " ++ singleQuote m + +instance ShowStripped JSImportNameSpace where + ss (JSImportNameSpace _ _ x) = "JSImportNameSpace (" ++ ss x ++ ")" + +instance ShowStripped JSImportsNamed where + ss (JSImportsNamed _ xs _) = "JSImportsNamed (" ++ ss xs ++ ")" + +instance ShowStripped JSImportSpecifier where + ss (JSImportSpecifier x1) = "JSImportSpecifier (" ++ ss x1 ++ ")" + ss (JSImportSpecifierAs x1 _ x2) = "JSImportSpecifierAs (" ++ ss x1 ++ "," ++ ss x2 ++ ")" + +instance ShowStripped JSExportDeclaration where + ss (JSExportFrom xs from _) = "JSExportFrom (" ++ ss xs ++ "," ++ ss from ++ ")" + ss (JSExportLocals xs _) = "JSExportLocals (" ++ ss xs ++ ")" + ss (JSExport x1 _) = "JSExport (" ++ ss x1 ++ ")" + +instance ShowStripped JSExportClause where + ss (JSExportClause _ xs _) = "JSExportClause (" ++ ss xs ++ ")" + +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 ++ ")" + +instance ShowStripped JSTryFinally where + ss (JSFinally _ x) = "JSFinally (" ++ ss x ++ ")" + ss JSNoFinally = "JSFinally ()" + +instance ShowStripped JSIdent where + ss (JSIdentName _ s) = "JSIdentifier " ++ singleQuote s + ss JSIdentNone = "JSIdentNone" + +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" + ss (JSAccessorSet _) = "JSAccessorSet" + +instance ShowStripped JSBlock where + ss (JSBlock _ xs _) = "JSBlock " ++ ss xs + +instance ShowStripped JSSwitchParts where + ss (JSCase _ x1 _c x2s) = "JSCase (" ++ ss x1 ++ ") (" ++ ss x2s ++ ")" + ss (JSDefault _ _c xs) = "JSDefault (" ++ ss xs ++ ")" + +instance ShowStripped JSBinOp where + ss (JSBinOpAnd _) = "'&&'" + ss (JSBinOpBitAnd _) = "'&'" + ss (JSBinOpBitOr _) = "'|'" + ss (JSBinOpBitXor _) = "'^'" + ss (JSBinOpDivide _) = "'/'" + ss (JSBinOpEq _) = "'=='" + ss (JSBinOpGe _) = "'>='" + ss (JSBinOpGt _) = "'>'" + ss (JSBinOpIn _) = "'in'" + ss (JSBinOpInstanceOf _) = "'instanceof'" + ss (JSBinOpLe _) = "'<='" + ss (JSBinOpLsh _) = "'<<'" + ss (JSBinOpLt _) = "'<'" + ss (JSBinOpMinus _) = "'-'" + ss (JSBinOpMod _) = "'%'" + ss (JSBinOpNeq _) = "'!='" + ss (JSBinOpOf _) = "'of'" + ss (JSBinOpOr _) = "'||'" + ss (JSBinOpPlus _) = "'+'" + ss (JSBinOpRsh _) = "'>>'" + ss (JSBinOpStrictEq _) = "'==='" + ss (JSBinOpStrictNeq _) = "'!=='" + ss (JSBinOpTimes _) = "'*'" + ss (JSBinOpUrsh _) = "'>>>'" + +instance ShowStripped JSUnaryOp where + ss (JSUnaryOpDecr _) = "'--'" + ss (JSUnaryOpDelete _) = "'delete'" + ss (JSUnaryOpIncr _) = "'++'" + ss (JSUnaryOpMinus _) = "'-'" + ss (JSUnaryOpNot _) = "'!'" + ss (JSUnaryOpPlus _) = "'+'" + ss (JSUnaryOpTilde _) = "'~'" + ss (JSUnaryOpTypeof _) = "'typeof'" + ss (JSUnaryOpVoid _) = "'void'" + +instance ShowStripped JSAssignOp where + ss (JSAssign _) = "'='" + ss (JSTimesAssign _) = "'*='" + ss (JSDivideAssign _) = "'/='" + ss (JSModAssign _) = "'%='" + ss (JSPlusAssign _) = "'+='" + ss (JSMinusAssign _) = "'-='" + ss (JSLshAssign _) = "'<<='" + ss (JSRshAssign _) = "'>>='" + ss (JSUrshAssign _) = "'>>>='" + ss (JSBwAndAssign _) = "'&='" + ss (JSBwXorAssign _) = "'^='" + ss (JSBwOrAssign _) = "'|='" + +instance ShowStripped JSVarInitializer where + ss (JSVarInit _ n) = "[" ++ ss n ++ "]" + ss JSVarInitNone = "" + +instance ShowStripped JSSemi where + ss (JSSemi _) = "JSSemicolon" + ss JSSemiAuto = "" + +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) ++ ")" + +instance ShowStripped a => ShowStripped (JSCommaTrailingList a) where + ss (JSCTLComma xs _) = "[" ++ commaJoin (map ss $ fromCommaList xs) ++ ",JSComma]" + ss (JSCTLNone xs) = "[" ++ commaJoin (map ss $ fromCommaList xs) ++ "]" + +instance ShowStripped a => ShowStripped [a] where + ss xs = "[" ++ commaJoin (map ss xs) ++ "]" + +-- ----------------------------------------------------------------------------- +-- Helpers. + +commaJoin :: [String] -> String +commaJoin s = intercalate "," $ filter (not . null) s + +fromCommaList :: JSCommaList a -> [a] +fromCommaList (JSLCons l _ i) = fromCommaList l ++ [i] +fromCommaList (JSLOne i) = [i] +fromCommaList JSLNil = [] + +singleQuote :: String -> String +singleQuote s = '\'' : (s ++ "'") + +ssid :: JSIdent -> String +ssid (JSIdentName _ s) = singleQuote s +ssid JSIdentNone = "''" + +commaIf :: String -> String +commaIf "" = "" +commaIf xs = ',' : xs + + +deAnnot :: JSBinOp -> JSBinOp +deAnnot (JSBinOpAnd _) = JSBinOpAnd JSNoAnnot +deAnnot (JSBinOpBitAnd _) = JSBinOpBitAnd JSNoAnnot +deAnnot (JSBinOpBitOr _) = JSBinOpBitOr JSNoAnnot +deAnnot (JSBinOpBitXor _) = JSBinOpBitXor JSNoAnnot +deAnnot (JSBinOpDivide _) = JSBinOpDivide JSNoAnnot +deAnnot (JSBinOpEq _) = JSBinOpEq JSNoAnnot +deAnnot (JSBinOpGe _) = JSBinOpGe JSNoAnnot +deAnnot (JSBinOpGt _) = JSBinOpGt JSNoAnnot +deAnnot (JSBinOpIn _) = JSBinOpIn JSNoAnnot +deAnnot (JSBinOpInstanceOf _) = JSBinOpInstanceOf JSNoAnnot +deAnnot (JSBinOpLe _) = JSBinOpLe JSNoAnnot +deAnnot (JSBinOpLsh _) = JSBinOpLsh JSNoAnnot +deAnnot (JSBinOpLt _) = JSBinOpLt JSNoAnnot +deAnnot (JSBinOpMinus _) = JSBinOpMinus JSNoAnnot +deAnnot (JSBinOpMod _) = JSBinOpMod JSNoAnnot +deAnnot (JSBinOpNeq _) = JSBinOpNeq JSNoAnnot +deAnnot (JSBinOpOf _) = JSBinOpOf JSNoAnnot +deAnnot (JSBinOpOr _) = JSBinOpOr JSNoAnnot +deAnnot (JSBinOpPlus _) = JSBinOpPlus JSNoAnnot +deAnnot (JSBinOpRsh _) = JSBinOpRsh JSNoAnnot +deAnnot (JSBinOpStrictEq _) = JSBinOpStrictEq JSNoAnnot +deAnnot (JSBinOpStrictNeq _) = JSBinOpStrictNeq JSNoAnnot +deAnnot (JSBinOpTimes _) = JSBinOpTimes JSNoAnnot +deAnnot (JSBinOpUrsh _) = JSBinOpUrsh JSNoAnnot + +binOpEq :: JSBinOp -> JSBinOp -> Bool +binOpEq a b = deAnnot a == deAnnot b diff --git a/src/Language/JavaScript/Parser/Grammar7.y b/src/Language/JavaScript/Parser/Grammar7.y new file mode 100644 index 0000000..13a1526 --- /dev/null +++ b/src/Language/JavaScript/Parser/Grammar7.y @@ -0,0 +1,1580 @@ +{ +{-# LANGUAGE BangPatterns #-} +module Language.JavaScript.Parser.Grammar7 + ( parseProgram + , parseModule + , parseStatement + , parseExpression + , parseLiteral + ) where + +import Data.Char +import Data.Functor (($>)) +import Language.JavaScript.Parser.Lexer +import Language.JavaScript.Parser.ParserMonad +import Language.JavaScript.Parser.SrcLocation +import Language.JavaScript.Parser.Token +import qualified Language.JavaScript.Parser.AST as AST + +} + +-- The name of the generated function to be exported from the module +%name parseProgram Program +%name parseModule Module +%name parseLiteral LiteralMain +%name parseExpression ExpressionMain +%name parseStatement StatementMain + +%tokentype { Token } +%error { parseError } +%monad { Alex } { >>= } { return } +%lexer { lexCont } { EOFToken {} } + + +%token + + ';' { SemiColonToken {} } + ',' { CommaToken {} } + '?' { HookToken {} } + ':' { ColonToken {} } + '||' { OrToken {} } + '&&' { AndToken {} } + '|' { BitwiseOrToken {} } + '^' { BitwiseXorToken {} } + '&' { BitwiseAndToken {} } + '=>' { ArrowToken {} } + '===' { StrictEqToken {} } + '==' { EqToken {} } + '*=' { TimesAssignToken {} } + '/=' { DivideAssignToken {} } + '%=' { ModAssignToken {} } + '+=' { PlusAssignToken {} } + '-=' { MinusAssignToken {} } + '<<=' { LshAssignToken {} } + '>>=' { RshAssignToken {} } + '>>>=' { UrshAssignToken {} } + '&=' { AndAssignToken {} } + '^=' { XorAssignToken {} } + '|=' { OrAssignToken {} } + '=' { SimpleAssignToken {} } + '!==' { StrictNeToken {} } + '!=' { NeToken {} } + '<<' { LshToken {} } + '<=' { LeToken {} } + '<' { LtToken {} } + '>>>' { UrshToken {} } + '>>' { RshToken {} } + '>=' { GeToken {} } + '>' { GtToken {} } + '++' { IncrementToken {} } + '--' { DecrementToken {} } + '+' { PlusToken {} } + '-' { MinusToken {} } + '*' { MulToken {} } + '/' { DivToken {} } + '%' { ModToken {} } + '!' { NotToken {} } + '~' { BitwiseNotToken {} } + '...' { SpreadToken {} } + '.' { DotToken {} } + '[' { LeftBracketToken {} } + ']' { RightBracketToken {} } + '{' { LeftCurlyToken {} } + '}' { RightCurlyToken {} } + '(' { LeftParenToken {} } + ')' { RightParenToken {} } + + 'as' { AsToken {} } + 'autosemi' { AutoSemiToken {} } + 'async' { AsyncToken {} } + 'await' { AwaitToken {} } + 'break' { BreakToken {} } + 'case' { CaseToken {} } + 'catch' { CatchToken {} } + 'class' { ClassToken {} } + 'const' { ConstToken {} } + 'continue' { ContinueToken {} } + 'debugger' { DebuggerToken {} } + 'default' { DefaultToken {} } + 'delete' { DeleteToken {} } + 'do' { DoToken {} } + 'else' { ElseToken {} } + 'enum' { EnumToken {} } + 'export' { ExportToken {} } + 'extends' { ExtendsToken {} } + 'false' { FalseToken {} } + 'finally' { FinallyToken {} } + 'for' { ForToken {} } + 'function' { FunctionToken {} } + 'from' { FromToken {} } + 'get' { GetToken {} } + 'if' { IfToken {} } + 'import' { ImportToken {} } + 'in' { InToken {} } + 'instanceof' { InstanceofToken {} } + 'let' { LetToken {} } + 'new' { NewToken {} } + 'null' { NullToken {} } + 'of' { OfToken {} } + 'return' { ReturnToken {} } + 'set' { SetToken {} } + 'static' { StaticToken {} } + 'super' { SuperToken {} } + 'switch' { SwitchToken {} } + 'this' { ThisToken {} } + 'throw' { ThrowToken {} } + 'true' { TrueToken {} } + 'try' { TryToken {} } + 'typeof' { TypeofToken {} } + 'var' { VarToken {} } + 'void' { VoidToken {} } + 'while' { WhileToken {} } + 'with' { WithToken {} } + 'yield' { YieldToken {} } + + + 'ident' { IdentifierToken {} } + 'decimal' { DecimalToken {} } + 'hexinteger' { HexIntegerToken {} } + 'octal' { OctalToken {} } + 'string' { StringToken {} } + 'regex' { RegExToken {} } + 'tmplnosub' { NoSubstitutionTemplateToken {} } + 'tmplhead' { TemplateHeadToken {} } + 'tmplmiddle' { TemplateMiddleToken {} } + 'tmpltail' { TemplateTailToken {} } + + 'future' { FutureToken {} } + + 'tail' { TailToken {} } + + +%% + +-- --------------------------------------------------------------------- +-- Sort out automatically inserted semi-colons. +-- A MaybeSemi is an actual semi-colon or nothing. +-- An AutoSemu is either an actual semi-colon or 'virtual' semi-colon inserted +-- by the Alex lexer or nothing. + +MaybeSemi :: { AST.JSSemi } +MaybeSemi : ';' { AST.JSSemi (mkJSAnnot $1) } + | { AST.JSSemiAuto } + +AutoSemi :: { AST.JSSemi } +AutoSemi : ';' { AST.JSSemi (mkJSAnnot $1) } + | 'autosemi' { AST.JSSemiAuto } + | { AST.JSSemiAuto } + +-- --------------------------------------------------------------------- + +-- Helpers + +LParen :: { AST.JSAnnot } +LParen : '(' { mkJSAnnot $1 } + +RParen :: { AST.JSAnnot } +RParen : ')' { mkJSAnnot $1 } + +LBrace :: { AST.JSAnnot } +LBrace : '{' { mkJSAnnot $1 } + +RBrace :: { AST.JSAnnot } +RBrace : '}' { mkJSAnnot $1 } + +LSquare :: { AST.JSAnnot } +LSquare : '[' { mkJSAnnot $1 } + +RSquare :: { AST.JSAnnot } +RSquare : ']' { mkJSAnnot $1 } + +Comma :: { AST.JSAnnot } +Comma : ',' { mkJSAnnot $1 } + +Colon :: { AST.JSAnnot } +Colon : ':' { mkJSAnnot $1 } + +Semi :: { AST.JSAnnot } +Semi : ';' { mkJSAnnot $1 } + +Arrow :: { AST.JSAnnot } +Arrow : '=>' { mkJSAnnot $1 } + +Spread :: { AST.JSAnnot } +Spread : '...' { mkJSAnnot $1 } + +Dot :: { AST.JSAnnot } +Dot : '.' { mkJSAnnot $1 } + +As :: { AST.JSAnnot } +As : 'as' { mkJSAnnot $1 } + +Increment :: { AST.JSUnaryOp } +Increment : '++' { AST.JSUnaryOpIncr (mkJSAnnot $1) } + +Decrement :: { AST.JSUnaryOp } +Decrement : '--' { AST.JSUnaryOpDecr (mkJSAnnot $1) } + +Delete :: { AST.JSUnaryOp } +Delete : 'delete' { AST.JSUnaryOpDelete (mkJSAnnot $1) } + +Void :: { AST.JSUnaryOp } +Void : 'void' { AST.JSUnaryOpVoid (mkJSAnnot $1) } + +Typeof :: { AST.JSUnaryOp } +Typeof : 'typeof' { AST.JSUnaryOpTypeof (mkJSAnnot $1) } + +Plus :: { AST.JSBinOp } +Plus : '+' { AST.JSBinOpPlus (mkJSAnnot $1) } + +Minus :: { AST.JSBinOp } +Minus : '-' { AST.JSBinOpMinus (mkJSAnnot $1) } + +Tilde :: { AST.JSUnaryOp } +Tilde : '~' { AST.JSUnaryOpTilde (mkJSAnnot $1) } + +Not :: { AST.JSUnaryOp } +Not : '!' { AST.JSUnaryOpNot (mkJSAnnot $1) } + +Mul :: { AST.JSBinOp } +Mul : '*' { AST.JSBinOpTimes (mkJSAnnot $1) } + +Div :: { AST.JSBinOp } +Div : '/' { AST.JSBinOpDivide (mkJSAnnot $1) } + +Mod :: { AST.JSBinOp } +Mod : '%' { AST.JSBinOpMod (mkJSAnnot $1) } + +Lsh :: { AST.JSBinOp } +Lsh : '<<' { AST.JSBinOpLsh (mkJSAnnot $1) } + +Rsh :: { AST.JSBinOp } +Rsh : '>>' { AST.JSBinOpRsh (mkJSAnnot $1) } + +Ursh :: { AST.JSBinOp } +Ursh : '>>>' { AST.JSBinOpUrsh (mkJSAnnot $1) } + +Le :: { AST.JSBinOp } +Le : '<=' { AST.JSBinOpLe (mkJSAnnot $1) } + +Lt :: { AST.JSBinOp } +Lt : '<' { AST.JSBinOpLt (mkJSAnnot $1) } + +Ge :: { AST.JSBinOp } +Ge : '>=' { AST.JSBinOpGe (mkJSAnnot $1) } + +Gt :: { AST.JSBinOp } +Gt : '>' { AST.JSBinOpGt (mkJSAnnot $1) } + +In :: { AST.JSBinOp } +In : 'in' { AST.JSBinOpIn (mkJSAnnot $1) } + +Instanceof :: { AST.JSBinOp } +Instanceof : 'instanceof' { AST.JSBinOpInstanceOf (mkJSAnnot $1) } + +StrictEq :: { AST.JSBinOp } +StrictEq : '===' { AST.JSBinOpStrictEq (mkJSAnnot $1) } + +Equal :: { AST.JSBinOp } +Equal : '==' { AST.JSBinOpEq (mkJSAnnot $1) } + +StrictNe :: { AST.JSBinOp } +StrictNe : '!==' { AST.JSBinOpStrictNeq (mkJSAnnot $1) } + +Ne :: { AST.JSBinOp } +Ne : '!=' { AST.JSBinOpNeq (mkJSAnnot $1)} + +Of :: { AST.JSBinOp } +Of : 'of' { AST.JSBinOpOf (mkJSAnnot $1) } + +Or :: { AST.JSBinOp } +Or : '||' { AST.JSBinOpOr (mkJSAnnot $1) } + +And :: { AST.JSBinOp } +And : '&&' { AST.JSBinOpAnd (mkJSAnnot $1) } + +BitOr :: { AST.JSBinOp } +BitOr : '|' { AST.JSBinOpBitOr (mkJSAnnot $1) } + +BitAnd :: { AST.JSBinOp } +BitAnd : '&' { AST.JSBinOpBitAnd (mkJSAnnot $1) } + +BitXor :: { AST.JSBinOp } +BitXor : '^' { AST.JSBinOpBitXor (mkJSAnnot $1)} + +Hook :: { AST.JSAnnot } +Hook : '?' { mkJSAnnot $1 } + +SimpleAssign :: { AST.JSAnnot } +SimpleAssign : '=' { mkJSAnnot $1 } + +OpAssign :: { AST.JSAssignOp } +OpAssign : '*=' { AST.JSTimesAssign (mkJSAnnot $1) } + | '/=' { AST.JSDivideAssign (mkJSAnnot $1) } + | '%=' { AST.JSModAssign (mkJSAnnot $1) } + | '+=' { AST.JSPlusAssign (mkJSAnnot $1) } + | '-=' { AST.JSMinusAssign (mkJSAnnot $1) } + | '<<=' { AST.JSLshAssign (mkJSAnnot $1) } + | '>>=' { AST.JSRshAssign (mkJSAnnot $1) } + | '>>>=' { AST.JSUrshAssign (mkJSAnnot $1) } + | '&=' { AST.JSBwAndAssign (mkJSAnnot $1) } + | '^=' { 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} + | '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" } + | '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 } + +Let :: { AST.JSAnnot } +Let : 'let' { mkJSAnnot $1 } + +Const :: { AST.JSAnnot } +Const : 'const' { mkJSAnnot $1 } + +Import :: { AST.JSAnnot } +Import : 'import' { mkJSAnnot $1 } + +From :: { AST.JSAnnot } +From : 'from' { mkJSAnnot $1 } + +Export :: { AST.JSAnnot } +Export : 'export' { mkJSAnnot $1 } + +If :: { AST.JSAnnot } +If : 'if' { mkJSAnnot $1 } + +Else :: { AST.JSAnnot } +Else : 'else' { mkJSAnnot $1 } + +Do :: { AST.JSAnnot } +Do : 'do' { mkJSAnnot $1 } + +While :: { AST.JSAnnot } +While : 'while' { mkJSAnnot $1 } + +For :: { AST.JSAnnot } +For : 'for' { mkJSAnnot $1 } + +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 } + +Return :: { AST.JSAnnot } +Return : 'return' { mkJSAnnot $1 } + +With :: { AST.JSAnnot } +With : 'with' { mkJSAnnot $1 } + +Switch :: { AST.JSAnnot } +Switch : 'switch' { mkJSAnnot $1 } + +Case :: { AST.JSAnnot } +Case : 'case' { mkJSAnnot $1 } + +Default :: { AST.JSAnnot } +Default : 'default' { mkJSAnnot $1 } + +Throw :: { AST.JSAnnot } +Throw : 'throw' { mkJSAnnot $1 {- 'Throw' -} } + +Try :: { AST.JSAnnot } +Try : 'try' { mkJSAnnot $1 } + +CatchL :: { AST.JSAnnot } +CatchL : 'catch' { mkJSAnnot $1 } + +FinallyL :: { AST.JSAnnot } +FinallyL : 'finally' { mkJSAnnot $1 } + +Function :: { AST.JSAnnot } +Function : 'function' { mkJSAnnot $1 {- 'Function' -} } + +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' -} } + +-- Literal :: See 7.8 +-- NullLiteral +-- BooleanLiteral +-- NumericLiteral +-- StringLiteral +Literal :: { AST.JSExpression } +Literal : NullLiteral { $1 } + | BooleanLiteral { $1 } + | NumericLiteral { $1 } + | StringLiteral { $1 } + | RegularExpressionLiteral { $1 } + +NullLiteral :: { AST.JSExpression } +NullLiteral : 'null' { AST.JSLiteral (mkJSAnnot $1) "null" } + +BooleanLiteral :: { AST.JSExpression } +BooleanLiteral : 'true' { AST.JSLiteral (mkJSAnnot $1) "true" } + | 'false' { AST.JSLiteral (mkJSAnnot $1) "false" } + +-- ::= DecimalLiteral +-- | HexIntegerLiteral +-- | OctalLiteral +NumericLiteral :: { AST.JSExpression } +NumericLiteral : 'decimal' { AST.JSDecimal (mkJSAnnot $1) (tokenLiteral $1) } + | 'hexinteger' { AST.JSHexInteger (mkJSAnnot $1) (tokenLiteral $1) } + | 'octal' { AST.JSOctal (mkJSAnnot $1) (tokenLiteral $1) } + +StringLiteral :: { AST.JSExpression } +StringLiteral : 'string' { AST.JSStringLiteral (mkJSAnnot $1) (tokenLiteral $1) } + +-- ::= RegExp +RegularExpressionLiteral :: { AST.JSExpression } +RegularExpressionLiteral : 'regex' { AST.JSRegEx (mkJSAnnot $1) (tokenLiteral $1) } + +-- PrimaryExpression : See 11.1 +-- this +-- Identifier +-- Literal +-- ArrayLiteral +-- ObjectLiteral +-- ( Expression ) +PrimaryExpression :: { AST.JSExpression } +PrimaryExpression : 'this' { AST.JSLiteral (mkJSAnnot $1) "this" } + | Identifier { $1 {- 'PrimaryExpression1' -} } + | Literal { $1 {- 'PrimaryExpression2' -} } + | ArrayLiteral { $1 {- 'PrimaryExpression3' -} } + | ObjectLiteral { $1 {- 'PrimaryExpression4' -} } + | 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 +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" } + +-- 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 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 ] +-- [ ElementList , Elisionopt ] +ArrayLiteral :: { AST.JSExpression } +ArrayLiteral : LSquare RSquare { AST.JSArrayLiteral $1 [] $2 {- 'ArrayLiteral11' -} } + | LSquare Elision RSquare { AST.JSArrayLiteral $1 $2 $3 {- 'ArrayLiteral12' -} } + | LSquare ElementList RSquare { AST.JSArrayLiteral $1 $2 $3 {- 'ArrayLiteral13' -} } + | LSquare ElementList Elision RSquare { AST.JSArrayLiteral $1 ($2 ++ $3) $4 {- 'ArrayLiteral14' -} } + + +-- ElementList : See 11.1.4 +-- Elisionopt AssignmentExpression +-- ElementList , Elisionopt AssignmentExpression +ElementList :: { [AST.JSArrayElement] } +ElementList : Elision AssignmentExpression { $1 ++ [AST.JSArrayElement $2] {- 'ElementList1' -} } + | AssignmentExpression { [AST.JSArrayElement $1] {- 'ElementList2' -} } + | ElementList Elision AssignmentExpression { (($1)++($2 ++ [AST.JSArrayElement $3])) {- 'ElementList3' -} } + + +-- Elision : See 11.1.4 +-- , +-- Elision , +Elision :: { [AST.JSArrayElement] } +Elision : Comma { [AST.JSArrayComma $1] {- 'Elision1' -} } + | Comma Elision { (AST.JSArrayComma $1):$2 {- 'Elision2' -} } + +-- ObjectLiteral : See 11.1.5 +-- { } +-- { PropertyNameAndValueList } +-- { PropertyNameAndValueList , } +ObjectLiteral :: { AST.JSExpression } +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' -} } + +-- ::= ':' +-- | ',' ':' + +-- Seems we can have function declarations in the value part too +-- PropertyNameAndValueList : See 11.1.5 +-- PropertyAssignment +-- PropertyNameAndValueList , PropertyAssignment +PropertyNameandValueList :: { AST.JSCommaList AST.JSObjectProperty } +PropertyNameandValueList : PropertyAssignment { AST.JSLOne $1 {- 'PropertyNameandValueList1' -} } + | PropertyNameandValueList Comma PropertyAssignment { AST.JSLCons $1 $2 $3 {- 'PropertyNameandValueList2' -} } + +-- PropertyAssignment : See 11.1.5 +-- PropertyName : AssignmentExpression +-- get PropertyName() { FunctionBody } +-- set PropertyName( PropertySetParameterList ) { FunctionBody } +PropertyAssignment :: { AST.JSObjectProperty } +PropertyAssignment : PropertyName Colon AssignmentExpression { AST.JSPropertyNameandValue $1 $2 [$3] } + | 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 +-- NumericLiteral +PropertyName :: { AST.JSPropertyName } +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 : AssignmentExpression { $1 {- 'PropertySetParameterList' -} } + +-- MemberExpression : See 11.2 +-- PrimaryExpression +-- FunctionExpression +-- MemberExpression [ Expression ] +-- MemberExpression . IdentifierName +-- new MemberExpression Arguments +MemberExpression :: { AST.JSExpression } +MemberExpression : PrimaryExpression { $1 {- 'MemberExpression1' -} } + | 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 +-- MemberExpression +-- new NewExpression +NewExpression :: { AST.JSExpression } +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 +-- CallExpression [ Expression ] +-- CallExpression . IdentifierName +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 +-- () +-- ( ArgumentList ) +Arguments :: { JSArguments } +Arguments : LParen RParen { JSArguments $1 AST.JSLNil $2 {- 'Arguments1' -} } + | LParen ArgumentList RParen { JSArguments $1 $2 $3 {- 'Arguments2' -} } + +-- ArgumentList : See 11.2 +-- AssignmentExpression +-- ArgumentList , AssignmentExpression +ArgumentList :: { AST.JSCommaList AST.JSExpression } +ArgumentList : AssignmentExpression { AST.JSLOne $1 {- 'ArgumentList1' -} } + | ArgumentList Comma AssignmentExpression { AST.JSLCons $1 $2 $3 {- 'ArgumentList2' -} } + +-- LeftHandSideExpression : See 11.2 +-- NewExpression +-- CallExpression +LeftHandSideExpression :: { AST.JSExpression } +LeftHandSideExpression : NewExpression { $1 {- 'LeftHandSideExpression1' -} } + | CallExpression { $1 {- 'LeftHandSideExpression12' -} } + | AwaitExpression { $1 {- 'LeftHandSideExpression13' -} } + +-- PostfixExpression : See 11.3 +-- LeftHandSideExpression +-- [no LineTerminator here] +-- LeftHandSideExpression ++ +-- [no LineTerminator here] +-- LeftHandSideExpression -- +PostfixExpression :: { AST.JSExpression } +PostfixExpression : LeftHandSideExpression { $1 {- 'PostfixExpression' -} } + | PostfixExpression Increment { AST.JSExpressionPostfix $1 $2 } + | PostfixExpression Decrement { AST.JSExpressionPostfix $1 $2 } + +-- UnaryExpression : See 11.4 +-- PostfixExpression +-- delete UnaryExpression +-- void UnaryExpression +-- typeof UnaryExpression +-- ++ UnaryExpression +-- -- UnaryExpression +-- + UnaryExpression +-- - UnaryExpression +-- ~ UnaryExpression +-- ! UnaryExpression +UnaryExpression :: { AST.JSExpression } +UnaryExpression : PostfixExpression { $1 {- 'UnaryExpression' -} } + | Delete UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Void UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Typeof UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Increment UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Decrement UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Plus UnaryExpression { AST.JSUnaryExpression (mkUnary $1) $2 } + | Minus UnaryExpression { AST.JSUnaryExpression (mkUnary $1) $2 } + | Tilde UnaryExpression { AST.JSUnaryExpression $1 $2 } + | Not UnaryExpression { AST.JSUnaryExpression $1 $2 } + +-- MultiplicativeExpression : See 11.5 +-- UnaryExpression +-- MultiplicativeExpression * UnaryExpression +-- MultiplicativeExpression / UnaryExpression +-- MultiplicativeExpression % UnaryExpression +MultiplicativeExpression :: { AST.JSExpression } +MultiplicativeExpression : UnaryExpression { $1 {- 'MultiplicativeExpression' -} } + | MultiplicativeExpression Mul UnaryExpression { AST.JSExpressionBinary {- '*' -} $1 $2 $3 } + | MultiplicativeExpression Div UnaryExpression { AST.JSExpressionBinary {- '/' -} $1 $2 $3 } + | MultiplicativeExpression Mod UnaryExpression { AST.JSExpressionBinary {- '%' -} $1 $2 $3 } + +-- AdditiveExpression : See 11.6 +-- MultiplicativeExpression +-- AdditiveExpression + MultiplicativeExpression +-- AdditiveExpression - MultiplicativeExpression +AdditiveExpression :: { AST.JSExpression } +AdditiveExpression : AdditiveExpression Plus MultiplicativeExpression { AST.JSExpressionBinary {- '+' -} $1 $2 $3 } + | AdditiveExpression Minus MultiplicativeExpression { AST.JSExpressionBinary {- '-' -} $1 $2 $3 } + | MultiplicativeExpression { $1 {- 'AdditiveExpression' -} } + +-- ShiftExpression : See 11.7 +-- AdditiveExpression +-- ShiftExpression << AdditiveExpression +-- ShiftExpression >> AdditiveExpression +-- ShiftExpression >>> AdditiveExpression +ShiftExpression :: { AST.JSExpression } +ShiftExpression : ShiftExpression Lsh AdditiveExpression { AST.JSExpressionBinary {- '<<' -} $1 $2 $3 } + | ShiftExpression Rsh AdditiveExpression { AST.JSExpressionBinary {- '>>' -} $1 $2 $3 } + | ShiftExpression Ursh AdditiveExpression { AST.JSExpressionBinary {- '>>>' -} $1 $2 $3 } + | AdditiveExpression { $1 {- 'ShiftExpression' -} } + +-- RelationalExpression : See 11.8 +-- ShiftExpression +-- RelationalExpression < ShiftExpression +-- RelationalExpression > ShiftExpression +-- RelationalExpression <= ShiftExpression +-- RelationalExpression >= ShiftExpression +-- RelationalExpression instanceof ShiftExpression +-- RelationalExpression in ShiftExpression +RelationalExpression :: { AST.JSExpression } +RelationalExpression : ShiftExpression { $1 {- 'RelationalExpression' -} } + | RelationalExpression Lt ShiftExpression { AST.JSExpressionBinary {- '<' -} $1 $2 $3 } + | RelationalExpression Gt ShiftExpression { AST.JSExpressionBinary {- '>' -} $1 $2 $3 } + | RelationalExpression Le ShiftExpression { AST.JSExpressionBinary {- '<=' -} $1 $2 $3 } + | RelationalExpression Ge ShiftExpression { AST.JSExpressionBinary {- '>=' -} $1 $2 $3 } + | RelationalExpression Instanceof ShiftExpression { AST.JSExpressionBinary {- ' instanceof' -} $1 $2 $3 } + | RelationalExpression In ShiftExpression { AST.JSExpressionBinary {- ' in ' -} $1 $2 $3 } + +-- RelationalExpressionNoIn : See 11.8 +-- ShiftExpression +-- RelationalExpressionNoIn < ShiftExpression +-- RelationalExpressionNoIn > ShiftExpression +-- RelationalExpressionNoIn <= ShiftExpression +-- RelationalExpressionNoIn >= ShiftExpression +-- RelationalExpressionNoIn instanceof ShiftExpression +RelationalExpressionNoIn :: { AST.JSExpression } +RelationalExpressionNoIn : ShiftExpression { $1 {- 'RelationalExpressionNoIn' -} } + | RelationalExpressionNoIn Lt ShiftExpression { AST.JSExpressionBinary {- '<' -} $1 $2 $3 } + | RelationalExpressionNoIn Gt ShiftExpression { AST.JSExpressionBinary {- '>' -} $1 $2 $3 } + | RelationalExpressionNoIn Le ShiftExpression { AST.JSExpressionBinary {- '<=' -} $1 $2 $3 } + | RelationalExpressionNoIn Ge ShiftExpression { AST.JSExpressionBinary {- '>=' -} $1 $2 $3 } + | RelationalExpressionNoIn Instanceof ShiftExpression { AST.JSExpressionBinary {- ' instanceof ' -} $1 $2 $3 } + +-- EqualityExpression : See 11.9 +-- RelationalExpression +-- EqualityExpression == RelationalExpression +-- EqualityExpression != RelationalExpression +-- EqualityExpression === RelationalExpression +-- EqualityExpression !== RelationalExpression +EqualityExpression :: { AST.JSExpression } +EqualityExpression : RelationalExpression { $1 {- 'EqualityExpression' -} } + | EqualityExpression Equal RelationalExpression { AST.JSExpressionBinary {- '==' -} $1 $2 $3 } + | EqualityExpression Ne RelationalExpression { AST.JSExpressionBinary {- '!=' -} $1 $2 $3 } + | EqualityExpression StrictEq RelationalExpression { AST.JSExpressionBinary {- '===' -} $1 $2 $3 } + | EqualityExpression StrictNe RelationalExpression { AST.JSExpressionBinary {- '!==' -} $1 $2 $3 } + +-- EqualityExpressionNoIn : See 11.9 +-- RelationalExpressionNoIn +-- EqualityExpressionNoIn == RelationalExpressionNoIn +-- EqualityExpressionNoIn != RelationalExpressionNoIn +-- EqualityExpressionNoIn === RelationalExpressionNoIn +-- EqualityExpressionNoIn !== RelationalExpressionNoIn +EqualityExpressionNoIn :: { AST.JSExpression } +EqualityExpressionNoIn : RelationalExpressionNoIn { $1 {- 'EqualityExpressionNoIn' -} } + | EqualityExpressionNoIn Equal RelationalExpression { AST.JSExpressionBinary {- '==' -} $1 $2 $3 } + | EqualityExpressionNoIn Ne RelationalExpression { AST.JSExpressionBinary {- '!=' -} $1 $2 $3 } + | EqualityExpressionNoIn StrictEq RelationalExpression { AST.JSExpressionBinary {- '===' -} $1 $2 $3 } + | EqualityExpressionNoIn StrictNe RelationalExpression { AST.JSExpressionBinary {- '!==' -} $1 $2 $3 } + +-- BitwiseANDExpression : See 11.10 +-- EqualityExpression +-- BitwiseANDExpression & EqualityExpression +BitwiseAndExpression :: { AST.JSExpression } +BitwiseAndExpression : EqualityExpression { $1 {- 'BitwiseAndExpression' -} } + | BitwiseAndExpression BitAnd EqualityExpression { AST.JSExpressionBinary {- '&' -} $1 $2 $3 } + +-- BitwiseANDExpressionNoIn : See 11.10 +-- EqualityExpressionNoIn +-- BitwiseANDExpressionNoIn & EqualityExpressionNoIn +BitwiseAndExpressionNoIn :: { AST.JSExpression } +BitwiseAndExpressionNoIn : EqualityExpressionNoIn { $1 {- 'BitwiseAndExpression' -} } + | BitwiseAndExpressionNoIn BitAnd EqualityExpressionNoIn { AST.JSExpressionBinary {- '&' -} $1 $2 $3 } + +-- BitwiseXORExpression : See 11.10 +-- BitwiseANDExpression +-- BitwiseXORExpression ^ BitwiseANDExpression +BitwiseXOrExpression :: { AST.JSExpression } +BitwiseXOrExpression : BitwiseAndExpression { $1 {- 'BitwiseXOrExpression' -} } + | BitwiseXOrExpression BitXor BitwiseAndExpression { AST.JSExpressionBinary {- '^' -} $1 $2 $3 } + +-- BitwiseXORExpressionNoIn : See 11.10 +-- BitwiseANDExpressionNoIn +-- BitwiseXORExpressionNoIn ^ BitwiseANDExpressionNoIn +BitwiseXOrExpressionNoIn :: { AST.JSExpression } +BitwiseXOrExpressionNoIn : BitwiseAndExpressionNoIn { $1 {- 'BitwiseXOrExpression' -} } + | BitwiseXOrExpressionNoIn BitXor BitwiseAndExpressionNoIn { AST.JSExpressionBinary {- '^' -} $1 $2 $3 } + +-- BitwiseORExpression : See 11.10 +-- BitwiseXORExpression +-- BitwiseORExpression | BitwiseXORExpression +BitwiseOrExpression :: { AST.JSExpression } +BitwiseOrExpression : BitwiseXOrExpression { $1 {- 'BitwiseOrExpression' -} } + | BitwiseOrExpression BitOr BitwiseXOrExpression { AST.JSExpressionBinary {- '|' -} $1 $2 $3 } + +-- BitwiseORExpressionNoIn : See 11.10 +-- BitwiseXORExpressionNoIn +-- BitwiseORExpressionNoIn | BitwiseXORExpressionNoIn +BitwiseOrExpressionNoIn :: { AST.JSExpression } +BitwiseOrExpressionNoIn : BitwiseXOrExpressionNoIn { $1 {- 'BitwiseOrExpression' -} } + | BitwiseOrExpressionNoIn BitOr BitwiseXOrExpressionNoIn { AST.JSExpressionBinary {- '|' -} $1 $2 $3 } + +-- LogicalANDExpression : See 11.11 +-- BitwiseORExpression +-- LogicalANDExpression && BitwiseORExpression +LogicalAndExpression :: { AST.JSExpression } +LogicalAndExpression : BitwiseOrExpression { $1 {- 'LogicalAndExpression' -} } + | LogicalAndExpression And BitwiseOrExpression { AST.JSExpressionBinary {- '&&' -} $1 $2 $3 } + +-- LogicalANDExpressionNoIn : See 11.11 +-- BitwiseORExpressionNoIn +-- LogicalANDExpressionNoIn && BitwiseORExpressionNoIn +LogicalAndExpressionNoIn :: { AST.JSExpression } +LogicalAndExpressionNoIn : BitwiseOrExpressionNoIn { $1 {- 'LogicalAndExpression' -} } + | LogicalAndExpressionNoIn And BitwiseOrExpressionNoIn { AST.JSExpressionBinary {- '&&' -} $1 $2 $3 } + +-- LogicalORExpression : See 11.11 +-- LogicalANDExpression +-- LogicalORExpression || LogicalANDExpression +LogicalOrExpression :: { AST.JSExpression } +LogicalOrExpression : LogicalAndExpression { $1 {- 'LogicalOrExpression' -} } + | LogicalOrExpression Or LogicalAndExpression { AST.JSExpressionBinary {- '||' -} $1 $2 $3 } + +-- LogicalORExpressionNoIn : See 11.11 +-- LogicalANDExpressionNoIn +-- LogicalORExpressionNoIn || LogicalANDExpressionNoIn +LogicalOrExpressionNoIn :: { AST.JSExpression } +LogicalOrExpressionNoIn : LogicalAndExpressionNoIn { $1 {- 'LogicalOrExpression' -} } + | LogicalOrExpressionNoIn Or LogicalAndExpressionNoIn { AST.JSExpressionBinary {- '||' -} $1 $2 $3 } + +-- ConditionalExpression : See 11.12 +-- LogicalORExpression +-- LogicalORExpression ? AssignmentExpression : AssignmentExpression +ConditionalExpression :: { AST.JSExpression } +ConditionalExpression : LogicalOrExpression { $1 {- 'ConditionalExpression1' -} } + | LogicalOrExpression Hook AssignmentExpression Colon AssignmentExpression + { AST.JSExpressionTernary $1 $2 $3 $4 $5 {- 'ConditionalExpression2' -} } + +-- ConditionalExpressionNoIn : See 11.12 +-- LogicalORExpressionNoIn +-- LogicalORExpressionNoIn ? AssignmentExpressionNoIn : AssignmentExpressionNoIn +ConditionalExpressionNoIn :: { AST.JSExpression } +ConditionalExpressionNoIn : LogicalOrExpressionNoIn { $1 {- 'ConditionalExpressionNoIn1' -} } + | LogicalOrExpressionNoIn Hook AssignmentExpressionNoIn Colon AssignmentExpressionNoIn + { AST.JSExpressionTernary $1 $2 $3 $4 $5 {- 'ConditionalExpressionNoIn2' -} } + +-- AssignmentExpression : See 11.13 +-- ConditionalExpression +-- 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' -} } + +-- AssignmentOperator : one of See 11.13 +-- '=' | '*=' | '/=' | '%=' | '+=' | '-=' | '<<=' | '>>=' | '>>>=' | '&=' | '^=' | '|=' +AssignmentOperator :: { AST.JSAssignOp } +AssignmentOperator : OpAssign { $1 } + | SimpleAssign { AST.JSAssign $1 {- 'SimpleAssign' -} } + +-- Expression : See 11.14 +-- AssignmentExpression +-- Expression , AssignmentExpression +Expression :: { AST.JSExpression } +Expression : AssignmentExpression { $1 {- 'Expression' -} } + | Expression Comma AssignmentExpression { AST.JSCommaExpression $1 $2 $3 {- 'Expression2' -} } + +-- ExpressionNoIn : See 11.14 +-- AssignmentExpressionNoIn +-- ExpressionNoIn , AssignmentExpressionNoIn +ExpressionNoIn :: { AST.JSExpression } +ExpressionNoIn : AssignmentExpressionNoIn { $1 {- 'ExpressionNoIn' -} } + | ExpressionNoIn Comma AssignmentExpressionNoIn { AST.JSCommaExpression $1 $2 $3 {- 'ExpressionNoIn2' -} } + +-- TODO: still required? +ExpressionOpt :: { AST.JSCommaList AST.JSExpression } +ExpressionOpt : Expression { AST.JSLOne $1 {- 'ExpressionOpt1' -} } + | { AST.JSLNil {- 'ExpressionOpt2' -} } + +ExpressionNoInOpt :: { AST.JSCommaList AST.JSExpression } +ExpressionNoInOpt : ExpressionNoIn { AST.JSLOne $1 {- 'ExpressionOpt1' -} } + | { AST.JSLNil {- 'ExpressionOpt2' -} } + + +-- Statement : See clause 12 +-- Block +-- VariableStatement +-- EmptyStatement +-- ExpressionStatement +-- IfStatement +-- IterationStatement +-- ContinueStatement +-- BreakStatement +-- ReturnStatement +-- WithStatement +-- LabelledStatement +-- SwitchStatement +-- ThrowStatement +-- TryStatement +-- DebuggerStatement +Statement :: { AST.JSStatement } +Statement : StatementNoEmpty { $1 {- 'Statement1' -} } + | EmptyStatement { $1 {- 'Statement2' -} } + +StatementNoEmpty :: { AST.JSStatement } +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' -} } + + +-- Block : See 12.1 +-- { StatementListopt } +Block :: { AST.JSBlock } +Block : LBrace RBrace { AST.JSBlock $1 [] $2 {- 'Block1' -} } + | LBrace StatementList RBrace { AST.JSBlock $1 $2 $3 {- 'Block2' -} } + +-- StatementList : See 12.1 +-- Statement +-- StatementList Statement +StatementList :: { [AST.JSStatement] } +StatementList : Statement { [$1] {- 'StatementList1' -} } + | StatementList Statement { ($1++[$2]) {- 'StatementList2' -} } + +-- VariableStatement : See 12.2 +-- var VariableDeclarationList ; +VariableStatement :: { AST.JSStatement } +VariableStatement : Var VariableDeclarationList MaybeSemi { AST.JSVariable $1 $2 $3 {- 'VariableStatement1' -} } + | Let VariableDeclarationList MaybeSemi { AST.JSLet $1 $2 $3 {- 'VariableStatement2' -} } + | Const VariableDeclarationList MaybeSemi { AST.JSConstant $1 $2 $3 {- 'VariableStatement3' -} } + +-- VariableDeclarationList : See 12.2 +-- VariableDeclaration +-- VariableDeclarationList , VariableDeclaration +VariableDeclarationList :: { AST.JSCommaList AST.JSExpression } +VariableDeclarationList : VariableDeclaration { AST.JSLOne $1 {- 'VariableDeclarationList1' -} } + | VariableDeclarationList Comma VariableDeclaration { AST.JSLCons $1 $2 $3 {- 'VariableDeclarationList2' -} } + +-- VariableDeclarationListNoIn : See 12.2 +-- VariableDeclarationNoIn +-- VariableDeclarationListNoIn , VariableDeclarationNoIn +VariableDeclarationListNoIn :: { AST.JSCommaList AST.JSExpression } +VariableDeclarationListNoIn : VariableDeclarationNoIn { AST.JSLOne $1 {- 'VariableDeclarationListNoIn1' -} } + | VariableDeclarationListNoIn Comma VariableDeclarationNoIn { AST.JSLCons $1 $2 $3 {- 'VariableDeclarationListNoIn2' -} } + +-- VariableDeclaration : See 12.2 +-- Identifier Initialiseropt +VariableDeclaration :: { AST.JSExpression } +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 : PrimaryExpression SimpleAssign AssignmentExpression { AST.JSVarInitExpression $1 (AST.JSVarInit $2 $3) {- 'JSVarInitExpressionInit2' -} } + | Identifier { AST.JSVarInitExpression $1 AST.JSVarInitNone {- 'JSVarInitExpression2' -} } + +-- EmptyStatement : See 12.3 +-- ; +EmptyStatement :: { AST.JSStatement } +EmptyStatement : Semi { AST.JSEmptyStatement $1 {- 'EmptyStatement' -} } + +-- ExpressionStatement : See 12.4 +-- [lookahead not in {{, function}] Expression ; +-- TODO: Sort out lookahead issue. Maybe by just putting production lower to set reduce/reduce conflict +-- According to http://sideshowbarker.github.com/es5-spec/#x12.4, the ambiguity is with +-- Block or FunctionDeclaration +ExpressionStatement :: { AST.JSStatement } +ExpressionStatement : Expression MaybeSemi { expressionToStatement $1 $2 {- 'ExpressionStatement' -} } + + +-- IfStatement : See 12.5 +-- if ( Expression ) Statement else Statement +-- if ( Expression ) Statement +IfStatement :: { AST.JSStatement } -- +++XXXX++ +IfStatement : If LParen Expression RParen EmptyStatement + { AST.JSIf $1 $2 $3 $4 $5 {- 'IfStatement1' -} } + | If LParen Expression RParen StatementNoEmpty Else Statement + { AST.JSIfElse $1 $2 $3 $4 $5 $6 $7 {- 'IfStatement3' -} } + | If LParen Expression RParen StatementNoEmpty + { AST.JSIf $1 $2 $3 $4 $5 {- 'IfStatement3' -} } + | If LParen Expression RParen EmptyStatement Else Statement + { AST.JSIfElse $1 $2 $3 $4 $5 $6 $7 {- 'IfStatement4' -} } + +-- IterationStatement : See 12.6 +-- do Statement while ( Expression ); +-- while ( Expression ) Statement +-- for (ExpressionNoInopt; Expressionopt ; Expressionopt ) Statement +-- for ( var VariableDeclarationListNoIn; Expressionopt ; Expressionopt ) Statement +-- for ( LeftHandSideExpression in Expression ) Statement +-- for ( var VariableDeclarationNoIn in Expression ) Statement +IterationStatement :: { AST.JSStatement } +IterationStatement : Do StatementNoEmpty While LParen Expression RParen MaybeSemi + { AST.JSDoWhile $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement1' -} } + | While LParen Expression RParen Statement + { AST.JSWhile $1 $2 $3 $4 $5 {- 'IterationStatement2' -} } + | For LParen ExpressionNoInOpt Semi ExpressionOpt Semi ExpressionOpt RParen Statement + { AST.JSFor $1 $2 $3 $4 $5 $6 $7 $8 $9 {- 'IterationStatement3' -} } + | For LParen Var VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement + { AST.JSForVar $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement4' -} } + | For LParen LeftHandSideExpression In Expression RParen Statement + { AST.JSForIn $1 $2 $3 $4 $5 $6 $7 {- 'IterationStatement 5' -} } + | For LParen Var VariableDeclarationNoIn In Expression RParen Statement + { AST.JSForVarIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement6' -} } + | For LParen Let VariableDeclarationListNoIn Semi ExpressionOpt Semi ExpressionOpt RParen Statement + { AST.JSForLet $1 $2 $3 $4 $5 $6 $7 $8 $9 $10 {- 'IterationStatement 7' -} } + | For LParen Let VariableDeclarationNoIn In Expression RParen Statement + { AST.JSForLetIn $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 8' -} } + | For LParen Let VariableDeclarationNoIn Of Expression RParen Statement + { AST.JSForLetOf $1 $2 $3 $4 $5 $6 $7 $8 {- 'IterationStatement 9' -} } + | For LParen LeftHandSideExpression Of Expression RParen Statement + { 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 ; +ContinueStatement :: { AST.JSStatement } +ContinueStatement : Continue AutoSemi { AST.JSContinue $1 AST.JSIdentNone $2 {- 'ContinueStatement1' -} } + | Continue Identifier MaybeSemi { AST.JSContinue $1 (identName $2) $3 {- 'ContinueStatement2' -} } + +-- BreakStatement : See 12.8 +-- break [no LineTerminator here] Identifieropt ; +BreakStatement :: { AST.JSStatement } +BreakStatement : Break AutoSemi { AST.JSBreak $1 AST.JSIdentNone $2 {- 'BreakStatement1' -} } + | Break Identifier MaybeSemi { AST.JSBreak $1 (identName $2) $3 {- 'BreakStatement2' -} } + +-- ReturnStatement : See 12.9 +-- return [no LineTerminator here] Expressionopt ; +ReturnStatement :: { AST.JSStatement } +ReturnStatement : Return AutoSemi { AST.JSReturn $1 Nothing $2 } + | Return Expression MaybeSemi { AST.JSReturn $1 (Just $2) $3 } + +-- WithStatement : See 12.10 +-- with ( Expression ) Statement +WithStatement :: { AST.JSStatement } +WithStatement : With LParen Expression RParen Statement MaybeSemi { AST.JSWith $1 $2 $3 $4 $5 $6 } + +-- SwitchStatement : See 12.11 +-- switch ( Expression ) CaseBlock +SwitchStatement :: { AST.JSStatement } +SwitchStatement : Switch LParen Expression RParen LBrace CaseBlock RBrace MaybeSemi { AST.JSSwitch $1 $2 $3 $4 $5 $6 $7 $8 } + +-- CaseBlock : See 12.11 +-- { CaseClausesopt } +-- { CaseClausesopt DefaultClause CaseClausesopt } +CaseBlock :: { [AST.JSSwitchParts] } +CaseBlock : CaseClausesOpt { $1 {- 'CaseBlock1' -} } + | CaseClausesOpt DefaultClause CaseClausesOpt { $1++[$2]++$3 {- 'CaseBlock2' -} } + +-- CaseClauses : See 12.11 +-- CaseClause +-- CaseClauses CaseClause +CaseClausesOpt :: { [AST.JSSwitchParts] } +CaseClausesOpt : CaseClause { [$1] {- 'CaseClausesOpt1' -} } + | CaseClausesOpt CaseClause { ($1++[$2]) {- 'CaseClausesOpt2' -} } + | { [] {- 'CaseClausesOpt3' -} } + +-- CaseClause : See 12.11 +-- case Expression : StatementListopt +CaseClause :: { AST.JSSwitchParts } +CaseClause : Case Expression Colon StatementList { AST.JSCase $1 $2 $3 $4 {- 'CaseClause1' -} } + | Case Expression Colon { AST.JSCase $1 $2 $3 [] {- 'CaseClause2' -} } + +-- DefaultClause : See 12.11 +-- default : StatementListopt +DefaultClause :: { AST.JSSwitchParts } +DefaultClause : Default Colon { AST.JSDefault $1 $2 [] {- 'DefaultClause1' -} } + | Default Colon StatementList { AST.JSDefault $1 $2 $3 {- 'DefaultClause2' -} } + +-- LabelledStatement : See 12.12 +-- Identifier : Statement +LabelledStatement :: { AST.JSStatement } +LabelledStatement : Identifier Colon Statement { AST.JSLabelled (identName $1) $2 $3 {- 'LabelledStatement' -} } + +-- ThrowStatement : See 12.13 +-- throw [no LineTerminator here] Expression ; +ThrowStatement :: { AST.JSStatement } +ThrowStatement : Throw Expression MaybeSemi { AST.JSThrow $1 $2 $3 {- 'ThrowStatement' -} } + +-- Note: worked in updated syntax as per https://developer.mozilla.org/en/JavaScript/Reference/Statements/try...catch +-- i.e., 0 or more catches, then an optional finally +-- TryStatement : See 12.14 +-- try Block Catch +-- try Block Finally +-- try Block Catch Finally +TryStatement :: { AST.JSStatement } +TryStatement : Try Block Catches { AST.JSTry $1 $2 $3 AST.JSNoFinally {- 'TryStatement1' -} } + | Try Block Finally { AST.JSTry $1 $2 [] $3 {- 'TryStatement2' -} } + | Try Block Catches Finally { AST.JSTry $1 $2 $3 $4 {- 'TryStatement3' -} } + +Catches :: { [AST.JSTryCatch] } +Catches : Catch { [$1] {- 'Catches1' -} } + | Catches Catch { ($1++[$2]) {- 'Catches2' -} } + +-- Note: worked in updated syntax as per https://developer.mozilla.org/en/JavaScript/Reference/Statements/try...catch +-- ::= 'catch' '(' Identifier ')' +-- becomes +-- ::= 'catch' '(' Identifier ')' +-- | 'catch' '(' Identifier 'if' ConditionalExpression ')' +Catch :: { AST.JSTryCatch } +Catch : CatchL LParen Identifier RParen Block { AST.JSCatch $1 $2 $3 $4 $5 {- 'Catch1' -} } + | CatchL LParen Identifier If ConditionalExpression RParen Block { AST.JSCatchIf $1 $2 $3 $4 $5 $6 $7 {- 'Catch2' -} } + +-- Finally : See 12.14 +-- finally Block +Finally :: { AST.JSTryFinally } +Finally : FinallyL Block { AST.JSFinally $1 $2 {- 'Finally' -} } + +-- DebuggerStatement : See 12.15 +-- debugger ; +DebuggerStatement :: { AST.JSStatement } +DebuggerStatement : 'debugger' MaybeSemi { AST.JSExpressionStatement (AST.JSLiteral (mkJSAnnot $1) "debugger") $2 {- 'DebuggerStatement' -} } + +-- FunctionDeclaration : See clause 13 +-- function Identifier ( FormalParameterListopt ) { FunctionBody } +FunctionDeclaration :: { AST.JSStatement } +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 } +FunctionExpression : ArrowFunctionExpression { $1 {- 'ArrowFunctionExpression' -} } + | LambdaExpression { $1 {- 'FunctionExpression1' -} } + | NamedFunctionExpression { $1 {- 'FunctionExpression2' -} } + +ArrowFunctionExpression :: { AST.JSExpression } +ArrowFunctionExpression : ArrowParameterList Arrow StatementOrBlock + { AST.JSArrowExpression $1 $2 $3 } + +ArrowParameterList :: { AST.JSArrowParameterList } +ArrowParameterList : PrimaryExpression {%^ toArrowParameterList $1 } + | LParen RParen + { AST.JSParenthesizedArrowParameterList $1 AST.JSLNil $2 } + +StatementOrBlock :: { AST.JSStatement } +StatementOrBlock : Block MaybeSemi { blockToStatement $1 $2 } + | Expression MaybeSemi { expressionToStatement $1 $2 } + +-- StatementListItem : +-- Statement +-- Declaration +StatementListItem :: { AST.JSStatement } +StatementListItem : Statement { $1 } + +NamedFunctionExpression :: { AST.JSExpression } +NamedFunctionExpression : Function Identifier LParen RParen FunctionBody + { AST.JSFunctionExpression $1 (identName $2) $3 AST.JSLNil $4 $5 {- 'NamedFunctionExpression1' -} } + | Function Identifier LParen FormalParameterList RParen FunctionBody + { AST.JSFunctionExpression $1 (identName $2) $3 $4 $5 $6 {- 'NamedFunctionExpression2' -} } + +LambdaExpression :: { AST.JSExpression } +LambdaExpression : Function LParen RParen FunctionBody + { AST.JSFunctionExpression $1 AST.JSIdentNone $2 AST.JSLNil $3 $4 {- 'LambdaExpression1' -} } + | 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' -} } + +-- FormalParameterList : See clause 13 +-- Identifier +-- FormalParameterList , Identifier +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 + +Program :: { AST.JSAST } +Program : StatementList Eof { AST.JSAstProgram $1 $2 {- 'Program1' -} } + | Eof { AST.JSAstProgram [] $1 {- 'Program2' -} } + +-- Module : See 15.2 +-- ModuleBody[opt] +-- +-- ModuleBody : +-- ModuleItemList +Module :: { AST.JSAST } +Module : ModuleItemList Eof { AST.JSAstModule $1 $2 {- 'Module1' -} } + | Eof { AST.JSAstModule [] $1 {- 'Module2' -} } + +-- ModuleItemList : +-- ModuleItem +-- ModuleItemList ModuleItem +ModuleItemList :: { [AST.JSModuleItem] } +ModuleItemList : ModuleItem { [$1] {- 'ModuleItemList1' -} } + | ModuleItemList ModuleItem { ($1++[$2]) {- 'ModuleItemList2' -} } + +-- ModuleItem : +-- ImportDeclaration +-- ExportDeclaration +-- StatementListItem +ModuleItem :: { AST.JSModuleItem } +ModuleItem : Import ImportDeclaration + { AST.JSModuleImportDeclaration $1 $2 {- 'ModuleItem1' -} } + | Export ExportDeclaration + { AST.JSModuleExportDeclaration $1 $2 {- 'ModuleItem1' -} } + | StatementListItem + { AST.JSModuleStatementListItem $1 {- 'ModuleItem2' -} } + +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 + { AST.JSImportClauseDefault (identName $1) } + | NameSpaceImport + { AST.JSImportClauseNameSpace $1 } + | NamedImports + { AST.JSImportClauseNamed $1 } + | IdentifierName ',' NameSpaceImport + { AST.JSImportClauseDefaultNameSpace (identName $1) (mkJSAnnot $2) $3 } + | IdentifierName ',' NamedImports + { AST.JSImportClauseDefaultNamed (identName $1) (mkJSAnnot $2) $3 } + +FromClause :: { AST.JSFromClause } +FromClause : From 'string' + { AST.JSFromClause $1 (mkJSAnnot $2) (tokenLiteral $2) } + +NameSpaceImport :: { AST.JSImportNameSpace } +NameSpaceImport : Mul As IdentifierName + { AST.JSImportNameSpace $1 $2 (identName $3) } + +NamedImports :: { AST.JSImportsNamed } +NamedImports : LBrace ImportsList RBrace + { AST.JSImportsNamed $1 $2 $3 } + +ImportsList :: { AST.JSCommaList AST.JSImportSpecifier } +ImportsList : ImportSpecifier + { AST.JSLOne $1 } + | ImportsList Comma ImportSpecifier + { AST.JSLCons $1 $2 $3 } + +ImportSpecifier :: { AST.JSImportSpecifier } +ImportSpecifier : IdentifierName + { AST.JSImportSpecifier (identName $1) } + | IdentifierName As IdentifierName + { AST.JSImportSpecifierAs (identName $1) $2 (identName $3) } + +-- ExportDeclaration : See 15.2.3 +-- [ ] export * FromClause ; +-- [x] export ExportClause FromClause ; +-- [x] export ExportClause ; +-- [x] export VariableStatement +-- [ ] export Declaration +-- [ ] Declaration : +-- [ ] HoistableDeclaration +-- [x] ClassDeclaration +-- [x] LexicalDeclaration +-- [ ] HoistableDeclaration : +-- [x] FunctionDeclaration +-- [x] GeneratorDeclaration +-- [ ] AsyncFunctionDeclaration +-- [ ] AsyncGeneratorDeclaration +-- [ ] export default HoistableDeclaration[Default] +-- [ ] export default ClassDeclaration[Default] +-- [ ] export default [lookahead ∉ { function, class }] AssignmentExpression[In] ; +ExportDeclaration :: { AST.JSExportDeclaration } +ExportDeclaration : ExportClause FromClause AutoSemi + { AST.JSExportFrom $1 $2 $3 {- 'ExportDeclaration1' -} } + | ExportClause AutoSemi + { AST.JSExportLocals $1 $2 {- 'ExportDeclaration2' -} } + | VariableStatement AutoSemi + { 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 : +-- { } +-- { ExportsList } +-- { ExportsList , } +ExportClause :: { AST.JSExportClause } +ExportClause : LBrace RBrace + { AST.JSExportClause $1 AST.JSLNil $2 {- 'ExportClause1' -} } + | LBrace ExportsList RBrace + { AST.JSExportClause $1 $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 } +LiteralMain : Literal Eof { AST.JSAstLiteral $1 $2 {- 'LiteralMain' -} } + +ExpressionMain :: { AST.JSAST } +ExpressionMain : Expression Eof { AST.JSAstExpression $1 $2 {- 'ExpressionMain' -} } + +StatementMain :: { AST.JSAST } +StatementMain : StatementNoEmpty Eof { AST.JSAstStatement $1 $2 {- 'StatementMain' -} } + +{ + +-- 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 + +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 + +mkJSMemberExpression :: AST.JSExpression -> JSArguments -> AST.JSExpression +mkJSMemberExpression e (JSArguments l arglist r) = AST.JSMemberExpression e l arglist r + +mkJSMemberNew :: AST.JSAnnot -> AST.JSExpression -> JSArguments -> AST.JSExpression +mkJSMemberNew a e (JSArguments l arglist r) = AST.JSMemberNew a e l arglist r + +parseError :: Token -> Alex a +parseError = alexError . show + +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 +-- version. +mkUnary :: AST.JSBinOp -> AST.JSUnaryOp +mkUnary (AST.JSBinOpMinus annot) = AST.JSUnaryOpMinus annot +mkUnary (AST.JSBinOpPlus annot) = AST.JSUnaryOpPlus annot + +mkUnary x = error $ "Invalid unary op : " ++ show x + +identName :: AST.JSExpression -> AST.JSIdent +identName (AST.JSIdentifier a s) = AST.JSIdentName a s +identName x = error $ "Cannot convert '" ++ show x ++ "' to a JSIdentName." + +propName :: AST.JSExpression -> AST.JSPropertyName +propName (AST.JSIdentifier a s) = AST.JSPropertyIdent a s +propName (AST.JSDecimal a s) = AST.JSPropertyNumber a s +propName (AST.JSHexInteger a s) = AST.JSPropertyNumber a s +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 + +} diff --git a/src/Language/JavaScript/Parser/Lexer.x b/src/Language/JavaScript/Parser/Lexer.x new file mode 100755 index 0000000..d28be52 --- /dev/null +++ b/src/Language/JavaScript/Parser/Lexer.x @@ -0,0 +1,692 @@ +{ +{-# LANGUAGE CPP #-} +{-# OPTIONS_GHC -funbox-strict-fields #-} + +#if __GLASGOW_HASKELL__ >= 800 +-- Alex generates code with these warnings so we'll just ignore them. +{-# OPTIONS_GHC -Wno-unused-matches #-} +{-# OPTIONS_GHC -Wno-unused-imports #-} +#endif + +module Language.JavaScript.Parser.Lexer + ( Token (..) + , Alex + , lexCont + , alexError + , runAlex + , alexTestTokeniser + , setInTemplate + ) where + +import Language.JavaScript.Parser.LexerUtils +import Language.JavaScript.Parser.ParserMonad +import Language.JavaScript.Parser.SrcLocation +import Language.JavaScript.Parser.Token +import qualified Data.Map as Map + +} + +-- %wrapper "basic" +-- %wrapper "monad" +%wrapper "monadUserState" +-- %wrapper "monad-bytestring" + +-- character sets +$lf = \n -- line feed +$cr = \r -- carriage return +$ht = \t -- horizontal tab +$sq = ' -- single quote +$dq = \" -- double quote +$digit = 0-9 -- digits +$oct_digit = [0-7] +$hex_digit = [0-9a-fA-F] +$alpha = [a-zA-Z] -- alphabetic characters +$non_zero_digit = 1-9 +$ident_letter = [a-zA-Z_] +@eol_pattern = $lf | $cr $lf | $cr $lf + +$ls = \x2028 +$ps = \x2029 +@LineTerminatorSequence = $lf | $cr | $ls | $ps | $cr $lf + + +$any_char = [\x00-\xff] +$any_unicode_char = [\x00-\x10ffff] + + +$eol_char = [\x000A\x000D\x2028\x2029] -- any end of line character +-- $eol_char = [$lf $cr] -- any end of line character +$not_eol_char = ~$eol_char -- anything but an end of line character + + +-- From GOLD Parser +-- {ID Head} = {Letter} + [_] + [$] +@IDHead = $alpha | [_] | [\$] + +-- {ID Tail} = {Alphanumeric} + [_] + [$] +@IDTail = $alpha | $digit | [_] | [\$] + +-- {String Chars1} = {Printable} + {HT} - ["\] +-- {String Chars2} = {Printable} + {HT} - [\''] +-- $StringCharsDoubleQuote = [$printable $ht] # [$dq \\] +-- $StringCharsSingleQuote = [$printable $ht] # [$sq \\] + +$string_chars = [^ \n \r ' \" \\] + +-- See e.g. http://es5.github.io/x7.html#x7.8.4 (Table 4) +@sq_escapes = \\ ( \\ | ' | \" | \s | \- | b | f | n | r | t | v | 0 | x ) +@dq_escapes = \\ ( \\ | ' | \" | \s | \- | b | f | n | r | t | v | 0 | x ) + +@unicode_escape = \\ u $hex_digit{4} + +@string_parts = $string_chars | \\ $digit | $ls | $ps + +@non_escape_char = \\ [^ \n \\ ] + +@stringCharsSingleQuote = @string_parts | @sq_escapes | @unicode_escape | $dq | @non_escape_char +@stringCharsDoubleQuote = @string_parts | @dq_escapes | @unicode_escape | $sq | @non_escape_char + +-- Character values < 0x20. +$low_unprintable = [\x00-\x1f] + +-- LineContinuation :: \ LineTerminatorSequence +@LineContinuation = [\\] @LineTerminatorSequence + + +-- {RegExp Chars} = {Letter}+{Digit}+['^']+['$']+['*']+['+']+['?']+['{']+['}']+['|']+['-']+['.']+[',']+['#']+['[']+[']']+['_']+['<']+['>'] +-- $RegExpChars = [$alpha $digit \^\$\*\+\?\{\}\|\-\.\,\#\[\]\_\<\>] +-- $RegExpChars = [$printable] # [\\] +-- {Non Terminator} = {String Chars1} - {CR} - {LF} +-- $NonTerminator = $StringCharsDoubleQuote # [$cr $lf] +$regNonTerminator = [$printable] # [$cr $lf] + + +$reg_char_class_chars = [^ $cr $lf \[ \] ] +@reg_char_class_escapes = \\ ( \[ | \] ) +@regCharClass = \[ ($reg_char_class_chars | @reg_char_class_escapes)* \] + + +-- ~ (LineTerminator | MUL | BSLASH | DIV) +$RegExpFirstChar = [$printable] # [ $cr $lf \* \\ \/] +-- ~ ( LineTerminator | BSLASH | DIV ) +$RegExpChars = [$printable] # [ $cr $lf \\ \/] + +$MultiLineNotAsteriskChar = [$any_unicode_char] # [\*] +$MultiLineNotForwardSlashOrAsteriskChar = [$any_unicode_char] # [\* \/] + +-- See http://blog.stevenlevithan.com/archives/javascript-regex-and-unicode + -- * \u0009 — Tab — \t + -- * \u000a — Line feed — \n — (newline character) + -- * \u000b — Vertical tab — \v + -- * \u000c — Form feed — \f + -- * \u000d — Carriage return — \r — (newline character) + -- * \u0020 — Space + -- * \u00a0 — No-break space + -- * \u1680 — Ogham space mark + -- * \u180e — Mongolian vowel separator + -- * \u2000 — En quad + -- * \u2001 — Em quad + -- * \u2002 — En space + -- * \u2003 — Em space + -- * \u2004 — Three-per-em space + -- * \u2005 — Four-per-em space + -- * \u2006 — Six-per-em space + -- * \u2007 — Figure space + -- * \u2008 — Punctuation space + -- * \u2009 — Thin space + -- * \u200a — Hair space + -- * \u2028 — Line separator — (newline character) + -- * \u2029 — Paragraph separator — (newline character) + -- * \u202f — Narrow no-break space + -- * \u205f — Medium mathematical space + -- * \u3000 — Ideographic space + +-- Note: from edition 5 the BOM (\xfeff) is also considered whitespace +$white_char = [\x0009\x000a\x000b\x000c\x000d\x0020\x00a0\x1680\x180e\x2000\x2001\x2002\x2003\x2004\x2005\x2006\x2007\x2008\x2009\x200a\x2028\x2029\x202f\x205f\x3000\xfeff] + +-- Identifier characters +-- UnicodeLetter +-- any character in the Unicode categories “Uppercase letter (Lu)”, “Lowercase letter (Ll)”, +-- “Titlecase letter (Lt)”, “Modifier letter (Lm)”, “Other letter (Lo)”, or “Letter number (Nl)”. + +-- http://www.fileformat.info/info/unicode/category/Lu/list.htm etc, see unicode/doit.sh +$UnicodeLetter = [\x41-\x5a\x61-\x7a\xaa-\xaa\xb5-\xb5\xba-\xba\xc0-\xd6\xd8-\xf6\xf8-\x2c1\x2c6-\x2d1\x2e0-\x2e4\x2ec-\x2ec\x2ee-\x2ee\x370-\x374\x376-\x377\x37a-\x37d\x386-\x386\x388-\x38a\x38c-\x38c\x38e-\x3a1\x3a3-\x3f5\x3f7-\x481\x48a-\x527\x531-\x556\x559-\x559\x561-\x587\x5d0-\x5ea\x5f0-\x5f2\x620-\x64a\x66e-\x66f\x671-\x6d3\x6d5-\x6d5\x6e5-\x6e6\x6ee-\x6ef\x6fa-\x6fc\x6ff-\x6ff\x710-\x710\x712-\x72f\x74d-\x7a5\x7b1-\x7b1\x7ca-\x7ea\x7f4-\x7f5\x7fa-\x7fa\x800-\x815\x81a-\x81a\x824-\x824\x828-\x828\x840-\x858\x904-\x939\x93d-\x93d\x950-\x950\x958-\x961\x971-\x977\x979-\x97f\x985-\x98c\x98f-\x990\x993-\x9a8\x9aa-\x9b0\x9b2-\x9b2\x9b6-\x9b9\x9bd-\x9bd\x9ce-\x9ce\x9dc-\x9dd\x9df-\x9e1\x9f0-\x9f1\xa05-\xa0a\xa0f-\xa10\xa13-\xa28\xa2a-\xa30\xa32-\xa33\xa35-\xa36\xa38-\xa39\xa59-\xa5c\xa5e-\xa5e\xa72-\xa74\xa85-\xa8d\xa8f-\xa91\xa93-\xaa8\xaaa-\xab0\xab2-\xab3\xab5-\xab9\xabd-\xabd\xad0-\xad0\xae0-\xae1\xb05-\xb0c\xb0f-\xb10\xb13-\xb28\xb2a-\xb30\xb32-\xb33\xb35-\xb39\xb3d-\xb3d\xb5c-\xb5d\xb5f-\xb61\xb71-\xb71\xb83-\xb83\xb85-\xb8a\xb8e-\xb90\xb92-\xb95\xb99-\xb9a\xb9c-\xb9c\xb9e-\xb9f\xba3-\xba4\xba8-\xbaa\xbae-\xbb9\xbd0-\xbd0\xc05-\xc0c\xc0e-\xc10\xc12-\xc28\xc2a-\xc33\xc35-\xc39\xc3d-\xc3d\xc58-\xc59\xc60-\xc61\xc85-\xc8c\xc8e-\xc90\xc92-\xca8\xcaa-\xcb3\xcb5-\xcb9\xcbd-\xcbd\xcde-\xcde\xce0-\xce1\xcf1-\xcf2\xd05-\xd0c\xd0e-\xd10\xd12-\xd3a\xd3d-\xd3d\xd4e-\xd4e\xd60-\xd61\xd7a-\xd7f\xd85-\xd96\xd9a-\xdb1\xdb3-\xdbb\xdbd-\xdbd\xdc0-\xdc6\xe01-\xe30\xe32-\xe33\xe40-\xe46\xe81-\xe82\xe84-\xe84\xe87-\xe88\xe8a-\xe8a\xe8d-\xe8d\xe94-\xe97\xe99-\xe9f\xea1-\xea3\xea5-\xea5\xea7-\xea7\xeaa-\xeab\xead-\xeb0\xeb2-\xeb3\xebd-\xebd\xec0-\xec4\xec6-\xec6\xedc-\xedd\xf00-\xf00\xf40-\xf47\xf49-\xf6c\xf88-\xf8c\x1000-\x1000\x10000-\x1000b\x1000d-\x1000f\x1001-\x1001\x10010-\x1001f\x1002-\x1002\x10020-\x10026\x10028-\x1002f\x1003-\x1003\x10030-\x1003a\x1003c-\x1003d\x1003f-\x1003f\x1004-\x1004\x10040-\x1004d\x1005-\x1005\x10050-\x1005d\x1006-\x1008\x10080-\x1008f\x1009-\x1009\x10090-\x1009f\x100a-\x100a\x100a0-\x100af\x100b-\x100b\x100b0-\x100bf\x100c-\x100c\x100c0-\x100cf\x100d-\x100d\x100d0-\x100df\x100e-\x100e\x100e0-\x100ef\x100f-\x100f\x100f0-\x100fa\x1010-\x1014\x10140-\x1014f\x1015-\x1015\x10150-\x1015f\x1016-\x1016\x10160-\x1016f\x1017-\x1017\x10170-\x10174\x1018-\x1028\x10280-\x1028f\x1029-\x1029\x10290-\x1029c\x102a-\x102a\x102a0-\x102d0\x10300-\x1031e\x10330-\x1034a\x10380-\x1039d\x103a0-\x103c3\x103c8-\x103cf\x103d1-\x103d5\x103f-\x103f\x10400-\x1049d\x1050-\x1055\x105a-\x105d\x1061-\x1061\x1065-\x1066\x106e-\x1070\x1075-\x1080\x10800-\x10805\x10808-\x10808\x1080a-\x1080f\x1081-\x1081\x10810-\x10835\x10837-\x10838\x1083c-\x1083c\x1083f-\x10855\x108e-\x108e\x10900-\x10915\x10920-\x10939\x10a0-\x10a0\x10a00-\x10a00\x10a1-\x10a1\x10a10-\x10a13\x10a15-\x10a17\x10a19-\x10a1f\x10a2-\x10a2\x10a20-\x10a2f\x10a3-\x10a3\x10a30-\x10a33\x10a4-\x10a6\x10a60-\x10a6f\x10a7-\x10a7\x10a70-\x10a7c\x10a8-\x10b0\x10b00-\x10b0f\x10b1-\x10b1\x10b10-\x10b1f\x10b2-\x10b2\x10b20-\x10b2f\x10b3-\x10b3\x10b30-\x10b35\x10b4-\x10b4\x10b40-\x10b4f\x10b5-\x10b5\x10b50-\x10b55\x10b6-\x10b6\x10b60-\x10b6f\x10b7-\x10b7\x10b70-\x10b72\x10b8-\x10c0\x10c00-\x10c0f\x10c1-\x10c1\x10c10-\x10c1f\x10c2-\x10c2\x10c20-\x10c2f\x10c3-\x10c3\x10c30-\x10c3f\x10c4-\x10c4\x10c40-\x10c48\x10c5-\x10c5\x10d0-\x10fa\x10fc-\x10fc\x1100-\x1100\x11003-\x1100f\x1101-\x1101\x11010-\x1101f\x1102-\x1102\x11020-\x1102f\x1103-\x1103\x11030-\x11037\x1104-\x1108\x11083-\x1108f\x1109-\x1109\x11090-\x1109f\x110a-\x110a\x110a0-\x110af\x110b-\x1200\x12000-\x1200f\x1201-\x1201\x12010-\x1201f\x1202-\x1202\x12020-\x1202f\x1203-\x1203\x12030-\x1203f\x1204-\x1204\x12040-\x1204f\x1205-\x1205\x12050-\x1205f\x1206-\x1206\x12060-\x1206f\x1207-\x1207\x12070-\x1207f\x1208-\x1208\x12080-\x1208f\x1209-\x1209\x12090-\x1209f\x120a-\x120a\x120a0-\x120af\x120b-\x120b\x120b0-\x120bf\x120c-\x120c\x120c0-\x120cf\x120d-\x120d\x120d0-\x120df\x120e-\x120e\x120e0-\x120ef\x120f-\x120f\x120f0-\x120ff\x1210-\x1210\x12100-\x1210f\x1211-\x1211\x12110-\x1211f\x1212-\x1212\x12120-\x1212f\x1213-\x1213\x12130-\x1213f\x1214-\x1214\x12140-\x1214f\x1215-\x1215\x12150-\x1215f\x1216-\x1216\x12160-\x1216f\x1217-\x1217\x12170-\x1217f\x1218-\x1218\x12180-\x1218f\x1219-\x1219\x12190-\x1219f\x121a-\x121a\x121a0-\x121af\x121b-\x121b\x121b0-\x121bf\x121c-\x121c\x121c0-\x121cf\x121d-\x121d\x121d0-\x121df\x121e-\x121e\x121e0-\x121ef\x121f-\x121f\x121f0-\x121ff\x1220-\x1220\x12200-\x1220f\x1221-\x1221\x12210-\x1221f\x1222-\x1222\x12220-\x1222f\x1223-\x1223\x12230-\x1223f\x1224-\x1224\x12240-\x1224f\x1225-\x1225\x12250-\x1225f\x1226-\x1226\x12260-\x1226f\x1227-\x1227\x12270-\x1227f\x1228-\x1228\x12280-\x1228f\x1229-\x1229\x12290-\x1229f\x122a-\x122a\x122a0-\x122af\x122b-\x122b\x122b0-\x122bf\x122c-\x122c\x122c0-\x122cf\x122d-\x122d\x122d0-\x122df\x122e-\x122e\x122e0-\x122ef\x122f-\x122f\x122f0-\x122ff\x1230-\x1230\x12300-\x1230f\x1231-\x1231\x12310-\x1231f\x1232-\x1232\x12320-\x1232f\x1233-\x1233\x12330-\x1233f\x1234-\x1234\x12340-\x1234f\x1235-\x1235\x12350-\x1235f\x1236-\x1236\x12360-\x1236e\x1237-\x1240\x12400-\x1240f\x1241-\x1241\x12410-\x1241f\x1242-\x1242\x12420-\x1242f\x1243-\x1243\x12430-\x1243f\x1244-\x1244\x12440-\x1244f\x1245-\x1245\x12450-\x1245f\x1246-\x1246\x12460-\x12462\x1247-\x1248\x124a-\x124d\x1250-\x1256\x1258-\x1258\x125a-\x125d\x1260-\x1288\x128a-\x128d\x1290-\x12b0\x12b2-\x12b5\x12b8-\x12be\x12c0-\x12c0\x12c2-\x12c5\x12c8-\x12d6\x12d8-\x1300\x13000-\x1300f\x1301-\x1301\x13010-\x1301f\x1302-\x1302\x13020-\x1302f\x1303-\x1303\x13030-\x1303f\x1304-\x1304\x13040-\x1304f\x1305-\x1305\x13050-\x1305f\x1306-\x1306\x13060-\x1306f\x1307-\x1307\x13070-\x1307f\x1308-\x1308\x13080-\x1308f\x1309-\x1309\x13090-\x1309f\x130a-\x130a\x130a0-\x130af\x130b-\x130b\x130b0-\x130bf\x130c-\x130c\x130c0-\x130cf\x130d-\x130d\x130d0-\x130df\x130e-\x130e\x130e0-\x130ef\x130f-\x130f\x130f0-\x130ff\x1310-\x1310\x13100-\x1311f\x1312-\x1312\x13120-\x1312f\x1313-\x1313\x13130-\x1313f\x1314-\x1314\x13140-\x1314f\x1315-\x1315\x13150-\x1317f\x1318-\x1318\x13180-\x1318f\x1319-\x1319\x13190-\x1319f\x131a-\x131a\x131a0-\x131af\x131b-\x131b\x131b0-\x131bf\x131c-\x131c\x131c0-\x131cf\x131d-\x131d\x131d0-\x131df\x131e-\x131e\x131e0-\x131ef\x131f-\x131f\x131f0-\x131ff\x1320-\x1320\x13200-\x1320f\x1321-\x1321\x13210-\x1321f\x1322-\x1322\x13220-\x1322f\x1323-\x1323\x13230-\x1323f\x1324-\x1324\x13240-\x1324f\x1325-\x1325\x13250-\x1325f\x1326-\x1326\x13260-\x1326f\x1327-\x1327\x13270-\x1327f\x1328-\x1328\x13280-\x1328f\x1329-\x1329\x13290-\x1329f\x132a-\x132a\x132a0-\x132af\x132b-\x132b\x132b0-\x132bf\x132c-\x132c\x132c0-\x132cf\x132d-\x132d\x132d0-\x132df\x132e-\x132e\x132e0-\x132ef\x132f-\x132f\x132f0-\x132ff\x1330-\x1330\x13300-\x1330f\x1331-\x1331\x13310-\x1331f\x1332-\x1332\x13320-\x1332f\x1333-\x1333\x13330-\x1333f\x1334-\x1334\x13340-\x1334f\x1335-\x1335\x13350-\x1335f\x1336-\x1336\x13360-\x1336f\x1337-\x1337\x13370-\x1337f\x1338-\x1338\x13380-\x1338f\x1339-\x1339\x13390-\x1339f\x133a-\x133a\x133a0-\x133af\x133b-\x133b\x133b0-\x133bf\x133c-\x133c\x133c0-\x133cf\x133d-\x133d\x133d0-\x133df\x133e-\x133e\x133e0-\x133ef\x133f-\x133f\x133f0-\x133ff\x1340-\x1340\x13400-\x1340f\x1341-\x1341\x13410-\x1341f\x1342-\x1342\x13420-\x1342e\x1343-\x135a\x1380-\x138f\x13a0-\x13f4\x1401-\x166c\x166f-\x167f\x16800-\x1680f\x1681-\x1681\x16810-\x1681f\x1682-\x1682\x16820-\x1682f\x1683-\x1683\x16830-\x1683f\x1684-\x1684\x16840-\x1684f\x1685-\x1685\x16850-\x1685f\x1686-\x1686\x16860-\x1686f\x1687-\x1687\x16870-\x1687f\x1688-\x1688\x16880-\x1688f\x1689-\x1689\x16890-\x1689f\x168a-\x168a\x168a0-\x168af\x168b-\x168b\x168b0-\x168bf\x168c-\x168c\x168c0-\x168cf\x168d-\x168d\x168d0-\x168df\x168e-\x168e\x168e0-\x168ef\x168f-\x168f\x168f0-\x168ff\x1690-\x1690\x16900-\x1690f\x1691-\x1691\x16910-\x1691f\x1692-\x1692\x16920-\x1692f\x1693-\x1693\x16930-\x1693f\x1694-\x1694\x16940-\x1694f\x1695-\x1695\x16950-\x1695f\x1696-\x1696\x16960-\x1696f\x1697-\x1697\x16970-\x1697f\x1698-\x1698\x16980-\x1698f\x1699-\x1699\x16990-\x1699f\x169a-\x169a\x169a0-\x169ff\x16a0-\x16a0\x16a00-\x16a0f\x16a1-\x16a1\x16a10-\x16a1f\x16a2-\x16a2\x16a20-\x16a2f\x16a3-\x16a3\x16a30-\x16a38\x16a4-\x16ea\x16ee-\x16f0\x1700-\x170c\x170e-\x1711\x1720-\x1731\x1740-\x1751\x1760-\x176c\x176e-\x1770\x1780-\x17b3\x17d7-\x17d7\x17dc-\x17dc\x1820-\x1877\x1880-\x18a8\x18aa-\x18aa\x18b0-\x18f5\x1900-\x191c\x1950-\x196d\x1970-\x1974\x1980-\x19ab\x19c1-\x19c7\x1a00-\x1a16\x1a20-\x1a54\x1aa7-\x1aa7\x1b000-\x1b001\x1b05-\x1b33\x1b45-\x1b4b\x1b83-\x1ba0\x1bae-\x1baf\x1bc0-\x1be5\x1c00-\x1c23\x1c4d-\x1c4f\x1c5a-\x1c7d\x1ce9-\x1cec\x1cee-\x1cf1\x1d00-\x1d40\x1d400-\x1d40f\x1d41-\x1d41\x1d410-\x1d41f\x1d42-\x1d42\x1d420-\x1d42f\x1d43-\x1d43\x1d430-\x1d43f\x1d44-\x1d44\x1d440-\x1d44f\x1d45-\x1d45\x1d450-\x1d454\x1d456-\x1d45f\x1d46-\x1d46\x1d460-\x1d46f\x1d47-\x1d47\x1d470-\x1d47f\x1d48-\x1d48\x1d480-\x1d48f\x1d49-\x1d49\x1d490-\x1d49c\x1d49e-\x1d49f\x1d4a-\x1d4a\x1d4a2-\x1d4a2\x1d4a5-\x1d4a6\x1d4a9-\x1d4ac\x1d4ae-\x1d4af\x1d4b-\x1d4b\x1d4b0-\x1d4b9\x1d4bb-\x1d4bb\x1d4bd-\x1d4bf\x1d4c-\x1d4c\x1d4c0-\x1d4c3\x1d4c5-\x1d4cf\x1d4d-\x1d4d\x1d4d0-\x1d4df\x1d4e-\x1d4e\x1d4e0-\x1d4ef\x1d4f-\x1d4f\x1d4f0-\x1d4ff\x1d50-\x1d50\x1d500-\x1d505\x1d507-\x1d50a\x1d50d-\x1d50f\x1d51-\x1d51\x1d510-\x1d514\x1d516-\x1d51c\x1d51e-\x1d51f\x1d52-\x1d52\x1d520-\x1d52f\x1d53-\x1d53\x1d530-\x1d539\x1d53b-\x1d53e\x1d54-\x1d54\x1d540-\x1d544\x1d546-\x1d546\x1d54a-\x1d54f\x1d55-\x1d55\x1d550-\x1d550\x1d552-\x1d55f\x1d56-\x1d56\x1d560-\x1d56f\x1d57-\x1d57\x1d570-\x1d57f\x1d58-\x1d58\x1d580-\x1d58f\x1d59-\x1d59\x1d590-\x1d59f\x1d5a-\x1d5a\x1d5a0-\x1d5af\x1d5b-\x1d5b\x1d5b0-\x1d5bf\x1d5c-\x1d5c\x1d5c0-\x1d5cf\x1d5d-\x1d5d\x1d5d0-\x1d5df\x1d5e-\x1d5e\x1d5e0-\x1d5ef\x1d5f-\x1d5f\x1d5f0-\x1d5ff\x1d60-\x1d60\x1d600-\x1d60f\x1d61-\x1d61\x1d610-\x1d61f\x1d62-\x1d62\x1d620-\x1d62f\x1d63-\x1d63\x1d630-\x1d63f\x1d64-\x1d64\x1d640-\x1d64f\x1d65-\x1d65\x1d650-\x1d65f\x1d66-\x1d66\x1d660-\x1d66f\x1d67-\x1d67\x1d670-\x1d67f\x1d68-\x1d68\x1d680-\x1d68f\x1d69-\x1d69\x1d690-\x1d69f\x1d6a-\x1d6a\x1d6a0-\x1d6a5\x1d6a8-\x1d6af\x1d6b-\x1d6b\x1d6b0-\x1d6bf\x1d6c-\x1d6c\x1d6c0-\x1d6c0\x1d6c2-\x1d6cf\x1d6d-\x1d6d\x1d6d0-\x1d6da\x1d6dc-\x1d6df\x1d6e-\x1d6e\x1d6e0-\x1d6ef\x1d6f-\x1d6f\x1d6f0-\x1d6fa\x1d6fc-\x1d6ff\x1d70-\x1d70\x1d700-\x1d70f\x1d71-\x1d71\x1d710-\x1d714\x1d716-\x1d71f\x1d72-\x1d72\x1d720-\x1d72f\x1d73-\x1d73\x1d730-\x1d734\x1d736-\x1d73f\x1d74-\x1d74\x1d740-\x1d74e\x1d75-\x1d75\x1d750-\x1d75f\x1d76-\x1d76\x1d760-\x1d76e\x1d77-\x1d77\x1d770-\x1d77f\x1d78-\x1d78\x1d780-\x1d788\x1d78a-\x1d78f\x1d79-\x1d79\x1d790-\x1d79f\x1d7a-\x1d7a\x1d7a0-\x1d7a8\x1d7aa-\x1d7af\x1d7b-\x1d7b\x1d7b0-\x1d7bf\x1d7c-\x1d7c\x1d7c0-\x1d7c2\x1d7c4-\x1d7cb\x1d7d-\x1dbf\x1e00-\x1f15\x1f18-\x1f1d\x1f20-\x1f45\x1f48-\x1f4d\x1f50-\x1f57\x1f59-\x1f59\x1f5b-\x1f5b\x1f5d-\x1f5d\x1f5f-\x1f7d\x1f80-\x1fb4\x1fb6-\x1fbc\x1fbe-\x1fbe\x1fc2-\x1fc4\x1fc6-\x1fcc\x1fd0-\x1fd3\x1fd6-\x1fdb\x1fe0-\x1fec\x1ff2-\x1ff4\x1ff6-\x1ffc\x20000-\x20000\x2071-\x2071\x207f-\x207f\x2090-\x209c\x2102-\x2102\x2107-\x2107\x210a-\x2113\x2115-\x2115\x2119-\x211d\x2124-\x2124\x2126-\x2126\x2128-\x2128\x212a-\x212d\x212f-\x2139\x213c-\x213f\x2145-\x2149\x214e-\x214e\x2160-\x2188\x2a6d6-\x2a6d6\x2a700-\x2a700\x2b734-\x2b734\x2b740-\x2b740\x2b81d-\x2b81d\x2c00-\x2c2e\x2c30-\x2c5e\x2c60-\x2ce4\x2ceb-\x2cee\x2d00-\x2d25\x2d30-\x2d65\x2d6f-\x2d6f\x2d80-\x2d96\x2da0-\x2da6\x2da8-\x2dae\x2db0-\x2db6\x2db8-\x2dbe\x2dc0-\x2dc6\x2dc8-\x2dce\x2dd0-\x2dd6\x2dd8-\x2dde\x2e2f-\x2e2f\x2f800-\x2fa1d\x3005-\x3007\x3021-\x3029\x3031-\x3035\x3038-\x303c\x3041-\x3096\x309d-\x309f\x30a1-\x30fa\x30fc-\x30ff\x3105-\x312d\x3131-\x318e\x31a0-\x31ba\x31f0-\x31ff\x3400-\x3400\x4db5-\x4db5\x4e00-\x4e00\x9fcb-\x9fcb\xa000-\xa48c\xa4d0-\xa4fd\xa500-\xa60c\xa610-\xa61f\xa62a-\xa62b\xa640-\xa66e\xa67f-\xa697\xa6a0-\xa6ef\xa717-\xa71f\xa722-\xa788\xa78b-\xa78e\xa790-\xa791\xa7a0-\xa7a9\xa7fa-\xa801\xa803-\xa805\xa807-\xa80a\xa80c-\xa822\xa840-\xa873\xa882-\xa8b3\xa8f2-\xa8f7\xa8fb-\xa8fb\xa90a-\xa925\xa930-\xa946\xa960-\xa97c\xa984-\xa9b2\xa9cf-\xa9cf\xaa00-\xaa28\xaa40-\xaa42\xaa44-\xaa4b\xaa60-\xaa76\xaa7a-\xaa7a\xaa80-\xaaaf\xaab1-\xaab1\xaab5-\xaab6\xaab9-\xaabd\xaac0-\xaac0\xaac2-\xaac2\xaadb-\xaadd\xab01-\xab06\xab09-\xab0e\xab11-\xab16\xab20-\xab26\xab28-\xab2e\xabc0-\xabe2\xac00-\xac00\xd7a3-\xd7a3\xd7b0-\xd7c6\xd7cb-\xd7fb\xf900-\xfa2d\xfa30-\xfa6d\xfa70-\xfad9\xfb00-\xfb06\xfb13-\xfb17\xfb1d-\xfb1d\xfb1f-\xfb28\xfb2a-\xfb36\xfb38-\xfb3c\xfb3e-\xfb3e\xfb40-\xfb41\xfb43-\xfb44\xfb46-\xfbb1\xfbd3-\xfd3d\xfd50-\xfd8f\xfd92-\xfdc7\xfdf0-\xfdfb\xfe70-\xfe74\xfe76-\xfefc\xff21-\xff3a\xff41-\xff5a\xff66-\xffbe\xffc2-\xffc7\xffca-\xffcf\xffd2-\xffd7] + +-- UnicodeCombiningMark +-- any character in the Unicode categories “Non-spacing mark (Mn)” or “Combining spacing mark (Mc)” +$UnicodeCombiningMark = [\x300-\x36f\x483-\x487\x591-\x5bd\x5bf-\x5bf\x5c1-\x5c2\x5c4-\x5c5\x5c7-\x5c7\x610-\x61a\x64b-\x65f\x670-\x670\x6d6-\x6dc\x6df-\x6e4\x6e7-\x6e8\x6ea-\x6ed\x711-\x711\x730-\x74a\x7a6-\x7b0\x7eb-\x7f3\x816-\x819\x81b-\x823\x825-\x827\x829-\x82d\x859-\x85b\x900-\x903\x93a-\x93c\x93e-\x94f\x951-\x957\x962-\x963\x981-\x983\x9bc-\x9bc\x9be-\x9c4\x9c7-\x9c8\x9cb-\x9cd\x9d7-\x9d7\x9e2-\x9e3\xa01-\xa03\xa3c-\xa3c\xa3e-\xa42\xa47-\xa48\xa4b-\xa4d\xa51-\xa51\xa70-\xa71\xa75-\xa75\xa81-\xa83\xabc-\xabc\xabe-\xac5\xac7-\xac9\xacb-\xacd\xae2-\xae3\xb01-\xb03\xb3c-\xb3c\xb3e-\xb44\xb47-\xb48\xb4b-\xb4d\xb56-\xb57\xb62-\xb63\xb82-\xb82\xbbe-\xbc2\xbc6-\xbc8\xbca-\xbcd\xbd7-\xbd7\xc01-\xc03\xc3e-\xc44\xc46-\xc48\xc4a-\xc4d\xc55-\xc56\xc62-\xc63\xc82-\xc83\xcbc-\xcbc\xcbe-\xcc4\xcc6-\xcc8\xcca-\xccd\xcd5-\xcd6\xce2-\xce3\xd02-\xd03\xd3e-\xd44\xd46-\xd48\xd4a-\xd4d\xd57-\xd57\xd62-\xd63\xd82-\xd83\xdca-\xdca\xdcf-\xdd4\xdd6-\xdd6\xdd8-\xddf\xdf2-\xdf3\xe31-\xe31\xe34-\xe3a\xe47-\xe4e\xeb1-\xeb1\xeb4-\xeb9\xebb-\xebc\xec8-\xecd\xf18-\xf19\xf35-\xf35\xf37-\xf37\xf39-\xf39\xf3e-\xf3f\xf71-\xf84\xf86-\xf87\xf8d-\xf97\xf99-\xfbc\xfc6-\xfc6\x101fd-\x101fd\x102b-\x103e\x1056-\x1059\x105e-\x1060\x1062-\x1064\x1067-\x106d\x1071-\x1074\x1082-\x108d\x108f-\x108f\x109a-\x109d\x10a01-\x10a03\x10a05-\x10a06\x10a0c-\x10a0f\x10a38-\x10a3a\x10a3f-\x10a3f\x11000-\x11002\x11038-\x11046\x11080-\x11082\x110b0-\x110ba\x135d-\x135f\x1712-\x1714\x1732-\x1734\x1752-\x1753\x1772-\x1773\x17b6-\x17d3\x17dd-\x17dd\x180b-\x180d\x18a9-\x18a9\x1920-\x192b\x1930-\x193b\x19b0-\x19c0\x19c8-\x19c9\x1a17-\x1a1b\x1a55-\x1a5e\x1a60-\x1a7c\x1a7f-\x1a7f\x1b00-\x1b04\x1b34-\x1b44\x1b6b-\x1b73\x1b80-\x1b82\x1ba1-\x1baa\x1be6-\x1bf3\x1c24-\x1c37\x1cd0-\x1cd2\x1cd4-\x1ce8\x1ced-\x1ced\x1cf2-\x1cf2\x1d165-\x1d169\x1d16d-\x1d172\x1d17b-\x1d182\x1d185-\x1d18b\x1d1aa-\x1d1ad\x1d242-\x1d244\x1dc0-\x1de6\x1dfc-\x1dff\x20d0-\x20dc\x20e1-\x20e1\x20e5-\x20f0\x2cef-\x2cf1\x2d7f-\x2d7f\x2de0-\x2dff\x302a-\x302f\x3099-\x309a\xa66f-\xa66f\xa67c-\xa67d\xa6f0-\xa6f1\xa802-\xa802\xa806-\xa806\xa80b-\xa80b\xa823-\xa827\xa880-\xa881\xa8b4-\xa8c4\xa8e0-\xa8f1\xa926-\xa92d\xa947-\xa953\xa980-\xa983\xa9b3-\xa9c0\xaa29-\xaa36\xaa43-\xaa43\xaa4c-\xaa4d\xaa7b-\xaa7b\xaab0-\xaab0\xaab2-\xaab4\xaab7-\xaab8\xaabe-\xaabf\xaac1-\xaac1\xabe3-\xabea\xabec-\xabed\xe0100-\xe01ef\xfb1e-\xfb1e\xfe00-\xfe0f] + +-- UnicodeDigit +-- any character in the Unicode category “Decimal number (Nd)” +$UnicodeDigit = [\x30-\x39\x660-\x669\x6f0-\x6f9\x7c0-\x7c9\x966-\x96f\x9e6-\x9ef\xa66-\xa6f\xae6-\xaef\xb66-\xb6f\xbe6-\xbef\xc66-\xc6f\xce6-\xcef\xd66-\xd6f\xe50-\xe59\xed0-\xed9\xf20-\xf29\x1040-\x1049\x104a0-\x104a9\x1090-\x1099\x11066-\x1106f\x17e0-\x17e9\x1810-\x1819\x1946-\x194f\x19d0-\x19d9\x1a80-\x1a89\x1a90-\x1a99\x1b50-\x1b59\x1bb0-\x1bb9\x1c40-\x1c49\x1c50-\x1c59\x1d7ce-\x1d7ff\xa620-\xa629\xa8d0-\xa8d9\xa900-\xa909\xa9d0-\xa9d9\xaa50-\xaa59\xabf0-\xabf9] + +-- UnicodeConnectorPunctuation +-- any character in the Unicode category “Connector punctuation (Pc)” +$UnicodeConnectorPunctuation = [\x5f-\x5f\x203f-\x2040\x2054-\x2054\xfe33-\xfe34\xfe4d-\xfe4f] + +-- UnicodeEscapeSequence :: +-- u HexDigit HexDigit HexDigit HexDigit +$HexDigit = [0-9a-fA-F] +@UnicodeEscapeSequence = u $HexDigit $HexDigit $HexDigit $HexDigit + +-- IdentifierStart :: +-- UnicodeLetter +-- $ +-- _ +-- \ UnicodeEscapeSequence +@IdentifierStart = $UnicodeLetter | [\$] | [_] | [\\] @UnicodeEscapeSequence + +-- IdentifierPart :: +-- IdentifierStart +-- UnicodeCombiningMark +-- UnicodeDigit +-- UnicodeConnectorPunctuation +-- \ UnicodeEscapeSequence + +$ZWNJ = [\x200c] +$ZWJ = [\x200d] +@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 template } + +-- Skip Whitespace + $white_char+ { adapt (mkString wsToken) } + +-- Skip one line comment + "//"($not_eol_char)* { adapt (mkString commentToken) } + +-- --------------------------------------------------------------------- +-- Comment definition from the ECMAScript spec, ver 3 + +-- MultiLineComment :: +-- /* MultiLineCommentChars(opt) */ +-- MultiLineCommentChars :: +-- MultiLineNotAsteriskChar MultiLineCommentChars(opt) +-- * PostAsteriskCommentChars(opt) +-- PostAsteriskCommentChars :: +-- MultiLineNotForwardSlashOrAsteriskChar MultiLineCommentChars(opt) +-- * PostAsteriskCommentChars(opt) +-- MultiLineNotAsteriskChar :: +-- SourceCharacter but not asterisk * +-- MultiLineNotForwardSlashOrAsteriskChar :: +-- SourceCharacter but not forward-slash / or asterisk * + +-- Skip multi-line comments. Note: may not nest +-- "/*"($any_char)*"*/" ; +-- "/*" (($MultiLineNotAsteriskChar)*| ("*")+ ($MultiLineNotForwardSlashOrAsteriskChar) )* ("*")+ "/" ; + "/*" (($MultiLineNotAsteriskChar)*| ("*")+ ($MultiLineNotForwardSlashOrAsteriskChar) )* ("*")+ "/" { adapt (mkString commentToken) } + + +-- Identifier = {ID Head}{ID Tail}* +-- @IDHead(@IDTail)* { \loc len str -> keywordOrIdent (take len str) loc } + @IdentifierStart(@IdentifierPart)* { \ap@(loc,_,_,str) len -> keywordOrIdent (take len str) (toTokenPosn loc) } + +-- ECMA-262 : Section 7.8.4 String Literals +-- StringLiteral = '"' ( {String Chars1} | '\' {Printable} )* '"' +-- | '' ( {String Chars2} | '\' {Printable} )* '' + $dq (@stringCharsDoubleQuote *) $dq + | $sq (@stringCharsSingleQuote *) $sq { adapt (mkString stringToken) } + +-- HexIntegerLiteral = '0x' {Hex Digit}+ + ("0x"|"0X") $hex_digit+ { adapt (mkString hexIntegerToken) } + +-- OctalLiteral = '0' {Octal Digit}+ + ("0") $oct_digit+ { adapt (mkString octalToken) } + +-- RegExp = '/' ({RegExp Chars} | '\' {Non Terminator})+ '/' ( 'g' | 'i' | 'm' )* + + "/" + ("\" $regNonTerminator | @regCharClass | $RegExpFirstChar) + ("\" $regNonTerminator | @regCharClass | $RegExpChars)* "/" ("g"|"i"|"m")* { adapt (mkString regExToken) } + + + + "`" @TemplateCharacters "`" { adapt (mkString' NoSubstitutionTemplateToken) } + "`" @TemplateCharacters "${" { adapt (mkString' TemplateHeadToken) } +