WebBits 0.15 → 2.2
raw patch · 17 files changed
Files
- LICENSE +23/−11
- WebBits.cabal +25/−32
- src/BrownPLT/Html.hs +0/−14
- src/BrownPLT/Html/Instances.hs +0/−66
- src/BrownPLT/Html/PermissiveParser.hs +0/−492
- src/BrownPLT/Html/PrettyPrint.hs +0/−53
- src/BrownPLT/Html/RawScript.hs +0/−35
- src/BrownPLT/Html/Syntax.hs +0/−86
- src/BrownPLT/JavaScript.hs +0/−4
- src/BrownPLT/JavaScript/Crawl.hs +0/−102
- src/BrownPLT/JavaScript/Environment.hs +12/−6
- src/BrownPLT/JavaScript/HtmlEmbedding.hs +0/−25
- src/BrownPLT/JavaScript/Instances.hs +0/−294
- src/BrownPLT/JavaScript/Lexer.hs +1/−1
- src/BrownPLT/JavaScript/Parser.hs +117/−81
- src/BrownPLT/JavaScript/PrettyPrint.hs +20/−15
- src/BrownPLT/JavaScript/Syntax.hs +22/−12
LICENSE view
@@ -1,14 +1,26 @@-Copyright (c) 2007-2008 Arjun Guha and Spiridon Eliopoulos.--WebBits is licensed under the terms of the GNU Lesser General Public License-2.1.+Copyright (c) 2007--2011, Brown University and Claudiu Saftoiu+All Rights Reserved. -Contains source code derived from HtmlPrag 0.16, Copyright (c) 2003 - 2005 Neil-W. Van Dyke, licensed under the terms of the GNU Lesser General Public License-2.1.+Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met: -Contains source code derived from javascript.plt, Copyright (c) 2008 David-Herman, licensed under the terms of the GNU Lesser General Public License 2.1+ * 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 Brown University nor the names of its contributors+ may be used to endorse or promote products derived from this software+ without specific prior written permission. -The tests/ directory contains open-source JavaScript code. Their licenses-are inline.+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.
WebBits.cabal view
@@ -1,54 +1,47 @@ Name: WebBits-Version: 0.15-Cabal-Version: >= 1.2.3-Copyright: Copyright (c) 2007-2009 Arjun Guha and Spiridon Eliopoulos-License: LGPL+Version: 2.2+Cabal-Version: >= 1.6+Copyright: Copyright (c) 2007-2011 Brown University, Claudiu Saftoiu, Arjun Guha, Spiridon Eliopoulos, Copyright (c) 2012 Arjun Guha and Andrey Chudnov+License: BSD3 License-file: LICENSE-Author: Arjun Guha, Spiridon Eliopoulos-Maintainer: Arjun Guha <arjun@cs.brown.edu>-Homepage: http://www.cs.brown.edu/research/plt/+Author: Arjun Guha, Claudiu Saftoiu, Spiridon Eliopoulos and Andrey Chudnov+Maintainer: Andrey Chudnov <oss@chudnov.com>+Homepage: http://github.com/brownplt/webbits+Bug-reports: http://github.com/brownplt/webbits/issues Stability: provisional+Tested-with: GHC==7.0.4, GHC==7.4.1 Category: Language Build-Type: Custom Synopsis: JavaScript analysis tools-Description:+Description: WebBits is a collection of libraries for working with JavaScript, contains a parser, a pretty-printer and a lexical environment analyser. The original author of the package is the PLT group of Brown University (http:\/\/www.cs.brown.edu\/research\/plt\/). Changes since version 2.1: the syntax of the try-catch-finally statement has been changed in accordance to the ECMAScript specification -- now it only has at most one catch clause. The original test-suite needs updating to support the current test system: patches are welcome. - WebBits is a collection of libraries for working with JavaScript embeded in- HTML files. Highlights include:- .- * @BrownPLT.JavaScript.Crawl@ returns all JavaScript in an HTML page, including- JavaScript from imported script files (@\<script src=...\>@).- .- * @BrownPLT.JavaScript.Environment@ annotates JavaScript syntax with its - static environment and returns a list of free identifiers.- .- * @BrownPLT.JavaScript.Parser@ is a JavaScript parser that is largely based on- JavaScript 1.5.- .- * @BrownPLT.Html.Parser@ is a permissive HTML parser.+Source-repository head+ type: git+ location: git://github.com/brownplt/webbits.git++Source-repository this+ type: git+ location: git://github.com/brownplt/webbits.git+ tag: WebBits-2.2 Library Hs-Source-Dirs: src Build-Depends:- base>=4, mtl>=1.1.0.1, parsec<3.0.0, pretty>=0.1, containers>=0.1, syb>=0.1+ base >= 4 && < 5,+ mtl >= 1.1.0.1,+ parsec < 3.2.0,+ pretty >= 0.1,+ containers >= 0.1,+ syb >= 0.1 ghc-options: -fwarn-incomplete-patterns Extensions: - Generics TypeSynonymInstances DeriveDataTypeable+ DeriveDataTypeable Exposed-Modules:- BrownPLT.Html- BrownPLT.Html.Syntax- BrownPLT.Html.PermissiveParser- BrownPLT.Html.PrettyPrint - BrownPLT.Html.Instances- BrownPLT.Html.RawScript BrownPLT.JavaScript - BrownPLT.JavaScript.HtmlEmbedding - BrownPLT.JavaScript.Instances BrownPLT.JavaScript.Lexer BrownPLT.JavaScript.Parser BrownPLT.JavaScript.PrettyPrint BrownPLT.JavaScript.Syntax - BrownPLT.JavaScript.Crawl BrownPLT.JavaScript.Environment
− src/BrownPLT/Html.hs
@@ -1,14 +0,0 @@--- |Rexports various modules of the HTML library. It's best to use this in lieu--- of selectively importing the following libraries.-module BrownPLT.Html- ( module BrownPLT.Html.Syntax- -- PermissiveParser- , renderHtml- , parseHtmlFromFile- , parseHtmlFromString- ) where- -import BrownPLT.Html.Syntax-import BrownPLT.Html.PermissiveParser-import BrownPLT.Html.PrettyPrint -- no names, only instances-import BrownPLT.Html.Instances -- no names, only instances
− src/BrownPLT/Html/Instances.hs
@@ -1,66 +0,0 @@-module BrownPLT.Html.Instances() where--import qualified Prelude as Prelude-import Prelude (Functor,map,fmap)-import qualified Data.List as List-import qualified Data.Char as Char-import Data.Foldable-import Data.Traversable-import Control.Applicative--import BrownPLT.Html.Syntax--ltraverse:: (Traversable t, Applicative f) => (a -> f b) -> [t a] -> f [t b]-ltraverse f [] = pure []-ltraverse f (x:xs) = pure (:) <*> (traverse f x) <*> ltraverse f xs--instance Functor (Attribute a) where- fmap f (Attribute id val a) = Attribute id val a- fmap f (AttributeExpr a id script def) = AttributeExpr a id (f script) def--instance Functor (Html a) where- fmap f (Element id attrs children a) = - Element id (map (fmap f) attrs) (map (fmap f) children) a- fmap f (Text str a) = Text str a- fmap f (Comment str a) = Comment str a- fmap f (HtmlSeq xs) = HtmlSeq (map (fmap f) xs)- fmap f (ProcessingInstruction str a) = ProcessingInstruction str a- fmap f (InlineScript script a def) = InlineScript (f script) a def- fmap f (Script script a) = Script (f script) a--instance Foldable (Attribute a) where- foldr f x (Attribute id val a) = x- foldr f x (AttributeExpr a id script def) = f script x--instance Foldable (Html a) where- foldr f x (Element id attrs children a) =- Prelude.foldr (\child x' -> foldr f x' child) x children - foldr f x (Text str a) = x- foldr f x (Comment str a) = x- foldr f x (HtmlSeq ys) = - Prelude.foldr (\child x' -> foldr f x' child) x ys- foldr f x (ProcessingInstruction str a) = x- foldr f x (InlineScript script a def) = f script x- foldr f x (Script script a) = f script x--instance Traversable (Attribute a) where- traverse f (Attribute id val a) =- pure (Attribute id val a)- traverse f (AttributeExpr a id script def) =- (AttributeExpr a id) <$> (f script) <*> pure def--instance Traversable (Html a) where- traverse f (Element id attrs children a) = - (Element id) <$> ltraverse f attrs <*> ltraverse f children <*> pure a- traverse f (Text str a) = - pure (Text str a)- traverse f (Comment str a) = - pure (Comment str a)- traverse f (HtmlSeq xs) = - HtmlSeq <$> ltraverse f xs- traverse f (ProcessingInstruction str a) = - pure (ProcessingInstruction str a)- traverse f (InlineScript script a def) =- InlineScript <$> (f script) <*> pure a <*> pure def- traverse f (Script script a) = - Script <$> (f script) <*> pure a
− src/BrownPLT/Html/PermissiveParser.hs
@@ -1,492 +0,0 @@--- |A structure-recovering parser for malformed documents.------ Copyright 2007-2008 Arjun Guha.--- Based on HtmlPrag 0.16 Copyright (C) 2003 - 2005 Neil W. Van Dyke. ------ This program is Free Software; you can redistribute it and/or modify it under--- the terms of the GNU Lesser General Public License as published by the Free--- Software Foundation; either version 2.1 of the License, or (at your option)--- any later version. This program is distributed in the hope that it will be--- useful, but without any warranty; without even the implied warranty of--- merchantability or fitness for a particular purpose. See --- <http://www.gnu.org/copyleft/lesser.html> for details. For other license--- options and consulting, contact the author.-module BrownPLT.Html.PermissiveParser- ( html- , parseHtmlFromFile- , parseHtmlFromString- -- tokenizer is exported primarily for testing- , tokens- , Token- ) where--import Control.Monad-import Text.ParserCombinators.Parsec hiding (token,tokens)-import qualified Text.ParserCombinators.Parsec as Parsec-import Data.Char (toLower)-import Data.List (intersperse)--import qualified BrownPLT.Html.Syntax as Html-import BrownPLT.Html.Syntax (HtmlId,Attribute,Script(..))--type ParsedHtml s = Html.Html SourcePos s-type ParsedAttribute s = Html.Attribute SourcePos s------------------------------------------------------------------------------------- Parsers generate warnings--data Warning = StringWarning SourcePos String--instance Show Warning where- show (StringWarning p s) = "Warning parsing HTML: " ++ s- showList [] s = s- showList (x:xs) s = show x ++ ('\n':showList xs s)--warn:: String -> GenParser tok [Warning] ()-warn s = do- p <- getPosition- updateState ((StringWarning p s):)--noWarnings:: [Warning]-noWarnings = []- ---- A structure-recovering parser for malformed documents, derived from--- Neil W. Van Dyke's htmlprag library for PLT Scheme---- The elements in the list can legally enclose the 1st element of the pair.-parentConstraints:: [(HtmlId,[HtmlId])]-parentConstraints =- [("area",["map"]),- ("body",["html"]),- ("caption", ["table"]),- ("colgroup", ["table"]),- ("dd", ["dl"]),- ("dt", ["dl"]),- ("frame", ["frameset"]),- ("head", ["html"]),- ("isindex", ["head"]),- ("li", ["dir", "menu", "ol", "ul"]),- ("meta", ["head"]),- ("noframes", ["frameset"]),- ("option", ["select"]),- ("p", ["body", "td", "th"]),- ("param", ["applet"]),- ("tbody", ["table"]),- ("td", ["tr"]),- ("th", ["tr"]),- ("thead", ["table"]),- ("title", ["head"]),- ("tr", ["table", "tbody", "thead"])]---- |List of HTML elements that are empty.-emptyElements:: [HtmlId]-emptyElements = - ["area", "base", "br", "frame", "hr", "img", "input", "isindex", "keygen", - "link", "meta", "object", "param", "spacer", "wbr"]--isLegalChildOf:: HtmlId -> HtmlId -> Bool-isLegalChildOf child parent =- case lookup child parentConstraints of- Nothing -> True- (Just legalParents) -> parent `elem` legalParents- -isEmptyElement:: HtmlId -> Bool-isEmptyElement element = element `elem` emptyElements----}}}------------------------------------------------------------------------------------- Parses an HTML file into a stream of tokens.---- The auxillary parsing functions return values of this type.-data Script s => Token s- = Text SourcePos String- | EntityToken SourcePos String- | EntityInt SourcePos Int- | Tag SourcePos HtmlId [Attribute SourcePos s] Bool {-closed?-}- | Script SourcePos s- | Inline SourcePos s String- | EndTag SourcePos HtmlId- | Comment SourcePos String- | DoctypeToken SourcePos String String String (Maybe String)---token:: Script s => Bool -> [Attribute SourcePos s] - -> CharParser [Warning] (Token s)-token expectedScript prevAttrs = case expectedScript of- True -> (liftM2 Script getPosition (parseScriptBlock prevAttrs)) - <?> "expected a script after a <script> tag"- False -> doctype <|> comment <|> tag <|> endTag <|> inlineScript <|> entity - <|> text--tokens:: Script s => CharParser [Warning] [Token s]-tokens = (eof >> return []) <|> tokens' where- tokens' = do - t <- token False []- case t of- (Tag _ "script" attrs False) -> do s <- token True attrs- ts <- tokens- return (t:s:ts)- _ -> tokens >>= return.(t:)------------------------------------------------------------------------------------- Parsers for various components of HTML--qname:: CharParser st String-qname = do- x <- letter- xs <- many (noneOf "/*=<>\"\' \v\f\t\r\n")- return (x:xs)---- |We do not permit spaces between the hyphens and the right-angle in the--- terminating '-->'.-comment:: Script s => CharParser st (Token s) -comment =- let notDoubleHyphen = try (char '-' >> notFollowedBy (char '-') >> return '-')- notHyphen = noneOf "-"- in do try (string "<!--")- pos <- getPosition- msg <- many (notHyphen <|> notDoubleHyphen)- string "-->"- return (Comment pos msg)--endTag:: Script s => CharParser [Warning] (Token s)-endTag = do- pos <- getPosition- string "</"- name <- qname <?> "closing tag\'s name"- junk <- manyTill anyChar (char '>') -- permits junk between tag name and '>'- unless (null junk) (warn $ "extra characters: " ++ junk ++ - "; assuming tag name is " ++ name)- return (EndTag pos name)- -doctype:: Script s => CharParser [Warning] (Token s)-doctype = do- p <- getPosition- try (string "<!DOCTYPE")- spaces- top <- qname <?> "top-element name"- spaces- avail <- qname <?> "availability"- spaces- regEtc <- quotedString <?> "registration, etc."- spaces- uri <- optionMaybe quotedString- spaces- string ">"- return (DoctypeToken p top avail regEtc uri)- -entity:: Script s => CharParser [Warning] (Token s)-entity = do- char '&'- pos <- getPosition- name <- many alphaNum <|> (char '#' >> many1 digit)- when (null name) (warn "no identifer or number after &")- (char ';' >> return ()) <|> (warn "expected semi-colon after entity") - return (EntityToken pos name)- -notScript:: CharParser a Char-notScript = try (char '{' >> notFollowedBy (char '!') >> return '{')---- Parses raw text, upto an opening angle-bracket ('<').-text:: Script s => CharParser st (Token s)-text = do- pos <- getPosition- cs <- many1 (noneOf "<{" <|> notScript) -- Doesn't consume the terminating angle bracket.- return (Text pos cs)---- Strings that are either double-quoted or single-quoted. Note that HTML--- strings contain no escape sequences.-quotedString:: CharParser a String-quotedString =- (char '"' >> manyTill anyChar (char '"')) <|>- (char '\'' >> manyTill anyChar (char '\'')) <?>- "quoted string (double-quotes or single quotes)"---- Parses text to the right of a triple-stick in an inline expression. We have--- to ensure that if we read a `!,' it isn't immediately followed by `}.'-initText =- let notEnd = try (char '!' >> notFollowedBy (char '}') >> return '!')- in many1 (notEnd <|> noneOf "!")--scriptValue:: Script s => CharParser a (s,String)-scriptValue =- case parseAttributeScript of- Nothing -> fail "attribute-script parser not defined"- (Just parser) -> do string "{!"- script <- parser- init <- (string "!}" >> return "") <|> - (string "|||" >> initText >>= - (\s -> string "!}" >> return s))- return (script,init)--number:: CharParser a String-number = many1 digit---- -nonquotedAttribute:: CharParser [Warning] String-nonquotedAttribute = do- x <- alphaNum <|> oneOf "_"- xs <- many (noneOf "/*=<>\"\' \v\f\t\r\n")- warn $ "non-quoted attribute value: " ++ (x:xs)- return (x:xs)---attribute:: Script s => CharParser [Warning] (Html.Attribute SourcePos s)-attribute = do- pos <- getPosition- name <- qname <?> "attribute name"- spaces- value <- (do char '='- spaces- (liftM Right scriptValue)- <|> (liftM Left (quotedString <|> nonquotedAttribute)) - <?> "attribute value")- <|> (return $ Left "") -- Unspecified values are empty values.- case value of- (Left v) -> return $ Html.Attribute name v pos- (Right (s,d)) -> return $ Html.AttributeExpr pos name s d---- Takes the name of the immediately-enclosing parent tag as an argument.-tag:: Script s => CharParser [Warning] (Token s)-tag = do- try (char '<' >> notFollowedBy (char '/'))- pos <- getPosition- name <- qname <?> "opening tag\'s name"- spaces- attributes <- (attribute `sepEndBy` spaces)- (char '>' >> return (Tag pos name attributes False))- <|> (string "/>" >> return (Tag pos name attributes True))- <?> "end of tag (i.e. \">\")"----- Parses an inline (curly-banged) script, if an inline-script parser has been--- specified (i.e. not Nothing). Two-character lookahead for the ``{!,'' after--- which control is passed to the inline script parser. Once control returns,--- the parser expects to see the closing ``!}.''-inlineScript:: Script s => CharParser a (Token s)-inlineScript =- case parseInlineScript of- Nothing -> fail "no inline script parser specified." -- TODO: appropriate?- (Just parser) -> do string "{!" <?> "{! script !}"- pos <- getPosition- script <- parser- spaces- init <- (string "!}" >> return "") <|>- (string "|||" >> initText >>= - (\s -> string "!}" >> return s))- return $ Inline pos script init----- Parses a stream of tokens, with a script parser, s and returns values of --- type a.-type TokenParser s a = GenParser (Token s) [Warning] a--instance Script s => Show (Token s) where- show = tokenShow--tokenShow token = case token of- (Text _ s) -> s- (EntityToken _ s) -> "&" ++ s ++ ";"- (EntityInt _ n) -> "&#" ++ show n ++ ";"- (Tag _ id attrs closed) -> - "<" ++ id ++ " ... " ++ closing where- closing = if closed then "/>" else ">"- (Script _ s) -> "/* script body omitted */"- (Inline _ s _)-> "{! /* script */ !}"- (EndTag _ id) -> "</" ++ show id ++ ">"- (Comment _ s) -> "<!-- " ++ show s ++ " -->"- (DoctypeToken _ top avail desc Nothing) ->- "<!DOCTYPE " ++ top ++ " " ++ avail ++ " " ++ show desc ++ ">"- (DoctypeToken _ top avail desc (Just uri)) ->- "<!DOCTYPE " ++ top ++ " " ++ avail ++ " " ++ show desc ++ " " - ++ show uri ++ ">" --tokenPos tok = case tok of- (Text p _) -> p- (EntityToken p _) -> p- (EntityInt p _) -> p- (Tag p _ _ _) -> p- (Script p _) -> p- (Inline p _ _) -> p- (EndTag p _) -> p- (Comment p _) -> p- (DoctypeToken p _ _ _ _) -> p- -textToken :: Script s => TokenParser s (ParsedHtml s)-textToken = Parsec.token tokenShow tokenPos $ \t -> case t of- Text _ s -> Just (Html.Text s (tokenPos t))- otherwise -> Nothing- -entityToken :: Script s => TokenParser s (ParsedHtml s)-entityToken =- Parsec.token tokenShow tokenPos- (\t -> case t of- (EntityToken p s) -> Just (Html.Text ("&" ++ s ++ ";") p)- (EntityInt p n) -> Just (Html.Text ("&#" ++ show n ++ ";") p)- otherwise -> Nothing)- -commentToken :: Script s => TokenParser s (ParsedHtml s)-commentToken = - Parsec.token tokenShow tokenPos- (\t -> case t of- (Comment _ s) -> Just (Html.Comment s (tokenPos t))- otherwise -> Nothing)--scriptToken :: Script s => TokenParser s (ParsedHtml s) -scriptToken = - Parsec.token tokenShow tokenPos- (\t -> case t of- (Script p s) -> Just (Html.Script s p)- otherwise -> Nothing)--inlineToken :: Script s => TokenParser s (ParsedHtml s)-inlineToken = - Parsec.token tokenShow tokenPos- (\t -> case t of- (Inline p s d) -> Just (Html.InlineScript s p d)- otherwise -> Nothing)- -endToken :: Script s => TokenParser s HtmlId-endToken = - Parsec.token tokenShow tokenPos- (\t -> case t of- (EndTag p s) -> Just s- otherwise -> Nothing)--tagToken :: Script s => TokenParser s (Token s)-tagToken = - Parsec.token tokenShow tokenPos- (\t -> case t of- (Tag p id attrs closed) -> Just t- otherwise -> Nothing)--doctypeToken :: Script s => TokenParser s (Token s)-doctypeToken = Parsec.token tokenShow tokenPos $ \t -> case t of- DoctypeToken _ _ _ _ _ -> Just t- otherwise -> Nothing------------------------------------------------------------------------------------- HTML fragments---- |An HTML fragment represents an HTML element with a sequence of children.-data HtmlFragment s = Fragment {- fragmentPosition :: SourcePos,- fragmentName :: HtmlId,- fragmentAttributes :: [ParsedAttribute s],- fragmentChildren :: [ParsedHtml s]-}--closeFragment:: HtmlFragment s -> ParsedHtml s-closeFragment (Fragment p htmlId attrs children) = - Html.Element htmlId attrs (reverse children) p--appendChildToFragment child fragment =- fragment { fragmentChildren = child : (fragmentChildren fragment) }- -atomic :: Script s => TokenParser s (ParsedHtml s)-atomic =- textToken <|> commentToken <|> scriptToken <|> inlineToken <|> entityToken---maybeClose :: Script s => [HtmlFragment s] -> TokenParser s [HtmlFragment s] -maybeClose es = do- htmlId <- endToken- let close [] = do - warn $ "unmatched closing tag \"" ++ htmlId ++ "\"; ignoring"- return es- close (e:e2:es) | fragmentName e == htmlId = do- return $ (appendChildToFragment (closeFragment e) e2) : es- close (e:e2:es) | otherwise = - let e2' = appendChildToFragment (closeFragment e) e2- in close (e2':es)- close [e] | fragmentName e == htmlId = do- return [e]- close [e] | otherwise = do- warn $ "unmatched closing tag \"" ++ htmlId ++ "\"; ignoring"- return [e]- in close es--open :: Script s => [HtmlFragment s] -> TokenParser s [HtmlFragment s]-open [] = fail "PermissiveParser.open: invalid state (1)"-open (e:es) = do- (Tag p id attrs isClosed) <- tagToken- case isClosed of- True -> return $ (appendChildToFragment (Html.Element id attrs [] p) e) : es- False ->- case isEmptyElement id of- True -> do warn $ "empty-element, \"" ++ id - ++ "\" was not immediately closed"- return $ (appendChildToFragment (Html.Element id attrs [] p)- e) : es- False -> do- let fragment = Fragment p id attrs []- -- If we reach the root, simply make 'fragment' a child.- let insert [root] = [fragment,root]- -- The <html> element is the only child of the root. This- -- catches all other elements and makes them children of <html>.- insert [html,root] = [fragment,html,root]- insert (e1:e2:es) | id `isLegalChildOf` (fragmentName e1) =- fragment:e1:e2:es- insert (e1:e2:es) | otherwise =- insert $ (appendChildToFragment (closeFragment e1) e2):es - insert [] = fail "PermissiveParser.open: invalid state (2)"- return $ insert (e:es)--structured es = do- maybeClose es <|> open es--html' :: Script s => [HtmlFragment s] -> TokenParser s [HtmlFragment s]-html' [] = fail "PermissiveParser.html': invalid state (1)"-html' (e:es) =- (do a <- atomic- html' $ (appendChildToFragment a e):es) <|>- (structured (e:es) >>= html') <|>- (return (e:es))--parseRoot = Fragment (error "parseRoot: position is meaningless") - "DOCROOT" (error "parseRoot: attributes are meaningless")- []--html :: Script s => CharParser [Warning] (Html.Html SourcePos s)-html = do- let parser = do- -- optional doctypeToken -- ignored- fragments <- html' [parseRoot]- case fragments of- [fragment] -> case closeFragment fragment of - Html.Element _ _ (c:_) _ -> do- ws <- getState- return (ws,head [c])- otherwise -> fail "root element not found"- otherwise -> fail "no root / multiple roots"- toks <- tokens -- a stream of HTML entities- pos <- Parsec.getPosition- warnings <- Parsec.getState- case Parsec.runParser parser warnings (Parsec.sourceName pos) toks of- Left e -> fail $ "unparsable HTML: " ++ (show e)- Right (ws,html) -> Parsec.setState ws >> return html --htmlWithWarnings :: Script s - => CharParser [Warning] (Html.Html SourcePos s,[Warning])-htmlWithWarnings = do- h <- html- ws <- getState- return (h,ws)--parseHtmlFromString :: Script s => String -> String -> Either Parsec.ParseError (Html.Html SourcePos s,[Warning])-parseHtmlFromString sourceName sourceText = - case Parsec.runParser htmlWithWarnings noWarnings sourceName sourceText of- Left err -> Left err- Right (html,ws) -> Right (html,ws) --parseHtmlFromFile :: Script s - => String - -> IO (Either Parsec.ParseError - (Html.Html SourcePos s,[Warning]))-parseHtmlFromFile filename = do- chars <- readFile filename- case Parsec.runParser htmlWithWarnings noWarnings filename chars of- Left err -> return (Left err)- Right (html,ws) -> return $ Right (html,ws)
− src/BrownPLT/Html/PrettyPrint.hs
@@ -1,53 +0,0 @@--- |Pretty-printer for HTML. This modules exports no names. It only defines--- instances of 'PrettyPrintable' for HTML. -module BrownPLT.Html.PrettyPrint- ( html- , renderHtml- ) where--import qualified Data.List as List-import qualified Data.Char as Char-import Text.PrettyPrint.HughesPJ--import BrownPLT.Html.Syntax--renderHtml :: Script s => Html a s -> String-renderHtml = render.html--vert [] = empty-vert [doc] = doc-vert (doc:docs) = doc <> text "<!--" $+$- text "-->" <> vert docs--attr :: Script s => Attribute a s -> Doc-attr a = case a of- Attribute name value _ ->- text name <> equals <> doubleQuotes (text value)- AttributeExpr _ n v "" ->- text n <> equals <> text "{!" <+> prettyPrintScript v <+> text "!}"- AttributeExpr _ n v d ->- text n <> equals <> text "{!" <+> prettyPrintScript v <+> text "|||" <+> - text d <+> text "!}"--html :: Script s => Html a s -> Doc-html x = case x of- -- The <script> tag must be terminated by </script>.- -- <script lang= src= /> doesn't work.- Element name attrs children _ ->- -- WARNING: Spacing is very sensitive- text "<" <> text name <+> hsep (map attr attrs) <> text ">" -- opening- $$ (nest 2 (vcat (map html children))) -- body- $$ text "</" <> text name <> text ">" -- closing- -- Horizontally aligned material that is vertically represented in source.- HtmlSeq xs -> vert (map html xs)- Text str _ -> text (skipWs str) where- skipWs str = List.dropWhile Char.isSpace str- Comment str _ -> text "<!--" <+> text str <+> text "-->"- ProcessingInstruction str _ -> text "<?" <> text str <> text ">"- Script s _ -> prettyPrintScript s- InlineScript script _ "" ->- text "{!" <+> prettyPrintScript script <+> text "!}"- InlineScript script _ init -> - text "{!" <+> prettyPrintScript script <+> text "|||" <+> - text init <+> text "!}"-
− src/BrownPLT/Html/RawScript.hs
@@ -1,35 +0,0 @@-module BrownPLT.Html.RawScript- ( RawScript (..)- , parseFromFile- , parseFromString- , RawHtml- ) where--import Data.Generics (Data, Typeable)-import Text.PrettyPrint.HughesPJ (text)-import Text.ParserCombinators.Parsec-import BrownPLT.Html.Syntax-import BrownPLT.Html.PermissiveParser--type RawHtml = Html SourcePos RawScript---data RawScript = RawScript String deriving (Show,Eq,Typeable,Data)---instance Script RawScript where-- prettyPrintScript (RawScript s) = text s- parseInlineScript = Nothing- - parseAttributeScript = Nothing- - parseScriptBlock _ = do- s <- manyTill anyChar (string "</script>")- return (RawScript s)- --parseFromString :: String -> RawHtml-parseFromString s = case parseHtmlFromString "" s of- Left e -> error (show e)- Right (html,_) -> html
− src/BrownPLT/Html/Syntax.hs
@@ -1,86 +0,0 @@--- |Datatypes for HTML parameterized over an annotation type and a script type.-module BrownPLT.Html.Syntax - (- -- * HTML Data Structures- HtmlId,AttributeValue, Attribute (..), Html (..)- -- * The Script class- , Script (..)- -- * Miscellaneous Functions- , attributeValue, attributeUpdate, attributeSet, isAttributeExpr- ) where--import Text.ParserCombinators.Parsec (CharParser, SourcePos)-import Text.PrettyPrint.HughesPJ (Doc)-import Data.Generics (Data, Typeable)------------------------------------------------------------------------------------- Types--type HtmlId = String-type AttributeValue = String--data Attribute a s- = Attribute HtmlId AttributeValue a- | AttributeExpr a HtmlId s String- deriving (Show,Eq,Typeable,Data)--data Html a sc- = Element HtmlId [Attribute a sc] [Html a sc] a- | Text String a- | Comment String a- | HtmlSeq [Html a sc] -- ^must be a non-empty list- | ProcessingInstruction String a- | InlineScript sc a String- | Script sc a- deriving (Show,Eq,Typeable,Data)- ------------------------------------------------------------------------------------ The Script class---- |A type 't' of the 'Script' class can be parsed using 'Parsec'. 't' is of--- kind '* -> *', as the parsed AST should be annotated with souce locations--- (see 'Text.ParserCombinators.Parsec.SourcePos').------ The big deal here is that we can embed a parser for some scripting language,--- (e.g. Javascript) into this HTML parser with ease, while preserving source--- locations. The Html datatype is parameterized over a script parser (an--- instance of Script).-class Script t where- prettyPrintScript :: t -> Doc- parseScriptBlock:: [Attribute SourcePos t] -> CharParser a t- -- An inline script parser, which may be Nothing if the scripting language- -- does not support inline scripts.- parseInlineScript:: Maybe (CharParser a t)- -- A parser for script-expressions defined inline as attribute values.- parseAttributeScript:: Maybe (CharParser a t)- ------------------------------------------------------------------------------------ HTML navigation--isAttributeExpr (AttributeExpr _ _ _ _) = True-isAttributeExpr _ = False---- |Returns the value of the attribute in the list, or 'Nothing' if it doesn't--- exist of the value is an inline-expression.-attributeValue:: HtmlId -> [Attribute a s] -> Maybe String-attributeValue name [] = Nothing-attributeValue name ((AttributeExpr pos name' expr init):rest) =- if name == name' then Nothing- else attributeValue name rest-attributeValue name ((Attribute name' value _):rest) =- if name == name' then Just value- else attributeValue name rest--attributeSet:: HtmlId -> String -> [Attribute a s] -> [Attribute a s]-attributeSet n v attrs = attributeUpdate n (\_ -> v) attrs--attributeUpdate:: HtmlId -> (String -> String) -> [Attribute a s] - -> [Attribute a s]-attributeUpdate n f [] = - [Attribute n (f "") (error "attributeUpdate--no value")] -- TODO: undefined?!-attributeUpdate n _ ((AttributeExpr _ _ _ _):_) =- error $ "attributeUpdate: " ++ n ++ " is an expression-attribute."-attributeUpdate n f ((Attribute n' v p):attrs) =- if n' == n then (Attribute n (f v) p):attrs- else (Attribute n' v p):(attributeUpdate n f attrs)-
src/BrownPLT/JavaScript.hs view
@@ -1,7 +1,6 @@ -- |Re-exports commonly used modules. module BrownPLT.JavaScript ( module BrownPLT.JavaScript.Syntax- , module BrownPLT.JavaScript.HtmlEmbedding , module BrownPLT.JavaScript.Parser -- JavaScript.Instances exports nothing , renderStatements@@ -12,6 +11,3 @@ import BrownPLT.JavaScript.Syntax import BrownPLT.JavaScript.Parser import BrownPLT.JavaScript.PrettyPrint-import BrownPLT.JavaScript.HtmlEmbedding--import BrownPLT.JavaScript.Instances
− src/BrownPLT/JavaScript/Crawl.hs
@@ -1,102 +0,0 @@--- |Crawls an HTML page for JavaScript-module BrownPLT.JavaScript.Crawl - ( getPageJavaScript- ) where--import Control.Monad-import Data.List-import Data.Char (toLower)-import Data.Generics-import System.IO-import Text.ParserCombinators.Parsec.Pos (SourcePos, sourceName)-import Text.ParserCombinators.Parsec(parse,setPosition,incSourceColumn,Column,sourceLine,sourceColumn)--import BrownPLT.Html.Syntax-import qualified BrownPLT.JavaScript as Js---instance Typeable SourcePos where- typeOf _ = - mkTyConApp (mkTyCon "Text.ParserCombinators.Parsec.Pos.SourcePos") []-- --- Complete guesswork. It seems to work.--- This definition is incomplete.-instance Data SourcePos where- -- We treat source locations as opaque. After all, we don't have access to- -- the constructor.- gfoldl k z pos = z pos- toConstr _ = sourcePosConstr1 where- sourcePosConstr1 = mkConstr sourcePosDatatype "SourcePos" [] Prefix- sourcePosDatatype = mkDataType "SourcePos" [sourcePosConstr1]- gunfold = error "gunfold is not defined for SourcePos"- dataTypeOf = error "dataTypeOf is not defined for SourcePos"----- |Returns the source of the script.-scriptSrc:: Js.ParsedJsHtml -> [String]-scriptSrc (Element tag attrs _ _) | (map toLower tag) == "script" =- case attributeValue "src" attrs of -- TODO: Check for type="javascript"?- Just "" -> []- Just url -> [url]- Nothing -> []-scriptSrc _ =- []----- |Returns a list of URIs for external Javascript files referenced in the page.-importedScripts:: Js.ParsedJsHtml -> [String]-importedScripts = everything (++) (mkQ [] scriptSrc)---- |Returns the top-level statements of a script.-scriptText :: Js.ParsedJsHtml -> [Js.ParsedStatement]-scriptText (Script (Js.Script _ stmts) _) = stmts-scriptText _ = []--eventHandlers :: [String]-eventHandlers = ["onload","onclick"]; --- ,"onmousemove","onmouseover","onmousedown","onmouseout","onmouseup","onselectstart", "onkeypress"]--attrScript :: Attribute SourcePos Js.ParsedJavaScript - -> IO [Js.ParsedStatement]-attrScript (Attribute id val loc) | id `elem` eventHandlers = do- let eventId = drop 2 id -- drop the "on" prefix- let scriptText = if "javascript:" `isPrefixOf` val then drop 11 val else val- let eventListenerPrefix = "addEventListener('" ++ eventId ++ "', function(event) { "- let prefixLen = length eventListenerPrefix- let eventListenerText = eventListenerPrefix ++ scriptText ++ " });"- let parser = do- setPosition (incSourceColumn loc (-prefixLen))- Js.parseExpression- case parse parser (sourceName loc) eventListenerText of- Left err -> do- fail $ "Error parsiing JavaScript in an attribute at " ++ show loc ++- "\nThe script was:\n\n" ++ eventListenerText- Right e -> return [Js.ExprStmt loc e]-attrScript _ = return []--inpageAttrScripts :: Js.ParsedJsHtml -> IO [Js.ParsedStatement]-inpageAttrScripts = everything (liftM2 (++)) (mkQ (return []) attrScript)--inpageScripts :: Js.ParsedJsHtml -> [Js.ParsedStatement]-inpageScripts = everything (++) (mkQ [] scriptText)--parseJsFile path = do- text <- readFile path- case Js.parseScriptFromString path text of- Left err -> fail (show err)- Right js -> hPutStrLn stderr ("Read file " ++ path) >> return js---- |Given an HTML page, crawls all external Javascript files and returns a list--- of statements, concatenated from all files.-getPageJavascript:: Js.ParsedJsHtml -> IO [Js.ParsedStatement]-getPageJavascript page = do- let importURIs = importedScripts page- let inpageJs = inpageScripts page- attrScripts <- inpageAttrScripts page- importedScripts <- mapM parseJsFile importURIs- let unScript (Js.Script _ ss) = ss- return $ (concatMap unScript importedScripts ++ attrScripts) ++ inpageJs--getPageJavaScript:: Js.ParsedJsHtml -> IO [Js.ParsedStatement] -- monomorphism-getPageJavaScript = getPageJavascript
src/BrownPLT/JavaScript/Environment.hs view
@@ -43,6 +43,13 @@ javascript :: JavaScript SourcePos -> Partial javascript (Script _ ss) = unions (map stmt ss) ++lvalue :: LValue SourcePos -> Partial+lvalue lv = case lv of+ LVar p x -> ref (Id p x)+ LDot _ e _ -> expr e+ LBracket _ e1 e2 -> unions [expr e1, expr e2]+ expr :: Expression SourcePos -> Partial expr e = case e of StringLit _ _ -> empty@@ -58,16 +65,15 @@ DotRef _ e _ -> expr e BracketRef _ e1 e2 -> unions [expr e1, expr e2] NewExpr _ e1 es -> unions [expr e1, unions $ map expr es]- PostfixExpr _ _ e -> expr e PrefixExpr _ _ e -> expr e InfixExpr _ _ e1 e2 -> unions [expr e1, expr e2] CondExpr _ e1 e2 e3 -> unions [expr e1, expr e2, expr e3]- AssignExpr _ _ (VarRef _ id) e -> unions [ref id, expr e]- AssignExpr _ _ e1 e2 -> unions [expr e1, expr e2]+ AssignExpr _ _ lv e -> unions [lvalue lv, expr e]+ UnaryAssignExpr _ _ lv -> lvalue lv ParenExpr _ e -> expr e ListExpr _ es -> unions (map expr es) CallExpr _ e es -> unions [expr e, unions $ map expr es]- FuncExpr _ args s -> nest $ unions [unions $ map decl args, stmt s]+ FuncExpr _ _ args s -> nest $ unions [unions $ map decl args, stmt s] caseClause :: CaseClause SourcePos -> Partial caseClause cc = case cc of@@ -108,8 +114,8 @@ ForInStmt _ fii e s -> unions [forInInit fii, expr e, stmt s] ForStmt _ fi me1 me2 s -> unions [forInit fi, maybe empty expr me1, maybe empty expr me2, stmt s]- TryStmt _ s catches ms ->- unions [stmt s, unions $ map catchClause catches, maybe empty stmt ms]+ TryStmt _ s catch ms ->+ unions [stmt s, maybe empty catchClause catch, maybe empty stmt ms] ThrowStmt _ e -> expr e ReturnStmt _ me -> maybe empty expr me WithStmt _ e s -> unions [expr e, stmt s]
− src/BrownPLT/JavaScript/HtmlEmbedding.hs
@@ -1,25 +0,0 @@-module BrownPLT.JavaScript.HtmlEmbedding- ( JsHtml- , ParsedJavaScript- , ParsedJsHtml- ) where--import BrownPLT.Html.Syntax-import BrownPLT.JavaScript.Parser (parseScript)-import BrownPLT.JavaScript.Syntax (JavaScript)-import BrownPLT.JavaScript.PrettyPrint (javaScript)-import Text.ParserCombinators.Parsec (SourcePos)--type JsHtml a = Html SourcePos (JavaScript a)--type ParsedJavaScript = JavaScript SourcePos--type ParsedJsHtml = JsHtml SourcePos--instance Script ParsedJavaScript where- prettyPrintScript s = javaScript s- parseScriptBlock attrs = parseScript- parseInlineScript = Nothing- parseAttributeScript = Nothing- -
− src/BrownPLT/JavaScript/Instances.hs
@@ -1,294 +0,0 @@--- |Instances of 'Foldable' and 'Traversable' for JavaScript's syntax.-module BrownPLT.JavaScript.Instances- ( -- This module does not export any names.- ) where--import Prelude hiding (foldr,sequence,mapM)-import qualified Prelude as Prelude--import Data.Foldable (Foldable(..))-import Data.Traversable(Traversable(..))-import Control.Applicative--import BrownPLT.JavaScript.Syntax--yfoldr:: Foldable t => (a -> b -> b) -> b -> Maybe (t a) -> b-yfoldr _ b Nothing = b-yfoldr f b (Just t) = foldr f b t--lfoldr:: Foldable t => (a -> b -> b) -> b -> [t a] -> b-lfoldr f = Prelude.foldr (flip $ foldr f)--ltraverse:: (Traversable t, Applicative f) => (a -> f b) -> [t a] -> f [t b]-ltraverse _ [] = pure []-ltraverse f (a:as) = (:) <$> traverse f a <*> ltraverse f as--ytraverse:: (Traversable t, Applicative f) - => (a -> f b) -> Maybe (t a) -> f (Maybe (t b))-ytraverse _ Nothing = pure Nothing-ytraverse f (Just t) = Just <$> traverse f t--instance Functor Id where- fmap f (Id a v) = Id (f a) v--instance Functor JavaScript where- fmap f (Script a stmts) = Script (f a) (map (fmap f) stmts)- -instance Functor Prop where- fmap f (PropId a id) = PropId (f a) (fmap f id)- fmap f (PropString a s) = PropString (f a) s- fmap f (PropNum a n) = PropNum (f a) n--instance Functor Expression where- fmap f expression = - case expression of- StringLit a s -> StringLit (f a) s- RegexpLit a s g ci -> RegexpLit (f a) s g ci- NumLit a n -> NumLit (f a) n- IntLit a n -> IntLit (f a) n- BoolLit a b -> BoolLit (f a) b- NullLit a -> NullLit (f a)- ArrayLit a es -> ArrayLit (f a) (map (fmap f) es)- ObjectLit a pes -> ObjectLit (f a) (map f' pes) where- f' (p,e) = (fmap f p, fmap f e)- ThisRef a -> ThisRef (f a)- VarRef a id -> VarRef (f a) (fmap f id)- DotRef a e id -> DotRef (f a) (fmap f e) (fmap f id)- BracketRef a e1 e2 -> BracketRef (f a) (fmap f e1) (fmap f e2)- NewExpr a e es -> NewExpr (f a) (fmap f e) (map (fmap f) es)- PostfixExpr a op e -> PostfixExpr (f a) op (fmap f e)- PrefixExpr a op e -> PrefixExpr (f a) op (fmap f e)- InfixExpr a op e1 e2 -> InfixExpr (f a) op (fmap f e1) (fmap f e2)- CondExpr a e1 e2 e3 -> CondExpr (f a) (fmap f e1) (fmap f e2) (fmap f e3)- AssignExpr a op e1 e2 -> AssignExpr (f a) op (fmap f e1) (fmap f e2)- ParenExpr a e -> ParenExpr (f a) (fmap f e)- ListExpr a es -> ListExpr (f a) (map (fmap f) es)- CallExpr a e es -> CallExpr (f a) (fmap f e) (map (fmap f) es)- FuncExpr a args s -> FuncExpr (f a) (map (fmap f) args) (fmap f s)--instance Functor CaseClause where- fmap f (CaseClause a e ss) = CaseClause (f a) (fmap f e) (map (fmap f) ss)- fmap f (CaseDefault a ss) = CaseDefault (f a) (map (fmap f) ss)- -instance Functor CatchClause where- fmap f (CatchClause a id s) = CatchClause (f a) (fmap f id) (fmap f s)--instance Functor VarDecl where- fmap f (VarDecl a id Nothing) = VarDecl (f a) (fmap f id) Nothing- fmap f (VarDecl a id (Just e)) = VarDecl (f a) (fmap f id) (Just $ fmap f e)- -instance Functor ForInit where- fmap f NoInit = NoInit- fmap f (VarInit decls) = VarInit (map (fmap f) decls)- fmap f (ExprInit e) = ExprInit (fmap f e)--instance Functor ForInInit where- fmap f (ForInVar id) = ForInVar (fmap f id)- fmap f (ForInNoVar id) = ForInNoVar (fmap f id)- -instance Functor Statement where- fmap f s = - case s of- BlockStmt a ss -> BlockStmt (f a) (map (fmap f) ss)- EmptyStmt a -> EmptyStmt (f a)- ExprStmt a e -> ExprStmt (f a) (fmap f e)- IfStmt a e s1 s2 -> IfStmt (f a) (fmap f e) (fmap f s1) (fmap f s2)- IfSingleStmt a e s -> IfSingleStmt (f a) (fmap f e) (fmap f s)- SwitchStmt a e cs -> SwitchStmt (f a) (fmap f e) (map (fmap f) cs)- WhileStmt a e s -> WhileStmt (f a) (fmap f e) (fmap f s)- DoWhileStmt a s e -> DoWhileStmt (f a) (fmap f s) (fmap f e)- BreakStmt a Nothing -> BreakStmt (f a) Nothing- BreakStmt a (Just id) -> BreakStmt (f a) (Just (fmap f id))- ContinueStmt a yid -> ContinueStmt (f a) (yid >>= return.(fmap f))- LabelledStmt a id s -> LabelledStmt (f a) (fmap f id) (fmap f s)- ForInStmt a init e s -> ForInStmt (f a) (fmap f init) (fmap f e)- (fmap f s)- ForStmt a init yinc ytest body -> - ForStmt (f a) (fmap f init) (yinc >>= return.(fmap f))- (ytest >>= return.(fmap f)) (fmap f body)- TryStmt a s cs ys -> - TryStmt (f a) (fmap f s) (map (fmap f) cs) (ys >>= return.(fmap f))- ThrowStmt a e -> ThrowStmt (f a) (fmap f e)- ReturnStmt a ye -> ReturnStmt (f a) (ye >>= return.(fmap f))- WithStmt a e s -> WithStmt (f a) (fmap f e) (fmap f s)- VarDeclStmt a ds -> VarDeclStmt (f a) (map (fmap f) ds)- FunctionStmt a id args s -> - FunctionStmt (f a) (fmap f id) (map (fmap f) args) (fmap f s)--instance Foldable Id where- foldr f b (Id a _) = f a b--instance Foldable Prop where- foldr f b (PropId a id) = f a (foldr f b id)- foldr f b (PropString a _) = f a b- foldr f b (PropNum a _) = f a b- -instance Foldable Expression where- -- foldr:: (a -> b -> b) -> b -> Expression a -> b- foldr f b e =- case e of- StringLit a _ -> f a b- RegexpLit a _ _ _ -> f a b- NumLit a _ -> f a b- IntLit a _ -> f a b- BoolLit a _ -> f a b- NullLit a -> f a b- ArrayLit a es -> f a (Prelude.foldr (flip $ foldr f) b es)- ObjectLit a pes -> f a (Prelude.foldr f' b pes) where- f' (p,e) b = foldr f (foldr f b e) p- ThisRef a -> f a b- VarRef a id -> f a (foldr f b id)- DotRef a e id -> f a (foldr f (foldr f b id) e)- BracketRef a e1 e2 -> f a (foldr f (foldr f b e2) e1)- NewExpr a e es -> f a (foldr f (Prelude.foldr (flip $ foldr f) b es) e)- PostfixExpr a _ e -> f a $ foldr f b e- PrefixExpr a _ e -> f a $ foldr f b e- InfixExpr a _ e1 e2 -> f a $ foldr f (foldr f b e2) e1- CondExpr a e1 e2 e3 -> f a $ foldr f (foldr f (foldr f b e3) e2) e1- AssignExpr a _ e1 e2 -> f a $ foldr f (foldr f b e2) e1- ParenExpr a e -> f a $ foldr f b e- ListExpr a es -> f a $ Prelude.foldr (flip $ foldr f) b es- CallExpr a e es -> f a $ foldr f (Prelude.foldr (flip $ foldr f) b es) e- FuncExpr a args s -> - f a $ Prelude.foldr (flip $ foldr f) (foldr f b s) args--instance Foldable CaseClause where- foldr f b (CaseClause a e ss) = - f a $ foldr f (Prelude.foldr (flip $ foldr f) b ss) e- foldr f b (CaseDefault a ss) = f a $ Prelude.foldr (flip $ foldr f) b ss- -instance Foldable CatchClause where- foldr f b (CatchClause a id s) = f a $ foldr f (foldr f b s) id--instance Foldable VarDecl where- foldr f b (VarDecl a id ye) = f a $ foldr f (yfoldr f b ye) id--instance Foldable ForInit where- foldr f b NoInit = b- foldr f b (VarInit ds) = Prelude.foldr (flip $ foldr f) b ds- foldr f b (ExprInit e) = foldr f b e--instance Foldable ForInInit where- foldr f b (ForInVar id) = foldr f b id- foldr f b (ForInNoVar id) = foldr f b id--instance Foldable Statement where- foldr f b statement =- case statement of- BlockStmt a ss -> f a $ lfoldr f b ss- EmptyStmt a -> f a b- ExprStmt a e -> f a $ foldr f b e- IfStmt a e s1 s2 -> f a $ foldr f (foldr f (foldr f b s2) s1) e- IfSingleStmt a e s -> f a $ foldr f (foldr f b s) e- SwitchStmt a e cs -> f a $ foldr f (lfoldr f b cs) e- WhileStmt a e s -> f a $ foldr f (foldr f b s) e- DoWhileStmt a s e -> f a $ foldr f (foldr f b e) s- BreakStmt a yid -> f a $ yfoldr f b yid- ContinueStmt a yid -> f a $ yfoldr f b yid- LabelledStmt a id s -> f a $ foldr f (foldr f b s) id- ForInStmt a init e s -> f a $ foldr f (foldr f (foldr f b s) e) init- ForStmt a init ye1 ye2 s ->- f a $ foldr f (yfoldr f (yfoldr f (foldr f b s) ye2) ye1) init- TryStmt a s cs ys -> f a $ foldr f (lfoldr f (yfoldr f b ys) cs) s- ThrowStmt a e -> f a $ foldr f b e- ReturnStmt a ys -> f a $ yfoldr f b ys- WithStmt a e s -> f a $ foldr f (foldr f b s) e- VarDeclStmt a ds -> f a $ lfoldr f b ds- FunctionStmt a id args s ->- f a $ lfoldr f (foldr f b s) (id:args)--instance Traversable Id where- traverse f (Id a v) = Id <$> f a <*> pure v--instance Traversable Prop where- traverse f (PropId a id) = PropId <$> f a <*> traverse f id- traverse f (PropString a s) = PropString <$> f a <*> pure s- traverse f (PropNum a n) = PropNum <$> f a <*> pure n- -instance Traversable Expression where- traverse f expression =- case expression of- StringLit a s -> StringLit <$> f a <*> pure s- RegexpLit a s g ci -> RegexpLit <$> f a <*> pure s <*> pure g <*> pure ci- NumLit a n -> NumLit <$> f a <*> pure n- IntLit a n -> IntLit <$> f a <*> pure n- BoolLit a b -> BoolLit <$> f a <*> pure b- NullLit a -> NullLit <$> f a- ArrayLit a es -> ArrayLit <$> f a <*> ltraverse f es- ObjectLit a ps -> ObjectLit <$> f a <*> (zip <$> props' <*> es') where- (props,es) = unzip ps- props' = ltraverse f props- es' = ltraverse f es- ThisRef a -> ThisRef <$> f a- VarRef a id -> VarRef <$> f a <*> traverse f id- DotRef a e id -> DotRef <$> f a <*> traverse f e <*> traverse f id- BracketRef a e es -> BracketRef <$> f a <*> traverse f e <*> traverse f es- NewExpr a e es -> NewExpr <$> f a <*> traverse f e <*> ltraverse f es- PostfixExpr a op e -> PostfixExpr <$> f a <*> pure op <*> traverse f e- PrefixExpr a op e -> PrefixExpr <$> f a <*> pure op <*> traverse f e- InfixExpr a op e1 e2 -> InfixExpr <$> f a <*> pure op <*> traverse f e1- <*> traverse f e2- CondExpr a e1 e2 e3 ->- CondExpr <$> f a <*> traverse f e1 <*> traverse f e2 <*> traverse f e3- AssignExpr a op e1 e2 -> AssignExpr <$> f a <*> pure op <*> traverse f e1- <*> traverse f e2- ParenExpr a e -> ParenExpr <$> f a <*> traverse f e- ListExpr a es -> ListExpr <$> f a <*> ltraverse f es- CallExpr a e es -> CallExpr <$> f a <*> traverse f e <*> ltraverse f es- FuncExpr a ids s -> FuncExpr <$> f a <*> ltraverse f ids <*> traverse f s--instance Traversable CaseClause where- traverse f (CaseClause a e ss) =- CaseClause <$> f a <*> traverse f e <*> ltraverse f ss- traverse f (CaseDefault a ss) = - CaseDefault <$> f a <*> ltraverse f ss--instance Traversable CatchClause where- traverse f (CatchClause a id s) = - CatchClause <$> f a <*> traverse f id <*> traverse f s- -instance Traversable VarDecl where- traverse f (VarDecl a id ye) =- VarDecl <$> f a <*> traverse f id <*> ytraverse f ye--instance Traversable ForInit where- traverse f NoInit = pure NoInit- traverse f (VarInit ds) = VarInit <$> ltraverse f ds- traverse f (ExprInit e) = ExprInit <$> traverse f e--instance Traversable ForInInit where- traverse f (ForInVar id) = ForInVar <$> traverse f id- traverse f (ForInNoVar id) = ForInNoVar <$> traverse f id--instance Traversable Statement where- traverse f statement =- case statement of- BlockStmt a ss -> BlockStmt <$> f a <*> ltraverse f ss- EmptyStmt a -> EmptyStmt <$> f a- ExprStmt a e -> ExprStmt <$> f a <*> traverse f e- IfStmt a e s1 s2 ->- IfStmt <$> f a <*> traverse f e <*> traverse f s1 <*> traverse f s2- IfSingleStmt a e s ->- IfSingleStmt <$> f a <*> traverse f e <*> traverse f s- SwitchStmt a e cs ->- SwitchStmt <$> f a <*> traverse f e <*> ltraverse f cs- WhileStmt a e s -> WhileStmt <$> f a <*> traverse f e <*> traverse f s- DoWhileStmt a s e -> DoWhileStmt <$> f a <*> traverse f s <*> traverse f e- BreakStmt a yid -> BreakStmt <$> f a <*> ytraverse f yid- ContinueStmt a yid -> ContinueStmt <$> f a <*> ytraverse f yid- LabelledStmt a id s -> - LabelledStmt <$> f a <*> traverse f id <*> traverse f s- ForInStmt a init e s ->- ForInStmt <$> f a <*> traverse f init <*> traverse f e <*> traverse f s- ForStmt a init yinc ytest s ->- ForStmt <$> f a <*> traverse f init <*> ytraverse f yinc - <*> ytraverse f ytest <*> traverse f s- TryStmt a s cs ys ->- TryStmt <$> f a <*> traverse f s <*> ltraverse f cs <*> ytraverse f ys- ThrowStmt a e -> ThrowStmt <$> f a <*> traverse f e- ReturnStmt a ys -> ReturnStmt <$> f a <*> ytraverse f ys- WithStmt a e s -> WithStmt <$> f a <*> traverse f e <*> traverse f s- VarDeclStmt a ds -> VarDeclStmt <$> f a <*> ltraverse f ds- FunctionStmt a id args s ->- FunctionStmt <$> f a <*> traverse f id <*> ltraverse f args - <*> traverse f s
src/BrownPLT/JavaScript/Lexer.hs view
@@ -18,7 +18,6 @@ "*/" "//" False -- no nested comments- {- Adapted from syntax/regexps.ss in Dave's code. -} identifierStart (alphaNum <|> oneOf "$_") -- identifier rest (oneOf "{}<>()~.,?:|&^=!+-*/%!") -- operator start@@ -35,6 +34,7 @@ "[", "]", "{", "}", "(", ")","</","instanceof"] True -- case-sensitive +lex :: T.TokenParser st lex = T.makeTokenParser javascriptDef -- everything but commaSep and semiSep
src/BrownPLT/JavaScript/Parser.hs view
@@ -12,7 +12,7 @@ , parseStatement , StatementParser , ExpressionParser- , parseAssignExpr+ , assignExpr ) where import BrownPLT.JavaScript.Lexer hiding (identifier)@@ -35,6 +35,7 @@ type StatementParser state = CharParser state ParsedStatement type ExpressionParser state = CharParser state ParsedExpression +identifier :: CharParser st (Id SourcePos) identifier = liftM2 Id getPosition Lexer.identifier @@ -197,10 +198,10 @@ in do reserved "try" pos <- getPosition guarded <- parseStatement- catches <- many parseCatchClause+ catch <- optionMaybe parseCatchClause finally <- (reserved "finally" >> liftM Just parseStatement) <|> (return Nothing)- return (TryStmt pos guarded catches finally)+ return (TryStmt pos guarded catch finally) parseThrowStmt:: StatementParser st parseThrowStmt = do@@ -302,20 +303,21 @@ parseVarRef = liftM2 VarRef getPosition identifier parseArrayLit:: ExpressionParser st-parseArrayLit = liftM2 ArrayLit getPosition (squares (parseExpression `sepBy` comma))+parseArrayLit = liftM2 ArrayLit getPosition (squares (parseExpression `sepEndBy` comma)) parseFuncExpr = do pos <- getPosition reserved "function"+ name <- (identifier >>= return . Just) <|> return Nothing args <- parens (identifier `sepBy` comma) body <- parseBlockStmt- return $ FuncExpr pos args body+ return $ FuncExpr pos name args body --{{{ parsing strings escapeChars = [('\'','\''),('\"','\"'),('\\','\\'),('b','\b'),('f','\f'),('n','\n'),- ('r','\r'),('t','\t'),('v','\v'),('/','/'),(' ',' ')]+ ('r','\r'),('t','\t'),('v','\v'),('/','/'),(' ',' '),('0','\0')] allEscapes:: String allEscapes = map fst escapeChars@@ -375,8 +377,10 @@ let parseFlags = do flags <- many (oneOf "mgi") return $ \f -> f ('g' `elem` flags) ('i' `elem` flags) - let parseEscape = char '\\' >> anyChar- let parseChar = noneOf "/"+ let parseEscape :: CharParser st Char+ parseEscape = char '\\' >> anyChar+ let parseChar :: CharParser st Char+ parseChar = noneOf "/" let parseRe = (char '/' >> return "") <|> (do char '\\' ch <- anyChar -- TOOD: too lenient@@ -401,7 +405,7 @@ <|> (liftM2 PropId getPosition identifier) <|> (liftM2 PropNum getPosition decimal) colon- val <- parseAssignExpr+ val <- assignExpr return (name,val) in do pos <- getPosition props <- braces (parseProp `sepEndBy` comma) <?> "object literal"@@ -520,35 +524,8 @@ reservedOp str return (InfixExpr pos constr) -- points-free, returns a function -makePrefixExpr str constr = Prefix parser where- parser = do- pos <- getPosition- (reservedOp str <|> reserved str)- return (PrefixExpr pos constr) -- points-free, returns a function- -mkPrefix operator constr = Prefix $ do- pos <- getPosition- operator- return (\operand -> PrefixExpr pos constr operand) -makePostfixExpr str constr = Postfix parser where- parser = do- pos <- getPosition- (reservedOp str <|> reserved str)- return (PostfixExpr pos constr) -- points-free, returns a function--prefixIncDecExpr = do- pos <- getPosition- op <- optionMaybe $ (reservedOp "++" >> return PrefixInc) <|>- (reservedOp "--" >> return PrefixDec)- case op of- Nothing -> parseSimpleExpr Nothing- Just op -> do- innerExpr <- parseSimpleExpr Nothing -- TODO: must be an l-val, I think- return (PrefixExpr pos op innerExpr)- -- apparently, expression tables can't handle immediately-nested prefixes- parsePrefixedExpr = do pos <- getPosition op <- optionMaybe $ (reservedOp "!" >> return PrefixLNot) <|> @@ -561,45 +538,98 @@ (reserved "void" >> return PrefixVoid) <|> (reserved "delete" >> return PrefixDelete) case op of- Nothing -> prefixIncDecExpr -- new is treated as a simple expr+ Nothing -> unaryAssignExpr Just op -> do innerExpr <- parsePrefixedExpr return (PrefixExpr pos op innerExpr) exprTable:: [[Operator Char st ParsedExpression]] exprTable = - [- [makePrefixExpr "++" PrefixInc,- makePostfixExpr "++" PostfixInc],- [makePrefixExpr "--" PrefixDec,- makePostfixExpr "--" PostfixDec],- [makeInfixExpr "*" OpMul, makeInfixExpr "/" OpDiv, makeInfixExpr "%" OpMod],- [makeInfixExpr "+" OpAdd, makeInfixExpr "-" OpSub],- [makeInfixExpr "<<" OpLShift, makeInfixExpr ">>" OpSpRShift,- makeInfixExpr ">>>" OpZfRShift],- [makeInfixExpr "<" OpLT, makeInfixExpr "<=" OpLEq, makeInfixExpr ">" OpGT,- makeInfixExpr ">=" OpGEq, - makeInfixExpr "instanceof" OpInstanceof, makeInfixExpr "in" OpIn],- [makeInfixExpr "&" OpBAnd], - [makeInfixExpr "^" OpBXor], - [makeInfixExpr "|" OpBOr],- [makeInfixExpr "&&" OpLAnd],- [makeInfixExpr "||" OpLOr], - [makeInfixExpr "==" OpEq, makeInfixExpr "!=" OpNEq,- makeInfixExpr "===" OpStrictEq, makeInfixExpr "!==" OpStrictNEq]+ [ [ makeInfixExpr "==" OpEq+ , makeInfixExpr "!=" OpNEq+ , makeInfixExpr "===" OpStrictEq+ , makeInfixExpr "!==" OpStrictNEq ]++ , [ makeInfixExpr "||" OpLOr ]++ , [ makeInfixExpr "&&" OpLAnd ] + , [ makeInfixExpr "|" OpBOr ]++ , [ makeInfixExpr "^" OpBXor ]++ , [ makeInfixExpr "&" OpBAnd ]++ , [ makeInfixExpr "<" OpLT+ , makeInfixExpr "<=" OpLEq+ , makeInfixExpr ">" OpGT+ , makeInfixExpr ">=" OpGEq+ , makeInfixExpr "instanceof" OpInstanceof+ , makeInfixExpr "in" OpIn+ ]++ , [ makeInfixExpr "<<" OpLShift+ , makeInfixExpr ">>" OpSpRShift+ , makeInfixExpr ">>>" OpZfRShift+ ]++ , [ makeInfixExpr "+" OpAdd+ , makeInfixExpr "-" OpSub+ ]++ , [ makeInfixExpr "*" OpMul+ , makeInfixExpr "/" OpDiv+ , makeInfixExpr "%" OpMod+ ]+ ]+ parseExpression' = buildExpressionParser exprTable parsePrefixedExpr <?> "simple expression" ---{{{ Parsing ternary operators: left factored+asLValue :: SourcePos+ -> Expression SourcePos + -> CharParser st (LValue SourcePos)+asLValue p' e = case e of+ VarRef p (Id _ x) -> return (LVar p x)+ DotRef p e (Id _ x) -> return (LDot p e x)+ BracketRef p e1 e2 -> return (LBracket p e1 e2)+ otherwise -> fail $ "expeceted l-value at " ++ show p' +lvalue :: CharParser st (LValue SourcePos)+lvalue = do+ p <- getPosition+ e <- parseSimpleExpr Nothing+ asLValue p e+++unaryAssignExpr :: CharParser st ParsedExpression+unaryAssignExpr = do+ p <- getPosition+ let prefixInc = do+ reservedOp "++"+ liftM (UnaryAssignExpr p PrefixInc) lvalue+ let prefixDec = do+ reservedOp "--"+ liftM (UnaryAssignExpr p PrefixDec) lvalue+ let postfixInc e = do+ reservedOp "++"+ liftM (UnaryAssignExpr p PostfixInc) (asLValue p e)+ let postfixDec e = do+ reservedOp "--"+ liftM (UnaryAssignExpr p PostfixDec) (asLValue p e)+ let other = do+ e <- parseSimpleExpr Nothing+ postfixInc e <|> postfixDec e <|> return e+ prefixInc <|> prefixDec <|> other++ parseTernaryExpr':: CharParser st (ParsedExpression,ParsedExpression) parseTernaryExpr' = do reservedOp "?"- l <- parseAssignExpr+ l <- assignExpr colon- r <- parseAssignExpr+ r <- assignExpr return $(l,r) parseTernaryExpr:: ExpressionParser st@@ -610,37 +640,43 @@ Nothing -> return e Just (l,r) -> do p <- getPosition return $ CondExpr p e l r---}}} --- Parsing assignment operations.-makeAssignExpr str constr = Infix parser AssocRight where- parser:: CharParser st (ParsedExpression -> ParsedExpression -> ParsedExpression)- parser = do- pos <- getPosition- reservedOp str- return (AssignExpr pos constr) -assignTable:: [[Operator Char st ParsedExpression]]-assignTable = [- [makeAssignExpr "=" OpAssign, makeAssignExpr "+=" OpAssignAdd, - makeAssignExpr "-=" OpAssignSub, makeAssignExpr "*=" OpAssignMul,- makeAssignExpr "/=" OpAssignDiv, makeAssignExpr "%=" OpAssignMod,- makeAssignExpr "<<=" OpAssignLShift, makeAssignExpr ">>=" OpAssignSpRShift,- makeAssignExpr ">>>=" OpAssignZfRShift, makeAssignExpr "&=" OpAssignBAnd,- makeAssignExpr "^=" OpAssignBXor, makeAssignExpr "|=" OpAssignBOr- ]]+assignOp :: CharParser st AssignOp+assignOp = + (reservedOp "=" >> return OpAssign) <|>+ (reservedOp "+=" >> return OpAssignAdd) <|>+ (reservedOp "-=" >> return OpAssignSub) <|>+ (reservedOp "*=" >> return OpAssignMul) <|>+ (reservedOp "/=" >> return OpAssignDiv) <|>+ (reservedOp "%=" >> return OpAssignMod) <|>+ (reservedOp "<<=" >> return OpAssignLShift) <|>+ (reservedOp ">>=" >> return OpAssignSpRShift) <|>+ (reservedOp ">>>=" >> return OpAssignZfRShift) <|>+ (reservedOp "&=" >> return OpAssignBAnd) <|>+ (reservedOp "^=" >> return OpAssignBXor) <|>+ (reservedOp "|=" >> return OpAssignBOr) -parseAssignExpr:: ExpressionParser st-parseAssignExpr = buildExpressionParser assignTable parseTernaryExpr +assignExpr :: ExpressionParser st+assignExpr = do+ p <- getPosition+ lhs <- parseTernaryExpr+ let assign = do+ op <- assignOp+ lhs <- asLValue p lhs+ rhs <- assignExpr+ return (AssignExpr p op lhs rhs)+ assign <|> (return lhs) + parseExpression:: ExpressionParser st-parseExpression = parseAssignExpr+parseExpression = assignExpr + parseListExpr =- liftM2 ListExpr getPosition (parseAssignExpr `sepBy1` comma)+ liftM2 ListExpr getPosition (assignExpr `sepBy1` comma) ---}}} parseScript:: CharParser state (JavaScript SourcePos) parseScript = do
src/BrownPLT/JavaScript/PrettyPrint.hs view
@@ -57,8 +57,10 @@ text "default:" $$ (nest 2 (semiSep ss)) -catchClause :: CatchClause a -> Doc-catchClause (CatchClause _ id s) = text "catch" <+> (parens.pp) id <+> inBlock s+catchClause :: Maybe (CatchClause a) -> Doc+catchClause Nothing = empty+catchClause (Just (CatchClause _ id s)) = + text "catch" <+> (parens.pp) id <+> inBlock s varDecl :: VarDecl a -> Doc@@ -93,8 +95,8 @@ text "for" <+> parens (forInit init <> semi <+> mexpr incr <> semi <+> mexpr test) $$ stmt body- TryStmt _ stmt catches finally ->- text "try" $$ inBlock stmt $$ (vcat (map catchClause catches)) $$+ TryStmt _ stmt catch finally ->+ text "try" $$ inBlock stmt $$ catchClause catch $$ ppFinally where ppFinally = case finally of Nothing -> empty@@ -143,8 +145,6 @@ prefixOp op = text $ case op of- PrefixInc -> "++"- PrefixDec -> "--" PrefixLNot -> "!" PrefixBNot -> "~" PrefixPlus -> "+"@@ -154,11 +154,6 @@ PrefixDelete -> "delete" -postfixOp op = text $ case op of- PostfixInc -> "++"- PostfixDec -> "--"-- assignOp op = text $ case op of OpAssign -> "=" OpAssignAdd -> "+="@@ -191,6 +186,12 @@ sel x = [x] -- We don't have to do anything about \X, \x and \u escape sequences. ++lvalue :: LValue a -> Doc+lvalue (LVar _ x) = text x+lvalue (LDot _ e x) = expr e <> text "." <> text x+lvalue (LBracket _ e1 e2) = expr e1 <> brackets (expr e2)+ expr :: Expression a -> Doc expr e = case e of @@ -216,17 +217,21 @@ text "new" <+> expr constr <> (parens $ cat $ punctuate comma (map expr args)) PrefixExpr _ op e' -> prefixOp op <+> expr e'- PostfixExpr _ op e' -> expr e' <+> postfixOp op InfixExpr _ op left right -> expr left <+> infixOp op <+> expr right CondExpr _ test cons alt -> expr test <+> text "?" <+> expr cons <+> colon <+> expr alt- AssignExpr _ op l r -> expr l <+> assignOp op <+> expr r+ AssignExpr _ op l r -> lvalue l <+> assignOp op <+> expr r+ UnaryAssignExpr _ op e' -> case op of+ PrefixInc -> text "++" <> lvalue e'+ PrefixDec -> text "--" <> lvalue e'+ PostfixInc -> lvalue e' <> text "++"+ PostfixDec -> lvalue e' <> text "--" ParenExpr _ e' -> parens (expr e') ListExpr _ es -> cat $ punctuate comma (map expr es) CallExpr _ f args -> expr f <> (parens $ cat $ punctuate comma (map expr args))- FuncExpr _ args body -> - text "function" <+> + FuncExpr _ name args body -> + text "function" <+> text (maybe "" unId name) <+> (parens $ cat $ punctuate comma (map pp args)) $$ inBlock body
src/BrownPLT/JavaScript/Syntax.hs view
@@ -1,8 +1,11 @@ -- |JavaScript's syntax. module BrownPLT.JavaScript.Syntax(Expression(..),CaseClause(..),Statement(..), InfixOp(..),CatchClause(..),VarDecl(..),JavaScript(..),- AssignOp(..),Id(..),PrefixOp(..),PostfixOp(..),Prop(..),- ForInit(..),ForInInit(..),unId) where+ AssignOp(..),Id(..),PrefixOp(..),Prop(..),+ ForInit(..),ForInInit(..),unId+ , UnaryAssignOp (..)+ , LValue (..)+ ) where import Text.ParserCombinators.Parsec(SourcePos) -- used by data JavaScript import Data.Generics(Data,Typeable)@@ -32,17 +35,23 @@ | OpAssignBAnd | OpAssignBXor | OpAssignBOr deriving (Show,Data,Typeable,Eq,Ord) -data PrefixOp = PrefixInc | PrefixDec | PrefixLNot | PrefixBNot | PrefixPlus+data UnaryAssignOp+ = PrefixInc | PrefixDec | PostfixInc | PostfixDec+ deriving (Show, Data, Typeable, Eq, Ord)++data PrefixOp = PrefixLNot | PrefixBNot | PrefixPlus | PrefixMinus | PrefixTypeof | PrefixVoid | PrefixDelete deriving (Show,Data,Typeable,Eq,Ord) -data PostfixOp - = PostfixInc | PostfixDec- deriving (Show,Data,Typeable,Eq,Ord)- data Prop a = PropId a (Id a) | PropString a String | PropNum a Integer deriving (Show,Data,Typeable,Eq,Ord)+ +data LValue a+ = LVar a String+ | LDot a (Expression a) String+ | LBracket a (Expression a) (Expression a)+ deriving (Show, Eq, Ord, Data, Typeable) data Expression a = StringLit a String@@ -58,15 +67,16 @@ | DotRef a (Expression a) (Id a) | BracketRef a (Expression a) {- container -} (Expression a) {- key -} | NewExpr a (Expression a) {- constructor -} [Expression a]- | PostfixExpr a PostfixOp (Expression a) | PrefixExpr a PrefixOp (Expression a)+ | UnaryAssignExpr a UnaryAssignOp (LValue a) | InfixExpr a InfixOp (Expression a) (Expression a) | CondExpr a (Expression a) (Expression a) (Expression a)- | AssignExpr a AssignOp (Expression a) (Expression a)+ | AssignExpr a AssignOp (LValue a) (Expression a) | ParenExpr a (Expression a) | ListExpr a [Expression a] | CallExpr a (Expression a) [Expression a]- | FuncExpr a [(Id a)] (Statement a)+ --funcexprs are optionally named+ | FuncExpr a (Maybe (Id a)) [(Id a)] (Statement a) deriving (Show,Data,Typeable,Eq,Ord) data CaseClause a @@ -108,10 +118,10 @@ | LabelledStmt a (Id a) (Statement a) | ForInStmt a (ForInInit a) (Expression a) (Statement a) | ForStmt a (ForInit a) - (Maybe (Expression a)) -- increment (Maybe (Expression a)) -- test+ (Maybe (Expression a)) -- increment (Statement a) -- body- | TryStmt a (Statement a) {-body-} [CatchClause a] {-catches-}+ | TryStmt a (Statement a) {-body-} (Maybe (CatchClause a)) (Maybe (Statement a)) {-finally-} | ThrowStmt a (Expression a) | ReturnStmt a (Maybe (Expression a))