Skip to content
Browse files

Make `own` behave correctly.

  • Loading branch information...
1 parent 0737f76 commit 873bfe3938a7927666fc47624a961ee0060f1717 @wycats committed Oct 17, 2011
Showing with 64 additions and 33 deletions.
  1. +6 −3 lib/grammar.y
  2. +27 −4 lib/lexer.l
  3. +30 −26 lib/stringify.js
  4. +1 −0 test/stringify-test.js
View
9 lib/grammar.y
@@ -863,9 +863,7 @@ IfStatement
;
IterationStatement
- : FOR '(' OWN LeftHandSideExpr INTOKEN Expr ')' Statement
- { $$ = yy.Node('ForInStatement', $LeftHandSideExpr, $Expr, $Statement, 'own', yy.loc([@$,@8])); }
- | DO Statement WHILE '(' Expr ')' ';'
+ : DO Statement WHILE '(' Expr ')' ';'
{ $$ = yy.Node('DoWhileStatement', $Statement, $Expr,yy.loc([@$,@7])); }
| DO Statement WHILE '(' Expr ')' error
{ $$ = yy.Node('DoWhileStatement', $Statement, $Expr,yy.loc([@$,@6])); }
@@ -888,6 +886,11 @@ IterationStatement
| FOR '(' LeftHandSideExpr INTOKEN Expr ')' Statement
{ $$ = yy.Node('ForInStatement',
$LeftHandSideExpr, $Expr, $Statement, null, yy.loc([@$,@7])); }
+ | FOR '(' OWN INTOKEN Expr ')' Statement
+ { $$ = yy.Node('ForInStatement',
+ yy.Node('Identifier', $3,yy.loc(@3)), $Expr, $Statement, null, yy.loc([@$,@7])); }
+ | FOR '(' OWN LeftHandSideExpr INTOKEN Expr ')' Statement
+ { $$ = yy.Node('ForInStatement', $LeftHandSideExpr, $Expr, $Statement, 'own', yy.loc([@$,@8])); }
| FOR '(' VarOrLet Expr ')' Statement
{ $$ = yy.Node('ForInStatement', $3,
$Expr, $Statement, null, yy.loc([@$,@6])); }
View
31 lib/lexer.l
@@ -6,6 +6,8 @@ IDS [a-zA-Z$_]|"\u"[a-fA-F0-9]{4}
BSL "\\".
RCLASS "["({BSL}|[^\\\]])*"]"
+%x for
+
%%
";"\s+/("++"|"--") return ';'
@@ -52,10 +54,26 @@ RCLASS "["({BSL}|[^\\\]])*"]"
"{" return 'OPENBRACE'
+<for>"{" this.popState(); return 'OPENBRACE';
"}" return 'CLOSEBRACE'
"[" return '['
+<for>"[" this.popState(); return '['
"]" return ']'
"(" return '('
+
+<for>"(" %{
+ if (yy.sawParen) {
+ this.popState();
+ } else {
+ yy.sawParen = true;
+ }
+
+ return '(';
+%}
+
+<for>\s+ yy.ASI = false;
+<for>";" this.popState(); yy.ASI = false; return ";"
+
")" return ')'
"," return ','
"..."/((#{IDS})+(#{IDS}|[0-9])*) return 'SPREAD'
@@ -109,25 +127,28 @@ RCLASS "["({BSL}|[^\\\]])*"]"
"do" return 'DO'
"else" return 'ELSE'
"finally" return 'FINALLY'
-"for" return 'FOR'
-"own" return 'OWN'
+"for" { this.begin("for"); yy.sawParen = false; return 'FOR'; }
+<for>"own" { this.popState(); return 'OWN'; }
"function" return 'FUNCTION'
"if" return 'IF'
"in" return 'INTOKEN'
"instanceof" return 'INSTANCEOF'
-"new" return 'NEW'
+"new" { return 'NEW'; }
+<for>"new" { this.popState(); return 'NEW'; }
"return" yy.ASI = true; return 'RETURN'
"switch" return 'SWITCH'
"try" return 'TRY'
"catch" return 'CATCH'
"throw" yy.ASI = true; return 'THROW'
"typeof" return 'TYPEOF'
-"var" return 'VAR'
+"var" return 'VAR';
+<for>"var" { this.popState(); return 'VAR'; }
"void" return 'VOIDTOKEN'
"while" return 'WHILE'
"with" return 'WITH'
"class" return 'WITH'
"const" return 'CONSTTOKEN'
+<for>"const" { this.popState(); return 'CONSTTOKEN'; }
"enum" return 'ENUM'
"export" return 'EXPORT'
"extends" return 'EXTENDS'
@@ -136,6 +157,7 @@ RCLASS "["({BSL}|[^\\\]])*"]"
"implements" return 'IMPLEMENTS'
"interface" return 'INTERFACE'
"let" return 'LET'
+<for>"let" { this.popState(); return 'LET' }
"package" return 'PACKAGE'
"private" return 'PRIVATE'
"protected" return 'PROTECTED'
@@ -148,6 +170,7 @@ RCLASS "["({BSL}|[^\\\]])*"]"
"false" return 'FALSETOKEN'
"null" return 'NULLTOKEN'
({IDS})+({IDS}|[0-9])* return 'IDENT';
+<for>({IDS})+({IDS}|[0-9])* { this.popState(); return 'IDENT'; }
. return 'INVALID'
%%
View
56 lib/stringify.js
@@ -645,8 +645,12 @@ function sourceElement(n, indent) {
/**
* Extensions
+ *
+ * In general, extensions are handled using a decaf_handle* method that
+ * manipulates the AST and possibly returns some output to insert.
*/
+// handle function(foo, ...bar)
function decaf_handleFunctionDeclSpread(n) {
var len = n.params.length - 1, params = n.params, spread, ast;
@@ -658,31 +662,7 @@ function decaf_handleFunctionDeclSpread(n) {
}
}
-function decaf_handleOwn(n, indent) {
- if (n.own) {
- var leftString = expr(n.left, indent, 0, false), varName, rightString, originalRight;
-
- //console.log(n.right)
-
- if (n.right.callee) {
- rightString = varName = getVar();
- originalRight = n.right;
- n.right = { name: varName, loc: null, type: 'Identifier' }
- } else {
- rightString = expr(n.right, indent, 0, false);
- }
-
- var ast = Reflect.parse("if (!" + rightString + ".hasOwnProperty(" + leftString + ")) { continue; }");
- n.body.body.unshift(ast.body[0]);
-
- if (varName) {
- return indent + varName + " = " + expr(originalRight, indent, 0, false) + ";\n";
- }
- }
-
- return "";
-}
-
+// handle foo(bar, ...baz)
function decaf_handleCallSpread(n, indent, callback) {
var len = n.arguments.length - 1, params = n.arguments, spread, ast;
@@ -721,7 +701,31 @@ function decaf_handleCallSpread(n, indent, callback) {
return calleeString + ".apply(" + thisString + ", " + argString + ")";
}
- return callback()
+ return callback();
+}
+
+// handle for (own foo in bar)
+function decaf_handleOwn(n, indent) {
+ if (n.own) {
+ var leftString = expr(n.left, indent, 0, false), varName, rightString, originalRight;
+
+ if (n.right.callee) {
+ rightString = varName = getVar();
+ originalRight = n.right;
+ n.right = { name: varName, loc: null, type: 'Identifier' }
+ } else {
+ rightString = expr(n.right, indent, 0, false);
+ }
+
+ var ast = Reflect.parse("if (!" + rightString + ".hasOwnProperty(" + leftString + ")) { continue; }");
+ n.body.body.unshift(ast.body[0]);
+
+ if (varName) {
+ return indent + varName + " = " + expr(originalRight, indent, 0, false) + ";\n";
+ }
+ }
+
+ return "";
}
function stringify(n, newIndentChar) {
View
1 test/stringify-test.js
@@ -128,6 +128,7 @@ function runUnitTests() {
" ;\n"),
("for (var i in arr)\n" +
" dump(arr[i]);\n"),
+ ("for (own in boo)\n ;\n"),
('for ([k, v] in items(x))\n' +
' dump(k + ": " + v);\n'),
("if (x) {\n" +

0 comments on commit 873bfe3

Please sign in to comment.
Something went wrong with that request. Please try again.