packages feed

language-ecmascript 0.10 → 0.11.1

raw patch · 7 files changed

+220/−122 lines, 7 filesdep +charsetdep +template-haskelldep ~QuickCheckdep ~data-defaultPVP ok

version bump matches the API change (PVP)

Dependencies added: charset, template-haskell

Dependency ranges changed: QuickCheck, data-default

API changes (from Hackage documentation)

+ Language.ECMAScript3.Parser: parseObjectLit :: Stream s Identity Char => ExpressionParser s
+ Language.ECMAScript3.Parser: type Parser s a = ParsecT s ParserState Identity a
+ Language.ECMAScript3.Parser.State: type ParserState = [String]
+ Language.ECMAScript3.Parser.Type: type Parser s a = ParsecT s ParserState Identity a
+ Language.ECMAScript3.Syntax.QuasiQuote: js :: QuasiQuoter
+ Language.ECMAScript3.Syntax.QuasiQuote: jsexpr :: QuasiQuoter
+ Language.ECMAScript3.Syntax.QuasiQuote: jsstmt :: QuasiQuoter
- Language.ECMAScript3.Lexer: braces :: ParsecT String u Identity a -> ParsecT String u Identity a
+ Language.ECMAScript3.Lexer: braces :: Stream s Identity Char => Parser s a -> Parser s a
- Language.ECMAScript3.Lexer: brackets :: ParsecT String u Identity a -> ParsecT String u Identity a
+ Language.ECMAScript3.Lexer: brackets :: Stream s Identity Char => Parser s a -> Parser s a
- Language.ECMAScript3.Lexer: charLiteral :: ParsecT String u Identity Char
+ Language.ECMAScript3.Lexer: charLiteral :: Stream s Identity Char => Parser s Char
- Language.ECMAScript3.Lexer: colon :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: colon :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: comma :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: comma :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: decimal :: ParsecT String u Identity Integer
+ Language.ECMAScript3.Lexer: decimal :: Stream s Identity Char => Parser s Integer
- Language.ECMAScript3.Lexer: dot :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: dot :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: float :: ParsecT String u Identity Double
+ Language.ECMAScript3.Lexer: float :: Stream s Identity Char => Parser s Double
- Language.ECMAScript3.Lexer: hexadecimal :: ParsecT String u Identity Integer
+ Language.ECMAScript3.Lexer: hexadecimal :: Stream s Identity Char => Parser s Integer
- Language.ECMAScript3.Lexer: identifier :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: identifier :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: identifierStart :: ParsecT [Char] u Identity Char
+ Language.ECMAScript3.Lexer: identifierStart :: Stream s Identity Char => Parser s Char
- Language.ECMAScript3.Lexer: integer :: ParsecT String u Identity Integer
+ Language.ECMAScript3.Lexer: integer :: Stream s Identity Char => Parser s Integer
- Language.ECMAScript3.Lexer: lexeme :: ParsecT String u Identity a -> ParsecT String u Identity a
+ Language.ECMAScript3.Lexer: lexeme :: Stream s Identity Char => Parser s a -> Parser s a
- Language.ECMAScript3.Lexer: natural :: ParsecT String u Identity Integer
+ Language.ECMAScript3.Lexer: natural :: Stream s Identity Char => Parser s Integer
- Language.ECMAScript3.Lexer: naturalOrFloat :: ParsecT String u Identity (Either Integer Double)
+ Language.ECMAScript3.Lexer: naturalOrFloat :: Stream s Identity Char => Parser s (Either Integer Double)
- Language.ECMAScript3.Lexer: octal :: ParsecT String u Identity Integer
+ Language.ECMAScript3.Lexer: octal :: Stream s Identity Char => Parser s Integer
- Language.ECMAScript3.Lexer: operator :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: operator :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: parens :: ParsecT String u Identity a -> ParsecT String u Identity a
+ Language.ECMAScript3.Lexer: parens :: Stream s Identity Char => Parser s a -> Parser s a
- Language.ECMAScript3.Lexer: reserved :: String -> ParsecT String u Identity ()
+ Language.ECMAScript3.Lexer: reserved :: Stream s Identity Char => String -> Parser s ()
- Language.ECMAScript3.Lexer: reservedOp :: String -> ParsecT String u Identity ()
+ Language.ECMAScript3.Lexer: reservedOp :: Stream s Identity Char => String -> Parser s ()
- Language.ECMAScript3.Lexer: semi :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: semi :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: squares :: ParsecT String u Identity a -> ParsecT String u Identity a
+ Language.ECMAScript3.Lexer: squares :: Stream s Identity Char => Parser s a -> Parser s a
- Language.ECMAScript3.Lexer: stringLiteral :: ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: stringLiteral :: Stream s Identity Char => Parser s String
- Language.ECMAScript3.Lexer: symbol :: String -> ParsecT String u Identity String
+ Language.ECMAScript3.Lexer: symbol :: Stream s Identity Char => String -> Parser s String
- Language.ECMAScript3.Lexer: whiteSpace :: ParsecT String u Identity ()
+ Language.ECMAScript3.Lexer: whiteSpace :: Stream s Identity Char => Parser s ()
- Language.ECMAScript3.Parser: assignExpr :: ExpressionParser
+ Language.ECMAScript3.Parser: assignExpr :: Stream s Identity Char => ExpressionParser s
- Language.ECMAScript3.Parser: parse :: Stream s Identity t => Parsec s [String] a -> SourceName -> s -> Either ParseError a
+ Language.ECMAScript3.Parser: parse :: Stream s Identity Char => Parser s a -> SourceName -> s -> Either ParseError a
- Language.ECMAScript3.Parser: parseBlockStmt :: StatementParser
+ Language.ECMAScript3.Parser: parseBlockStmt :: Stream s Identity Char => StatementParser s
- Language.ECMAScript3.Parser: parseExpression :: ExpressionParser
+ Language.ECMAScript3.Parser: parseExpression :: Stream s Identity Char => ExpressionParser s
- Language.ECMAScript3.Parser: parseScript :: CharParser (JavaScript SourcePos)
+ Language.ECMAScript3.Parser: parseScript :: Stream s Identity Char => Parser s (JavaScript SourcePos)
- Language.ECMAScript3.Parser: parseSimpleExpr' :: ParsecT String ParserState Identity ParsedExpression
+ Language.ECMAScript3.Parser: parseSimpleExpr' :: Stream s Identity Char => ExpressionParser s
- Language.ECMAScript3.Parser: parseStatement :: StatementParser
+ Language.ECMAScript3.Parser: parseStatement :: Stream s Identity Char => StatementParser s
- Language.ECMAScript3.Parser: type ExpressionParser = CharParser ParsedExpression
+ Language.ECMAScript3.Parser: type ExpressionParser s = Parser s ParsedExpression
- Language.ECMAScript3.Parser: type StatementParser = CharParser ParsedStatement
+ Language.ECMAScript3.Parser: type StatementParser s = Parser s ParsedStatement

Files

CHANGELOG view
@@ -1,7 +1,13 @@ Version change log. -=0.10=+=0.11.1=+Fixed binary operator precedence in the parser. See  +=0.11=+Added a simple quasi-quoter for ECMAScript (see+Language.ECMAScript3.Syntax.QuasiQuote)++=0.10= The ParenExpr constructor was removed from the Expression AST (WARNING: might break some builds). The pretty printer was rewritten to automatically parenthesize sub-expressions based on operator
language-ecmascript.cabal view
@@ -1,5 +1,5 @@ Name:           language-ecmascript-Version:        0.10+Version:        0.11.1 Cabal-Version:	>= 1.10 Copyright:      (c) 2007-2012 Brown University, (c) 2008-2010 Claudiu Saftoiu,                 (c) 2012 Stevens Institute of Technology@@ -21,7 +21,7 @@   Includes a parser, pretty-printer, and basic building blocks for more   sophisticated tools. -  This package used to be called WebBits.+  This package supercedes package WebBits.  Source-repository head    type: git@@ -30,7 +30,7 @@ Source-repository this    type: git    location: git://github.com/jswebtools/language-ecmascript.git-   tag: 0.9.1+   tag: 0.11.1  Library   Hs-Source-Dirs:@@ -44,7 +44,9 @@     syb >= 0.1,     uniplate >= 1.6 && <1.7,     data-default >= 0.4 && <0.6,-    QuickCheck >= 2.4.1.1+    QuickCheck >= 2.5,+    template-haskell,+    charset >= 0.3.2.1   ghc-options:     -fwarn-incomplete-patterns   Exposed-Modules:@@ -55,8 +57,11 @@     Language.ECMAScript3.Syntax     Language.ECMAScript3.Syntax.Annotations     Language.ECMAScript3.Syntax.Arbitrary+    Language.ECMAScript3.Syntax.QuasiQuote     Language.ECMAScript3.Analysis.Environment     Language.ECMAScript3.Analysis.LabelSets+    Language.ECMAScript3.Parser.Type+    Language.ECMAScript3.Parser.State   Default-Extensions:     DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts   Default-Language: Haskell2010@@ -76,7 +81,8 @@     filepath,     HUnit,     data-default >=0.4 && <0.6,-    QuickCheck >= 2.4.1.1+    QuickCheck >= 2.5,+    charset >= 0.3.2.1   Default-Extensions: DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts   Default-Language: Haskell2010   ghc-options:@@ -96,8 +102,8 @@     directory,     filepath,     HUnit,-    data-default >=0.4 && <0.5,-    QuickCheck >= 2.4.1.1,+    data-default >=0.4 && <0.6,+    QuickCheck >= 2.5,     uniplate >= 1.6 && <1.7   Default-Extensions: DeriveDataTypeable, ScopedTypeVariables, DeriveFunctor, DeriveFoldable, DeriveTraversable, FlexibleContexts   Default-Language: Haskell2010
src/Language/ECMAScript3/Lexer.hs view
@@ -11,9 +11,14 @@ import Prelude hiding (lex) import Text.Parsec import qualified Text.Parsec.Token as T+import Language.ECMAScript3.Parser.State+import Language.ECMAScript3.Parser.Type+import Control.Monad.Identity +identifierStart :: Stream s Identity Char => Parser s Char identifierStart = letter <|> oneOf "$_" +javascriptDef :: Stream s Identity Char =>T.GenLanguageDef s ParserState Identity javascriptDef =   T.LanguageDef "/*"                 "*/"@@ -35,31 +40,55 @@                  "[", "]", "{", "}", "(", ")","</","instanceof"]                  True -- case-sensitive             -lex :: T.TokenParser st+lex :: Stream s Identity Char => T.GenTokenParser s ParserState Identity lex = T.makeTokenParser javascriptDef  -- everything but commaSep and semiSep+identifier :: Stream s Identity Char => Parser s String identifier = T.identifier	 lex+reserved :: Stream s Identity Char => String -> Parser s () reserved = T.reserved	 lex+operator :: Stream s Identity Char => Parser s String operator = T.operator	 lex+reservedOp :: Stream s Identity Char => String -> Parser s () reservedOp = T.reservedOp lex	+charLiteral :: Stream s Identity Char => Parser s Char charLiteral = T.charLiteral lex	-stringLiteral = T.stringLiteral lex	+stringLiteral :: Stream s Identity Char => Parser s String+stringLiteral = T.stringLiteral lex+natural :: Stream s Identity Char => Parser s Integer natural = T.natural lex	+integer :: Stream s Identity Char => Parser s Integer integer = T.integer lex	-float = T.float lex	-naturalOrFloat = T.naturalOrFloat lex	+float :: Stream s Identity Char => Parser s Double+float = T.float lex+naturalOrFloat :: Stream s Identity Char => Parser s (Either Integer Double)+naturalOrFloat = T.naturalOrFloat lex+decimal :: Stream s Identity Char => Parser s Integer decimal = T.decimal lex	+hexadecimal :: Stream s Identity Char => Parser s Integer hexadecimal = T.hexadecimal lex	-octal = T.octal lex	-symbol = T.symbol lex	+octal :: Stream s Identity Char => Parser s Integer+octal = T.octal lex+symbol :: Stream s Identity Char => String -> Parser s String+symbol = T.symbol lex+whiteSpace :: Stream s Identity Char => Parser s () whiteSpace = T.whiteSpace lex	+parens :: Stream s Identity Char => Parser s a -> Parser s a parens = T.parens	 lex+braces :: Stream s Identity Char => Parser s a -> Parser s a braces = T.braces	 lex+squares :: Stream s Identity Char => Parser s a -> Parser s a squares = T.squares lex	+semi :: Stream s Identity Char => Parser s String semi = T.semi	 lex+comma :: Stream s Identity Char => Parser s String comma = T.comma	 lex-colon = T.colon lex	+colon :: Stream s Identity Char => Parser s String+colon = T.colon lex+dot :: Stream s Identity Char => Parser s String dot = T.dot lex+brackets :: Stream s Identity Char => Parser s a -> Parser s a brackets = T.brackets lex+lexeme :: Stream s Identity Char => Parser s a -> Parser s a lexeme = T.lexeme lex
src/Language/ECMAScript3/Parser.hs view
@@ -18,10 +18,14 @@   -- debugging, remove the next 2 lines   , mkDecimal   , intLen+  , parseObjectLit  +  , Parser     ) where  import Language.ECMAScript3.Lexer hiding (identifier) import qualified Language.ECMAScript3.Lexer as Lexer+import Language.ECMAScript3.Parser.State+import Language.ECMAScript3.Parser.Type import Language.ECMAScript3.Syntax import Language.ECMAScript3.Syntax.Annotations import Data.Default@@ -38,27 +42,24 @@ type ParsedStatement = Statement SourcePos type ParsedExpression = Expression SourcePos -type CharParser a = ParsecT String ParserState Identity a- -- These parsers can store some arbitrary state-type StatementParser  = CharParser ParsedStatement-type ExpressionParser = CharParser ParsedExpression--- the statement label stack-type ParserState = [String]+type StatementParser s = Parser s ParsedStatement+type ExpressionParser s = Parser s ParsedExpression + initialParserState :: ParserState initialParserState = []  -- | checks if the label is not yet on the stack, if it is -- throws -- an error; otherwise it pushes it onto the stack-pushLabel :: String -> CharParser ()+pushLabel :: String -> Parser s () pushLabel lab = do labs <- getState                    pos <- getPosition                    if lab `elem` labs                       then fail $ "Duplicate label at " ++ show pos                      else putState (lab:labs) -popLabel :: CharParser ()+popLabel :: Parser s () popLabel = modifyState safeTail   where safeTail [] = []         safeTail (_:xs) = xs@@ -66,14 +67,14 @@ clearLabels :: ParserState -> ParserState clearLabels _ = [] -withFreshLabelStack :: CharParser a -> CharParser a+withFreshLabelStack :: Parser s a -> Parser s a withFreshLabelStack p = do oldState <- getState                            putState $ clearLabels oldState                            a <- p                            putState oldState                            return a -identifier :: CharParser (Id SourcePos)+identifier :: Stream s Identity Char => Parser s (Id SourcePos) identifier =   liftM2 Id getPosition Lexer.identifier @@ -88,7 +89,7 @@ -- reserved-word, we truly have a syntax error.  Since input has been consumed, -- <|> will not try its alternate in parseExpression, and we will fail. -parseIfStmt:: StatementParser  +parseIfStmt:: Stream s Identity Char => StatementParser s  parseIfStmt = do   pos <- getPosition   reserved "if"@@ -100,7 +101,7 @@        return $ IfStmt pos test consequent alternate)    <|> return (IfSingleStmt pos test consequent)) -parseSwitchStmt:: StatementParser+parseSwitchStmt :: Stream s Identity Char => StatementParser s parseSwitchStmt =   let parseDefault = do         pos <- getPosition@@ -128,7 +129,7 @@           checkClauses clauses           return (SwitchStmt pos test clauses) -parseWhileStmt:: StatementParser+parseWhileStmt:: Stream s Identity Char => StatementParser s parseWhileStmt = do   pos <- getPosition   reserved "while"@@ -136,7 +137,7 @@   body <- parseStatement   return (WhileStmt pos test body) -parseDoWhileStmt:: StatementParser+parseDoWhileStmt:: Stream s Identity Char => StatementParser s parseDoWhileStmt = do   pos <- getPosition   reserved "do"@@ -146,7 +147,7 @@   optional semi   return (DoWhileStmt pos body test) -parseContinueStmt:: StatementParser+parseContinueStmt:: Stream s Identity Char => StatementParser s parseContinueStmt = do   pos <- getPosition   reserved "continue"@@ -158,7 +159,7 @@   optional semi   return $ ContinueStmt pos id -parseBreakStmt:: StatementParser+parseBreakStmt:: Stream s Identity Char => StatementParser s parseBreakStmt = do   pos <- getPosition   reserved "break"@@ -170,19 +171,19 @@   optional semi              return $ BreakStmt pos id -parseBlockStmt:: StatementParser+parseBlockStmt:: Stream s Identity Char => StatementParser s parseBlockStmt = do   pos <- getPosition   statements <- braces (many parseStatement)   return (BlockStmt pos statements) -parseEmptyStmt:: StatementParser +parseEmptyStmt:: Stream s Identity Char => StatementParser s parseEmptyStmt = do   pos <- getPosition   semi   return (EmptyStmt pos) -parseLabelledStmt:: StatementParser+parseLabelledStmt:: Stream s Identity Char => StatementParser s parseLabelledStmt = do   pos <- getPosition   -- Lookahead for the colon.  If we don't see it, we are parsing an identifier@@ -195,7 +196,7 @@   popLabel   return (LabelledStmt pos label statement) -parseExpressionStmt:: StatementParser+parseExpressionStmt:: Stream s Identity Char => StatementParser s parseExpressionStmt = do   pos <- getPosition   expr <- parseListExpr -- TODO: spec 12.4?@@ -203,7 +204,7 @@   return $ ExprStmt pos expr  -parseForInStmt:: StatementParser+parseForInStmt:: Stream s Identity Char => StatementParser s parseForInStmt =   let parseInit = (reserved "var" >> liftM ForInVar identifier)                <|> liftM ForInLVal lvalue@@ -217,7 +218,7 @@         body <- parseStatement         return $ ForInStmt pos init expr body -parseForStmt:: StatementParser+parseForStmt:: Stream s Identity Char => StatementParser s parseForStmt =   let parseInit = (reserved "var" >> liftM VarInit (parseVarDecl `sepBy` comma))                <|> liftM ExprInit parseListExpr@@ -234,7 +235,7 @@           stmt <- parseStatement           return $ ForStmt pos init test iter stmt -parseTryStmt:: StatementParser+parseTryStmt:: Stream s Identity Char => StatementParser s parseTryStmt =   let parseCatchClause = do pos <- getPosition                             reserved "catch"@@ -253,7 +254,7 @@           else fail $ "A try statement should have at least a catch\                        \ or a finally block, at " ++ show pos -parseThrowStmt:: StatementParser+parseThrowStmt:: Stream s Identity Char => StatementParser s parseThrowStmt = do   pos <- getPosition   reserved "throw"@@ -261,7 +262,7 @@   optional semi   return (ThrowStmt pos expr) -parseReturnStmt:: StatementParser+parseReturnStmt:: Stream s Identity Char => StatementParser s parseReturnStmt = do   pos <- getPosition   reserved "return"@@ -269,7 +270,7 @@   optional semi   return (ReturnStmt pos expr) -parseWithStmt:: StatementParser+parseWithStmt:: Stream s Identity Char => StatementParser s parseWithStmt = do   pos <- getPosition   reserved "with"@@ -277,13 +278,14 @@   stmt <- parseStatement   return (WithStmt pos context stmt) +parseVarDecl :: Stream s Identity Char => Parser s (VarDecl SourcePos)  parseVarDecl = do   pos <- getPosition   id <- identifier   init <- (reservedOp "=" >> liftM Just parseExpression) <|> return Nothing   return (VarDecl pos id init) -parseVarDeclStmt:: StatementParser+parseVarDeclStmt:: Stream s Identity Char => StatementParser s parseVarDeclStmt = do    pos <- getPosition   reserved "var"@@ -291,7 +293,7 @@   optional semi   return (VarDeclStmt pos decls) -parseFunctionStmt:: StatementParser+parseFunctionStmt:: Stream s Identity Char => StatementParser s parseFunctionStmt = do   pos <- getPosition   name <- try (reserved "function" >> identifier) -- ambiguity with FuncExpr@@ -301,7 +303,7 @@                       "function body in { ... }"   return (FunctionStmt pos name args body) -parseStatement:: StatementParser+parseStatement:: Stream s Identity Char => StatementParser s parseStatement = parseIfStmt <|> parseSwitchStmt <|> parseWhileStmt    <|> parseDoWhileStmt <|> parseContinueStmt <|> parseBreakStmt    <|> parseBlockStmt <|> parseEmptyStmt <|> parseForInStmt <|> parseForStmt@@ -331,32 +333,33 @@  --{{{ Primary expressions -parseThisRef:: ExpressionParser+parseThisRef:: Stream s Identity Char => ExpressionParser s parseThisRef = do   pos <- getPosition   reserved "this"   return (ThisRef pos) -parseNullLit:: ExpressionParser+parseNullLit:: Stream s Identity Char => ExpressionParser s parseNullLit = do   pos <- getPosition   reserved "null"   return (NullLit pos)  -parseBoolLit:: ExpressionParser+parseBoolLit:: Stream s Identity Char => ExpressionParser s parseBoolLit = do     pos <- getPosition     let parseTrueLit  = reserved "true"  >> return (BoolLit pos True)         parseFalseLit = reserved "false" >> return (BoolLit pos False)     parseTrueLit <|> parseFalseLit -parseVarRef:: ExpressionParser+parseVarRef:: Stream s Identity Char => ExpressionParser s parseVarRef = liftM2 VarRef getPosition identifier -parseArrayLit:: ExpressionParser+parseArrayLit:: Stream s Identity Char => ExpressionParser s parseArrayLit = liftM2 ArrayLit getPosition (squares (parseExpression `sepEndBy` comma))-  ++parseFuncExpr :: Stream s Identity Char => ExpressionParser s parseFuncExpr = do   pos <- getPosition   reserved "function"@@ -375,17 +378,20 @@ allEscapes:: String allEscapes = map fst escapeChars +parseEscapeChar :: Stream s Identity Char => Parser s Char parseEscapeChar = do   c <- oneOf allEscapes   let (Just c') = lookup c escapeChars -- will succeed due to line above   return c'  +parseAsciiHexChar :: Stream s Identity Char => Parser s Char parseAsciiHexChar = do   char 'x'   d1 <- hexDigit   d2 <- hexDigit   return ((chr.fst.head.readHex) (d1:d2:"")) +parseUnicodeHexChar :: Stream s Identity Char => Parser s Char parseUnicodeHexChar = do   char 'u'   liftM (chr.fst.head.readHex) @@ -410,7 +416,7 @@         else return (c:cs)) <|>    liftM2 (:) anyChar (parseStringLit' endWith) -parseStringLit:: ExpressionParser+parseStringLit:: Stream s Identity Char => ExpressionParser s parseStringLit = do   pos <- getPosition   -- parseStringLit' takes as an argument the quote-character that opened the@@ -425,14 +431,14 @@  --}}} -parseRegexpLit:: ExpressionParser+parseRegexpLit:: Stream s Identity Char => ExpressionParser s parseRegexpLit = do   let parseFlags = do         flags <- many (oneOf "mgi")         return $ \f -> f ('g' `elem` flags) ('i' `elem` flags) -  let parseEscape :: CharParser Char+  let parseEscape :: Stream s Identity Char => Parser s Char       parseEscape = char '\\' >> anyChar-  let parseChar :: CharParser Char+  let parseChar :: Stream s Identity Char => Parser s Char       parseChar = noneOf "/"   let parseRe = (char '/' >> return "") <|>                  (do char '\\'@@ -448,7 +454,7 @@   spaces -- crucial for Parsec.Token parsers   return $ flags (RegexpLit pos pat)           -parseObjectLit:: ExpressionParser+parseObjectLit:: Stream s Identity Char => ExpressionParser s parseObjectLit =   let parseProp = do         -- Parses a string, identifier or integer as the property name.  I@@ -465,7 +471,7 @@           return $ ObjectLit pos props  --{{{ Parsing numbers.  From pg. 17-18 of ECMA-262.-+hexLit :: Stream s Identity Char => Parser s (Bool, Double) hexLit = do   try (string "0x")   digits <- many1 (oneOf "0123456789abcdefABCDEF")@@ -477,18 +483,16 @@ mkDecimal whole frac fracLen exp =    ((fromInteger whole) + ((fromInteger frac) * (10 ^^ (-fracLen)))) * (10 ^^ exp) --- mkDecimal:: Double -> Double -> Int -> Double--- mkDecimal w f e =  if f >= 1.0---                    then mkDecimal w (f / 10.0) e---                    else (w + f) * (10.0 ^^ e)-+exponentPart :: Stream s Identity Char => Parser s Integer exponentPart = do   oneOf "eE"   (char '+' >> decimal) <|> (char '-' >> negate `fmap` decimal) <|> decimal  --wrap a parser's result in a Just:+jparser :: Stream s Identity Char => Parser s a -> Parser s (Maybe a) jparser = liftM Just +decLit :: Stream s Identity Char => Parser s (Bool, Double) decLit =    (do whole <- decimal       mfrac <- option Nothing (jparser (char '.' >> decimal))@@ -508,7 +512,7 @@ intLen i | i `div` 10 < 1 = 1 intLen i | otherwise = 1 + intLen (i `div` 10) -parseNumLit:: ExpressionParser+parseNumLit:: Stream s Identity Char => ExpressionParser s parseNumLit = do     pos <- getPosition     (isint, num) <- lexeme $ hexLit <|> decLit@@ -542,20 +546,23 @@ -- Expression Parsers ------------------------------------------------------------------------------- -parseParenExpr:: ExpressionParser+parseParenExpr:: Stream s Identity Char => ExpressionParser s parseParenExpr = parens parseListExpr  -- everything above expect functions+parseExprForNew :: Stream s Identity Char => ExpressionParser s parseExprForNew = parseThisRef <|> parseNullLit <|> parseBoolLit <|> parseStringLit    <|> parseArrayLit <|> parseParenExpr <|> parseNewExpr <|> parseNumLit    <|> parseRegexpLit <|> parseObjectLit <|> parseVarRef  -- all the expression parsers defined above+parseSimpleExpr' :: Stream s Identity Char => ExpressionParser s parseSimpleExpr' = parseThisRef <|> parseNullLit <|> parseBoolLit    <|> parseStringLit <|> parseArrayLit <|> parseParenExpr   <|> parseFuncExpr <|> parseNumLit <|> parseRegexpLit <|> parseObjectLit   <|> parseVarRef +parseNewExpr :: Stream s Identity Char => ExpressionParser s parseNewExpr =   (do pos <- getPosition       reserved "new"@@ -571,6 +578,8 @@   e <- parseNewExpr <?> "expression (3)"   parseSimpleExpr (Just e) +parseSimpleExprForNew :: Stream s Identity Char+                      =>(Maybe ParsedExpression) -> ExpressionParser s parseSimpleExprForNew (Just e) = ((dotRef e <|> bracketRef e) >>=                                   parseSimpleExprForNew . Just)                               <|> return e@@ -581,7 +590,8 @@ --}}}  makeInfixExpr str constr = Infix parser AssocLeft where-  parser:: CharParser (Expression SourcePos -> Expression SourcePos -> Expression SourcePos)+  parser:: Stream s Identity Char+        => Parser s (Expression SourcePos -> Expression SourcePos -> Expression SourcePos)   parser = do     pos <- getPosition     reservedOp str@@ -589,6 +599,7 @@   -- apparently, expression tables can't handle immediately-nested prefixes+parsePrefixedExpr :: Stream s Identity Char => ExpressionParser s parsePrefixedExpr = do   pos <- getPosition   op <- optionMaybe $ (reservedOp "!" >> return PrefixLNot) <|> @@ -606,24 +617,19 @@       innerExpr <- parsePrefixedExpr       return (PrefixExpr pos op innerExpr) -exprTable:: [[Operator String ParserState Identity ParsedExpression]]+exprTable:: Stream s Identity Char => [[Operator s ParserState Identity ParsedExpression]] exprTable = -  [ [ makeInfixExpr "==" OpEq-    , makeInfixExpr "!=" OpNEq-    , makeInfixExpr "===" OpStrictEq-    , makeInfixExpr "!==" OpStrictNEq+  [ [ makeInfixExpr "*" OpMul+    , makeInfixExpr "/" OpDiv+    , makeInfixExpr "%" OpMod     ]--  , [ makeInfixExpr "||" OpLOr ]--  , [ makeInfixExpr "&&" OpLAnd ]-  -  , [ makeInfixExpr "|" OpBOr ]--  , [ makeInfixExpr "^" OpBXor ]--  , [ makeInfixExpr "&" OpBAnd ]-+  , [ makeInfixExpr "+" OpAdd+    , makeInfixExpr "-" OpSub+    ]+  , [ makeInfixExpr "<<" OpLShift+    , makeInfixExpr ">>" OpSpRShift+    , makeInfixExpr ">>>" OpZfRShift+    ]   , [ makeInfixExpr "<" OpLT     , makeInfixExpr "<=" OpLEq     , makeInfixExpr ">" OpGT@@ -631,42 +637,39 @@     , makeInfixExpr "instanceof" OpInstanceof     , makeInfixExpr "in" OpIn     ]--  , [ makeInfixExpr "<<" OpLShift-    , makeInfixExpr ">>" OpSpRShift-    , makeInfixExpr ">>>" OpZfRShift-    ]--  , [ makeInfixExpr "+" OpAdd-    , makeInfixExpr "-" OpSub-    ]--  , [ makeInfixExpr "*" OpMul-    , makeInfixExpr "/" OpDiv-    , makeInfixExpr "%" OpMod+  , [ makeInfixExpr "==" OpEq+    , makeInfixExpr "!=" OpNEq+    , makeInfixExpr "===" OpStrictEq+    , makeInfixExpr "!==" OpStrictNEq     ]+  , [ makeInfixExpr "&" OpBAnd ]+  , [ makeInfixExpr "^" OpBXor ]+  , [ makeInfixExpr "|" OpBOr ]+  , [ makeInfixExpr "&&" OpLAnd ]+  , [ makeInfixExpr "||" OpLOr ]   ] +parseExpression' :: Stream s Identity Char => ExpressionParser s parseExpression' =    buildExpressionParser exprTable parsePrefixedExpr <?> "simple expression" -asLValue :: SourcePos+asLValue :: Stream s Identity Char+         => SourcePos          -> Expression SourcePos -         -> CharParser (LValue SourcePos)+         -> Parser s (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 $ "expected a left-value at " ++ show p' -lvalue :: CharParser (LValue SourcePos)+lvalue :: Stream s Identity Char => Parser s (LValue SourcePos) lvalue = do   p <- getPosition   e <- parseSimpleExpr Nothing   asLValue p e --unaryAssignExpr :: CharParser ParsedExpression+unaryAssignExpr :: Stream s Identity Char => ExpressionParser s unaryAssignExpr = do   p <- getPosition   let prefixInc = do@@ -686,8 +689,8 @@         postfixInc e <|> postfixDec e <|> return e   prefixInc <|> prefixDec <|> other --parseTernaryExpr':: CharParser (ParsedExpression,ParsedExpression)+parseTernaryExpr':: Stream s Identity Char+                 => Parser s (ParsedExpression,ParsedExpression) parseTernaryExpr' = do     reservedOp "?"     l <- assignExpr@@ -695,7 +698,7 @@     r <- assignExpr     return (l,r) -parseTernaryExpr:: ExpressionParser+parseTernaryExpr:: Stream s Identity Char => ExpressionParser s parseTernaryExpr = do   e <- parseExpression'   e' <- optionMaybe parseTernaryExpr'@@ -704,24 +707,21 @@     Just (l,r) -> do p <- getPosition                      return $ CondExpr p e l r --assignOp :: CharParser 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)-+assignOp :: Stream s Identity Char => Parser s 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) -assignExpr :: ExpressionParser+assignExpr :: Stream s Identity Char => ExpressionParser s assignExpr = do   p <- getPosition   lhs <- parseTernaryExpr@@ -732,22 +732,23 @@         return (AssignExpr p op lhs rhs)   assign <|> return lhs -parseExpression:: ExpressionParser+parseExpression:: Stream s Identity Char => ExpressionParser s parseExpression = assignExpr +parseListExpr :: Stream s Identity Char => ExpressionParser s parseListExpr = assignExpr `sepBy1` comma >>= \exprs ->   case exprs of     [expr] -> return expr     es     -> liftM2 ListExpr getPosition (return es) -parseScript:: CharParser (JavaScript SourcePos)+parseScript:: Stream s Identity Char => Parser s (JavaScript SourcePos) parseScript = do   whiteSpace   liftM2 Script getPosition (parseStatement `sepBy` whiteSpace)    -- | Parse from a stream; same as 'Text.Parsec.parse'-parse :: Stream s Identity t -      => Parsec s [String] a -- ^ The parser to use+parse :: Stream s Identity Char+      => Parser s a -- ^ The parser to use       -> SourceName -- ^ Name of the source file       -> s -- ^ the stream to parse, usually a 'String'       -> Either ParseError a
+ src/Language/ECMAScript3/Parser/State.hs view
@@ -0,0 +1,4 @@+module Language.ECMAScript3.Parser.State where++-- the statement label stack+type ParserState = [String]
+ src/Language/ECMAScript3/Parser/Type.hs view
@@ -0,0 +1,7 @@+module Language.ECMAScript3.Parser.Type where++import Language.ECMAScript3.Parser.State+import Text.Parsec+import Control.Monad.Identity++type Parser s a = ParsecT s ParserState Identity a
+ src/Language/ECMAScript3/Syntax/QuasiQuote.hs view
@@ -0,0 +1,45 @@+-- | Experimental and very simple quasi-quotation of ECMAScript in+-- Haskell. Doesn't support anti-quotation as of now.++{-# LANGUAGE FlexibleContexts #-}+module Language.ECMAScript3.Syntax.QuasiQuote (js, jsexpr, jsstmt) where++import qualified Language.Haskell.TH as TH+import Language.Haskell.TH.Quote+import Text.Parsec hiding (parse)+import Control.Monad.Identity+import Data.Data (Data)++import Language.ECMAScript3.Syntax+import Language.ECMAScript3.Parser++jsexpr :: QuasiQuoter+jsexpr = QuasiQuoter {quoteExp = quoteJSExpr}++jsstmt :: QuasiQuoter+jsstmt = QuasiQuoter {quoteExp = quoteJSStmt}++js :: QuasiQuoter+js = QuasiQuoter {quoteExp = quoteJS}++quoteJSExpr :: String -> TH.ExpQ+quoteJSExpr = quoteCommon parseExpression++quoteJSStmt :: String -> TH.ExpQ+quoteJSStmt = quoteCommon parseStatement++quoteJS :: String -> TH.ExpQ+quoteJS = quoteCommon parseScript++quoteCommon :: Data a => Parser String a -> String -> TH.ExpQ+quoteCommon p s = do loc <- TH.location+                     let fname = TH.loc_filename loc+                     let (line, col)  = TH.loc_start loc+                     let p2 = (getPosition >>= \pos ->+                                setPosition $ (flip setSourceName) fname $+                                (flip setSourceLine) line $+                                (flip setSourceColumn) col $ pos) >> p+                     case parse p2 "" s of+                       Left err -> do TH.report True $ show err+                                      return $ TH.UnboxedTupE []+                       Right x  -> dataToExpQ (const Nothing) x