AST Function(AST parent, FunctionType ft) { FunctionType synthetic_type = ft; string name; AST member_expr = null; if (ts.MatchToken (Token.NAME)) { name = ts.GetString; if (!ts.MatchToken (Token.LP)) { if (allow_member_expr_as_function_name) { // Extension to ECMA: if 'function <name>' does not follow // by '(', assume <name> starts memberExpr // FIXME: is StringLiteral the correct AST to build? decompiler.AddName (name); AST member_expr_head = new StringLiteral (null, name, new Location (ts.SourceName, ts.LineNumber)); name = ""; member_expr = MemberExprTail (parent, false, member_expr_head); } MustMatchToken (Token.LP, "msg.no.paren.parms"); } } else if (ts.MatchToken (Token.LP)) { // Anonymous function name = ""; } else { name = ""; if (allow_member_expr_as_function_name) { // Note that memberExpr can not start with '(' like // in function (1+2).toString(), because 'function (' already // processed as anonymous function member_expr = MemberExpr (parent, false); } MustMatchToken (Token.LP, "msg.no.paren.parms"); } if (member_expr != null) { synthetic_type = FunctionType.Expression; decompiler.AddToken (Token.ASSIGN); } bool nested = InsideFunction; Function fn = CreateFunction (parent, synthetic_type, name); if (nested) fn.CheckThis = true; if (nested || nesting_of_with > 0) { // 1. Nested functions are not affected by the dynamic scope flag // as dynamic scope is already a parent of their scope. // 2. Functions defined under the with statement also immune to // this setup, in which case dynamic scope is ignored in favor // of with object. fn.IgnoreDynamicScope = true; } // FIXME: which is old version of Decompiler.MarkFunctionStart int functionSourceStart = decompiler.MarkFunctionStart ((int) synthetic_type); if (name != "") decompiler.AddName (name); int saved_nesting_of_with = nesting_of_with; nesting_of_with = 0; FormalParameterList _params = new FormalParameterList (new Location (ts.SourceName, ts.LineNumber)); Block body; try { decompiler.AddToken (Token.LP); if (!ts.MatchToken (Token.RP)) { bool first = true; do { if (!first) decompiler.AddToken (Token.COMMA); first = false; MustMatchToken (Token.NAME, "msg.no.parm"); string s = ts.GetString; _params.Add (s, String.Empty, new Location (ts.SourceName, ts.LineNumber)); decompiler.AddName (s); } while (ts.MatchToken (Token.COMMA)); MustMatchToken (Token.RP, "msg.no.paren.after.parms"); } decompiler.AddToken (Token.RP); MustMatchToken (Token.LC, "msg.no.brace.body"); decompiler.AddEOL (Token.LC); body = ParseFunctionBody (fn); MustMatchToken (Token.RC, "msg.no.brace.after.body"); decompiler.AddToken (Token.RC); decompiler.MarkFunctionEnd (functionSourceStart); fn.func_obj.source = decompiler.SourceToString (functionSourceStart); if (ft != FunctionType.Expression) { CheckWellTerminatedFunction (); if (member_expr == null) decompiler.AddToken (Token.EOL); else decompiler.AddEOL (Token.SEMI); } } finally { nesting_of_with = saved_nesting_of_with; } fn.Init (body, _params); AST pn; if (member_expr == null) { // FIXME pn = fn; // FIXME, research about createExprStatementNoReturn if (ft == FunctionType.ExpressionStatement) pn = null; } else { // FIXME pn = fn; Assign assign = new Assign (null, JSToken.Assign, new Location (ts.SourceName, ts.LineNumber)); assign.Init (member_expr, pn, false); pn = assign; #if false // FIXME, research about createExprStatement if (ft != FunctionType.Expression) ; #endif } return pn; }
AST AssignExpr(AST parent, bool in_for_init) { AST pn = CondExpr (parent, in_for_init); int tt = ts.PeekToken (); // omitted: "invalid assignment left-hand side" check. if (tt == Token.ASSIGN) { ts.GetToken (); decompiler.AddToken (Token.ASSIGN); Assign assign = new Assign (parent, JSToken.Assign, new Location (ts.SourceName, ts.LineNumber)); assign.Init (pn, AssignExpr (assign, in_for_init), false); pn = assign; return pn; } else if (tt == Token.ASSIGNOP) { ts.GetToken (); int op = ts.GetOp (); decompiler.AddAssignOp (op); Assign assign = new Assign (parent, ToJSToken (op, tt), new Location (ts.SourceName, ts.LineNumber)); assign.Init (pn, AssignExpr (assign, in_for_init), false); pn = assign; } return pn; }