Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Initial fix for ECMAScript 3 allowing named function expressions.

  • Loading branch information...
commit 425aa61585d542bb6576d519214a2ac8fa1fdbb5 1 parent d7e1795
@alanz authored
View
4 README
@@ -45,6 +45,10 @@ $ cabal install --reinstall alex
Changes
+0.2.0 ECMAScript 3 allows function expressions to have names, AST.JSFunctionExpression now reflects this
+
+0.1.0 Simplified AST by removing JSElement and JSElementList components
+
0.0.3 Support for unicode in source. At the moment it only supports
UTF8 encoding, does not recognise byte order marks or UTF-16/UTF-32
View
2  language-javascript.cabal
@@ -1,5 +1,5 @@
Name: language-javascript
-Version: 0.1.0
+Version: 0.2.0
Synopsis: Parser for JavaScript
Description: Parses Javascript into an Abstract Syntax Tree (AST). Initially intended as frontend to hjsmin.
Homepage: https://github.com/alanz/language-javascript
View
14 runtests.hs
@@ -104,9 +104,9 @@ testSuite = testGroup "Parser"
, testCase "Statement28" (testStmt "y--" "Right (JSExpression [JSExpressionPostfix \"--\" [JSIdentifier \"y\"]])")
-- Member Expressions
- , testCase "MemberExpression1" (testStmt "function(){}" "Right (JSExpression [JSFunctionExpression [] (JSFunctionBody [])])")
- , testCase "MemberExpression1" (testStmt "function(a){}" "Right (JSExpression [JSFunctionExpression [JSIdentifier \"a\"] (JSFunctionBody [])])")
- , testCase "MemberExpression1" (testStmt "function(a,b){}" "Right (JSExpression [JSFunctionExpression [JSIdentifier \"a\",JSIdentifier \"b\"] (JSFunctionBody [])])")
+ , testCase "MemberExpression1" (testStmt "function(){}" "Right (JSExpression [JSFunctionExpression [] [] (JSFunctionBody [])])")
+ , testCase "MemberExpression1" (testStmt "function(a){}" "Right (JSExpression [JSFunctionExpression [] [JSIdentifier \"a\"] (JSFunctionBody [])])")
+ , testCase "MemberExpression1" (testStmt "function(a,b){}" "Right (JSExpression [JSFunctionExpression [] [JSIdentifier \"a\",JSIdentifier \"b\"] (JSFunctionBody [])])")
, testCase "MemberExpression1" (testStmt "x[y]" "Right (JSExpression [JSMemberSquare [JSIdentifier \"x\"] (JSExpression [JSIdentifier \"y\"])])")
, testCase "MemberExpression1" (testStmt "x[y][z]" "Right (JSExpression [JSMemberSquare [JSMemberSquare [JSIdentifier \"x\"] (JSExpression [JSIdentifier \"y\"])] (JSExpression [JSIdentifier \"z\"])])")
@@ -201,9 +201,9 @@ testSuite = testGroup "Parser"
, testCase "Comment2" (testProg "/*x=1\ny=2\n*/z=2;//foo\na" "Right (JSSourceElementsTop [JSExpression [JSIdentifier \"z\",JSOperator \"=\",JSDecimal \"2\"],JSLiteral \";\",JSExpression [JSIdentifier \"a\"]])")
- , testCase "min_100_animals1" (testProg "function Animal(name){if(!name)throw new Error('Must specify an animal name');this.name=name};Animal.prototype.toString=function(){return this.name};o=new Animal(\"bob\");o.toString()==\"bob\"" "Right (JSSourceElementsTop [JSFunction (JSIdentifier \"Animal\") [JSIdentifier \"name\"] (JSFunctionBody [JSSourceElements [JSIf (JSExpression [JSUnary \"!\",JSIdentifier \"name\"]) (JSBlock (JSStatementList [JSThrow (JSExpression [JSLiteral \"new \",JSIdentifier \"Error\",JSArguments [[JSStringLiteral '\\'' \"Must specify an animal name\"]]])])),JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\"),JSOperator \"=\",JSIdentifier \"name\"]]]),JSLiteral \";\",JSExpression [JSMemberDot [JSMemberDot [JSIdentifier \"Animal\"] (JSIdentifier \"prototype\")] (JSIdentifier \"toString\"),JSOperator \"=\",JSFunctionExpression [] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\")],JSLiteral \"\"]]])],JSLiteral \";\",JSExpression [JSIdentifier \"o\",JSOperator \"=\",JSLiteral \"new \",JSIdentifier \"Animal\",JSArguments [[JSStringLiteral '\"' \"bob\"]]],JSLiteral \";\",JSExpression [JSExpressionBinary \"==\" [JSMemberDot [JSIdentifier \"o\"] (JSIdentifier \"toString\"),JSArguments []] [JSStringLiteral '\"' \"bob\"]]])")
+ , testCase "min_100_animals1" (testProg "function Animal(name){if(!name)throw new Error('Must specify an animal name');this.name=name};Animal.prototype.toString=function(){return this.name};o=new Animal(\"bob\");o.toString()==\"bob\"" "Right (JSSourceElementsTop [JSFunction (JSIdentifier \"Animal\") [JSIdentifier \"name\"] (JSFunctionBody [JSSourceElements [JSIf (JSExpression [JSUnary \"!\",JSIdentifier \"name\"]) (JSBlock (JSStatementList [JSThrow (JSExpression [JSLiteral \"new \",JSIdentifier \"Error\",JSArguments [[JSStringLiteral '\\'' \"Must specify an animal name\"]]])])),JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\"),JSOperator \"=\",JSIdentifier \"name\"]]]),JSLiteral \";\",JSExpression [JSMemberDot [JSMemberDot [JSIdentifier \"Animal\"] (JSIdentifier \"prototype\")] (JSIdentifier \"toString\"),JSOperator \"=\",JSFunctionExpression [] [] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\")],JSLiteral \"\"]]])],JSLiteral \";\",JSExpression [JSIdentifier \"o\",JSOperator \"=\",JSLiteral \"new \",JSIdentifier \"Animal\",JSArguments [[JSStringLiteral '\"' \"bob\"]]],JSLiteral \";\",JSExpression [JSExpressionBinary \"==\" [JSMemberDot [JSIdentifier \"o\"] (JSIdentifier \"toString\"),JSArguments []] [JSStringLiteral '\"' \"bob\"]]])")
- , testCase "min_100_animals2" (testProg "Animal=function(){return this.name};" "Right (JSSourceElementsTop [JSExpression [JSIdentifier \"Animal\",JSOperator \"=\",JSFunctionExpression [] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\")],JSLiteral \"\"]]])],JSLiteral \";\"])")
+ , testCase "min_100_animals2" (testProg "Animal=function(){return this.name};" "Right (JSSourceElementsTop [JSExpression [JSIdentifier \"Animal\",JSOperator \"=\",JSFunctionExpression [] [] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSMemberDot [JSLiteral \"this\"] (JSIdentifier \"name\")],JSLiteral \"\"]]])],JSLiteral \";\"])")
, testCase "min_100_animals3" (testProg "if(a)x=1;y=2" "Right (JSSourceElementsTop [JSIf (JSExpression [JSIdentifier \"a\"]) (JSBlock (JSStatementList [JSExpression [JSIdentifier \"x\",JSOperator \"=\",JSDecimal \"1\"]])),JSExpression [JSIdentifier \"y\",JSOperator \"=\",JSDecimal \"2\"]])")
@@ -243,6 +243,10 @@ testSuite = testGroup "Parser"
, testCase "unicode5" (testFile "./test/Unicode.js" "JSSourceElementsTop [JSExpression [JSIdentifier \"\\224\\225\\226\\227\\228\\229\",JSOperator \"=\",JSDecimal \"1\"],JSLiteral \";\"]")
+ , testCase "bug2.a" (testProg "function() {\nz = function /*z*/(o) {\nreturn r;\n};}" "Right (JSSourceElementsTop [JSExpression [JSFunctionExpression [] [] (JSFunctionBody [JSSourceElements [JSExpression [JSIdentifier \"z\",JSOperator \"=\",JSFunctionExpression [] [JSIdentifier \"o\"] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSIdentifier \"r\"],JSLiteral \";\"]]])],JSLiteral \";\"]])]])")
+
+ , testCase "bug2.b" (testProg "function() {\nz = function z(o) {\nreturn r;\n};}" "Right (JSSourceElementsTop [JSExpression [JSFunctionExpression [] [] (JSFunctionBody [JSSourceElements [JSExpression [JSIdentifier \"z\",JSOperator \"=\",JSFunctionExpression [JSIdentifier \"z\"] [JSIdentifier \"o\"] (JSFunctionBody [JSSourceElements [JSReturn [JSExpression [JSIdentifier \"r\"],JSLiteral \";\"]]])],JSLiteral \";\"]])]])")
+
]
srcHelloWorld = "Hello"
View
4 src/Language/JavaScript/Parser/AST.hs
@@ -16,8 +16,6 @@ data JSNode = JSArguments [[JSNode]]
| JSDecimal String -- Was Integer
| JSDefault JSNode
| JSDoWhile JSNode JSNode JSNode
- -- | JSElement String [JSNode]
- -- | JSElementList [JSNode]
| JSElision [JSNode]
| JSEmpty JSNode
| JSExpression [JSNode]
@@ -32,7 +30,7 @@ data JSNode = JSArguments [[JSNode]]
| JSForVarIn JSNode JSNode JSNode
| JSFunction JSNode [JSNode] JSNode -- name, parameter list, body
| JSFunctionBody [JSNode]
- | JSFunctionExpression [JSNode] JSNode -- name, parameter list, body
+ | JSFunctionExpression [JSNode] [JSNode] JSNode -- name, parameter list, body
| JSHexInteger String -- Was Integer
| JSIdentifier String
| JSIf JSNode JSNode
View
7 src/Language/JavaScript/Parser/Grammar.y
@@ -666,9 +666,12 @@ FunctionDeclaration : 'function' Identifier '(' FormalParameterList ')' '{' Func
-- <Function Expression> ::= 'function' '(' ')' '{' <Function Body> '}'
-- | 'function' '(' <Formal Parameter List> ')' '{' <Function Body> '}'
FunctionExpression :: { AST.JSNode }
-FunctionExpression : 'function' '(' ')' '{' FunctionBody '}' { (AST.JSFunctionExpression [] $5) }
- | 'function' '(' FormalParameterList ')' '{' FunctionBody '}' { (AST.JSFunctionExpression $3 $6) }
+FunctionExpression : 'function' IdentifierOpt '(' ')' '{' FunctionBody '}' { (AST.JSFunctionExpression $2 [] $6) }
+ | 'function' IdentifierOpt '(' FormalParameterList ')' '{' FunctionBody '}' { (AST.JSFunctionExpression $2 $4 $7) }
+IdentifierOpt :: { [AST.JSNode] }
+IdentifierOpt : Identifier { [$1] {- IdentifierOpt -}}
+ | { [] {- IdentifierOpt -}}
-- <Formal Parameter List> ::= Identifier
-- | <Formal Parameter List> ',' Identifier
View
1  test/k.js
@@ -0,0 +1 @@
+function f() {}
Please sign in to comment.
Something went wrong with that request. Please try again.