From c89bd331636af15d33c1bb0d1ceba51b4d9559d2 Mon Sep 17 00:00:00 2001 From: Matthieu Riou Date: Mon, 3 Aug 2009 18:01:21 -0700 Subject: [PATCH] Unary functions using ~> --- src/org/mozilla/javascript/Parser.java | 32 ++++++++++++++------- src/org/mozilla/javascript/Token.java | 4 ++- src/org/mozilla/javascript/TokenStream.java | 6 +++- src/org/mozilla/javascript/ast/Symbol.java | 1 + 4 files changed, 30 insertions(+), 13 deletions(-) diff --git a/src/org/mozilla/javascript/Parser.java b/src/org/mozilla/javascript/Parser.java index 5729c108..e1dfb1d7 100644 --- a/src/org/mozilla/javascript/Parser.java +++ b/src/org/mozilla/javascript/Parser.java @@ -536,12 +536,12 @@ private AstRoot parse() throws IOException } AstNode n; - if (tt == Token.FUNCTION) { + if (tt == Token.FUNCTION || tt == Token.FUNCTION_UNARY) { consumeToken(); try { n = function(calledByCompileFunction ? FunctionNode.FUNCTION_EXPRESSION - : FunctionNode.FUNCTION_STATEMENT); + : FunctionNode.FUNCTION_STATEMENT, tt == Token.FUNCTION_UNARY); } catch (ParserException e) { break; } @@ -609,8 +609,9 @@ private AstNode parseFunctionBody() break bodyLoop; case Token.FUNCTION: + case Token.FUNCTION_UNARY: consumeToken(); - n = function(FunctionNode.FUNCTION_STATEMENT); + n = function(FunctionNode.FUNCTION_STATEMENT, tt == Token.FUNCTION_UNARY); break; default: n = statement(); @@ -700,7 +701,7 @@ private AstNode parseFunctionBodyExpr() return n; } - private FunctionNode function(int type) + private FunctionNode function(int type, boolean unary) throws IOException { int syntheticType = type; @@ -709,7 +710,7 @@ private FunctionNode function(int type) Name name = null; AstNode memberExprNode = null; - if (matchToken(Token.NAME)) { + if (!unary && matchToken(Token.NAME)) { name = createNameNode(true, Token.NAME); if (!matchToken(Token.LP)) { if (compilerEnv.isAllowMemberExprAsFunctionName()) { @@ -728,7 +729,8 @@ private FunctionNode function(int type) // processed as anonymous function memberExprNode = memberExpr(false); } - mustMatchToken(Token.LP, "msg.no.paren.parms"); + if (!unary) + mustMatchToken(Token.LP, "msg.no.paren.parms"); } int lpPos = currentToken == Token.LP ? ts.tokenBeg : -1; @@ -760,7 +762,12 @@ private FunctionNode function(int type) PerFunctionVariables savedVars = new PerFunctionVariables(fnNode); try { - parseFunctionParams(fnNode); + if (unary) { + fnNode.addParam(new Name(functionSourceStart, 1, "_")); + defineSymbol(Token.LP, "_"); + } else { + parseFunctionParams(fnNode); + } fnNode.setBody(parseFunctionBody()); fnNode.setEncodedSourceBounds(functionSourceStart, ts.tokenEnd); fnNode.setLength(ts.tokenEnd - functionSourceStart); @@ -995,8 +1002,9 @@ && peekToken() == Token.SEMI) return pn; case Token.FUNCTION: + case Token.FUNCTION_UNARY: consumeToken(); - return function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT); + return function(FunctionNode.FUNCTION_EXPRESSION_STATEMENT, tt == Token.FUNCTION_UNARY); case Token.DEFAULT : pn = defaultXmlNamespace(); @@ -1919,7 +1927,7 @@ void defineSymbol(int declType, String name, boolean ignoreNotInBlock) { addError(symDeclType == Token.CONST ? "msg.const.redecl" : symDeclType == Token.LET ? "msg.let.redecl" : symDeclType == Token.VAR ? "msg.var.redecl" : - symDeclType == Token.FUNCTION ? "msg.fn.redecl" : + symDeclType == Token.FUNCTION || symDeclType == Token.FUNCTION_UNARY ? "msg.fn.redecl" : "msg.parm.redecl", name); return; } @@ -1937,6 +1945,7 @@ void defineSymbol(int declType, String name, boolean ignoreNotInBlock) { case Token.VAR: case Token.CONST: case Token.FUNCTION: + case Token.FUNCTION_UNARY: if (symbol != null) { if (symDeclType == Token.VAR) addStrictWarning("msg.var.redecl", name); @@ -2710,7 +2719,8 @@ private AstNode primaryExpr() switch(tt) { case Token.FUNCTION: - return function(FunctionNode.FUNCTION_EXPRESSION); + case Token.FUNCTION_UNARY: + return function(FunctionNode.FUNCTION_EXPRESSION, tt == Token.FUNCTION_UNARY); case Token.LB: return arrayLiteral(); @@ -3078,7 +3088,7 @@ private ObjectProperty getterSetterProperty(int pos, AstNode propName, boolean isGetter) throws IOException { - FunctionNode fn = function(FunctionNode.FUNCTION_EXPRESSION); + FunctionNode fn = function(FunctionNode.FUNCTION_EXPRESSION, false); // We've already parsed the function name, so fn should be anonymous. Name name = fn.getFunctionName(); if (name != null && name.length() != 0) { diff --git a/src/org/mozilla/javascript/Token.java b/src/org/mozilla/javascript/Token.java index 32fc74dc..d85e6d79 100644 --- a/src/org/mozilla/javascript/Token.java +++ b/src/org/mozilla/javascript/Token.java @@ -199,6 +199,7 @@ public static enum CommentType { DEC = 106, DOT = 107, // member operator (.) FUNCTION = 108, // function keyword + FUNCTION_UNARY = 161, // unary ~> function keyword EXPORT = 109, // export keyword IMPORT = 110, // import keyword IF = 111, // if keyword @@ -262,7 +263,7 @@ public static enum CommentType { WITHEXPR = 158, DEBUGGER = 159, COMMENT = 160, - LAST_TOKEN = 160; + LAST_TOKEN = 161; /** * Returns a name for the token. If Rhino is compiled with certain @@ -394,6 +395,7 @@ public static String typeToName(int token) { case DEC: return "DEC"; case DOT: return "DOT"; case FUNCTION: return "FUNCTION"; + case FUNCTION_UNARY: return "FUNCTION_UNARY"; case EXPORT: return "EXPORT"; case IMPORT: return "IMPORT"; case IF: return "IF"; diff --git a/src/org/mozilla/javascript/TokenStream.java b/src/org/mozilla/javascript/TokenStream.java index 90f6db4d..6ffac55b 100644 --- a/src/org/mozilla/javascript/TokenStream.java +++ b/src/org/mozilla/javascript/TokenStream.java @@ -819,7 +819,11 @@ final int getToken() throws IOException } case '~': - return Token.BITNOT; + if (matchChar('>')) { + return Token.FUNCTION_UNARY; + } else { + return Token.BITNOT; + } case '+': if (matchChar('=')) { diff --git a/src/org/mozilla/javascript/ast/Symbol.java b/src/org/mozilla/javascript/ast/Symbol.java index 3ca5c9c7..33753444 100644 --- a/src/org/mozilla/javascript/ast/Symbol.java +++ b/src/org/mozilla/javascript/ast/Symbol.java @@ -82,6 +82,7 @@ public int getDeclType() { */ public void setDeclType(int declType) { if (!(declType == Token.FUNCTION + || declType == Token.FUNCTION_UNARY || declType == Token.LP || declType == Token.VAR || declType == Token.LET