internal static CodeNode Parse(ParseInfo state, ref int index) { int i = index; if (!Parser.Validate(state.Code, "with (", ref i) && !Parser.Validate(state.Code, "with(", ref i)) { return(null); } if (state.Strict) { ExceptionHelper.Throw((new SyntaxError("WithStatement is not allowed in strict mode."))); } state.Message?.Invoke(MessageLevel.CriticalWarning, index, 4, "Do not use \"with\"."); var obj = Parser.Parse(state, ref i, CodeFragmentType.Expression); while (Tools.IsWhiteSpace(state.Code[i])) { i++; } if (state.Code[i] != ')') { ExceptionHelper.Throw((new SyntaxError("Invalid syntax WithStatement."))); } do { i++; }while (Tools.IsWhiteSpace(state.Code[i])); CodeNode body = null; VariableDescriptor[] vars = null; var oldVariablesCount = state.Variables.Count; state.LexicalScopeLevel++; var oldCodeContext = state.CodeContext; state.CodeContext |= CodeContext.InWith; try { body = Parser.Parse(state, ref i, 0); vars = CodeBlock.extractVariables(state, oldVariablesCount); body = new CodeBlock(new[] { body }) { _variables = vars, Position = body.Position, Length = body.Length }; } finally { state.LexicalScopeLevel--; state.CodeContext = oldCodeContext; } var pos = index; index = i; return(new With { _scope = obj, _body = body, Position = pos, Length = index - pos }); }
internal static CodeNode Parse(ParseInfo state, ref int index) { int i = index; if (!Parser.Validate(state.Code, "switch (", ref i) && !Parser.Validate(state.Code, "switch(", ref i)) { return(null); } while (Tools.IsWhiteSpace(state.Code[i])) { i++; } var body = new List <CodeNode>(); var funcs = new List <FunctionDefinition>(); var cases = new List <SwitchCase>(); CodeNode result = null; cases.Add(new SwitchCase { index = int.MaxValue }); state.AllowBreak.Push(true); var oldVariablesCount = state.Variables.Count; VariableDescriptor[] vars = null; state.LexicalScopeLevel++; try { var image = ExpressionTree.Parse(state, ref i); if (state.Code[i] != ')') { ExceptionHelper.Throw((new SyntaxError("Expected \")\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } do { i++; }while (Tools.IsWhiteSpace(state.Code[i])); if (state.Code[i] != '{') { ExceptionHelper.Throw((new SyntaxError("Expected \"{\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } do { i++; }while (Tools.IsWhiteSpace(state.Code[i])); while (state.Code[i] != '}') { do { if (Parser.Validate(state.Code, "case", i) && Parser.IsIdentifierTerminator(state.Code[i + 4])) { i += 4; while (Tools.IsWhiteSpace(state.Code[i])) { i++; } var sample = ExpressionTree.Parse(state, ref i); if (state.Code[i] != ':') { ExceptionHelper.Throw((new SyntaxError("Expected \":\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } i++; cases.Add(new SwitchCase { index = body.Count, statement = sample }); } else if (Parser.Validate(state.Code, "default", i) && Parser.IsIdentifierTerminator(state.Code[i + 7])) { i += 7; while (Tools.IsWhiteSpace(state.Code[i])) { i++; } if (cases[0].index != int.MaxValue) { ExceptionHelper.Throw((new SyntaxError("Duplicate default case in switch at " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } if (state.Code[i] != ':') { ExceptionHelper.Throw((new SyntaxError("Expected \":\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } i++; cases[0].index = body.Count; } else { break; } while (Tools.IsWhiteSpace(state.Code[i]) || (state.Code[i] == ';')) { i++; } } while (true); if (cases.Count == 1 && cases[0].index == int.MaxValue) { ExceptionHelper.Throw((new SyntaxError("Switch statement must contain cases. " + CodeCoordinates.FromTextPosition(state.Code, index, 0)))); } var t = Parser.Parse(state, ref i, 0); if (t == null) { continue; } body.Add(t); while (Tools.IsWhiteSpace(state.Code[i]) || (state.Code[i] == ';')) { i++; } } state.AllowBreak.Pop(); i++; var pos = index; index = i; result = new Switch(body.ToArray()) { Functions = funcs.ToArray(), Cases = cases.ToArray(), image = image, Position = pos, Length = index - pos }; vars = CodeBlock.extractVariables(state, oldVariablesCount); } finally { state.LexicalScopeLevel--; } return(new CodeBlock(new[] { result }) { _variables = vars, Position = result.Position, Length = result.Length }); }
internal static CodeNode Parse(ParseInfo state, ref int index) { int i = index; Tools.SkipSpaces(state.Code, ref i); if (!Parser.Validate(state.Code, "for(", ref i) && (!Parser.Validate(state.Code, "for (", ref i))) { return(null); } Tools.SkipSpaces(state.Code, ref i); var result = new ForOf { _labels = state.Labels.GetRange(state.Labels.Count - state.LabelsCount, state.LabelsCount).ToArray() }; VariableDescriptor[] vars = null; var oldVariablesCount = state.Variables.Count; state.LexicalScopeLevel++; try { var vStart = i; result._variable = VariableDefinition.Parse(state, ref i, true); if (result._variable == null) { if (state.Code[i] == ';') { return(null); } Tools.SkipSpaces(state.Code, ref i); int start = i; if (!Parser.ValidateName(state.Code, ref i, state.Strict)) { return(null); } var varName = Tools.Unescape(state.Code.Substring(start, i - start), state.Strict); if (state.Strict) { if (varName == "arguments" || varName == "eval") { ExceptionHelper.ThrowSyntaxError("Parameters name may not be \"arguments\" or \"eval\" in strict mode at ", state.Code, start, i - start); } } result._variable = new Variable(varName, state.LexicalScopeLevel) { Position = start, Length = i - start, ScopeLevel = state.LexicalScopeLevel }; Tools.SkipSpaces(state.Code, ref i); if (state.Code[i] == '=') { Tools.SkipSpaces(state.Code, ref i); var defVal = ExpressionTree.Parse(state, ref i, false, false, false, true, true); if (defVal == null) { return(null); } Expression exp = new AssignmentOperatorCache((Variable)result._variable); exp = new Assignment(exp, defVal) { Position = exp.Position, Length = defVal.EndPosition - exp.Position }; if (result._variable == exp._left._left) { result._variable = exp; } else { (result._variable as VariableDefinition)._initializers[0] = exp; } Tools.SkipSpaces(state.Code, ref i); } } if (!Parser.Validate(state.Code, "of", ref i)) { if (oldVariablesCount < state.Variables.Count) { state.Variables.RemoveRange(oldVariablesCount, state.Variables.Count - oldVariablesCount); } return(null); } state.LabelsCount = 0; Tools.SkipSpaces(state.Code, ref i); if (result._variable is VariableDefinition) { if ((result._variable as VariableDefinition)._variables.Length > 1) { ExceptionHelper.ThrowSyntaxError("Too many variables in for-of loop", state.Code, i); } } result._source = Parser.Parse(state, ref i, CodeFragmentType.Expression); Tools.SkipSpaces(state.Code, ref i); if (state.Code[i] != ')') { ExceptionHelper.Throw((new SyntaxError("Expected \")\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } i++; state.AllowBreak.Push(true); state.AllowContinue.Push(true); result._body = Parser.Parse(state, ref i, 0); state.AllowBreak.Pop(); state.AllowContinue.Pop(); result.Position = index; result.Length = i - index; index = i; vars = CodeBlock.extractVariables(state, oldVariablesCount); } finally { state.LexicalScopeLevel--; } return(new CodeBlock(new[] { result }) { _variables = vars, Position = result.Position, Length = result.Length }); }
internal static CodeNode Parse(ParseInfo state, ref int index) { int i = index; while (Tools.IsWhiteSpace(state.Code[i])) { i++; } if (!Parser.Validate(state.Code, "for(", ref i) && (!Parser.Validate(state.Code, "for (", ref i))) { return(null); } while (Tools.IsWhiteSpace(state.Code[i])) { i++; } CodeNode init = null; CodeNode body = null; CodeNode condition = null; CodeNode post = null; CodeNode result = null; var labelsCount = state.LabelsCount; var oldVariablesCount = state.Variables.Count; state.LabelsCount = 0; state.LexicalScopeLevel++; try { init = VariableDefinition.Parse(state, ref i, true) ?? ExpressionTree.Parse(state, ref i, forForLoop: true); if (init is ExpressionTree && (init as ExpressionTree).Type == OperationType.None && (init as ExpressionTree)._right == null) { init = (init as ExpressionTree)._left; } if (state.Code[i] != ';') { ExceptionHelper.Throw((new SyntaxError("Expected \";\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } do { i++; }while (Tools.IsWhiteSpace(state.Code[i])); condition = state.Code[i] == ';' ? null : ExpressionTree.Parse(state, ref i, forForLoop: true); if (state.Code[i] != ';') { ExceptionHelper.Throw((new SyntaxError("Expected \";\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } do { i++; }while (Tools.IsWhiteSpace(state.Code[i])); post = state.Code[i] == ')' ? null : ExpressionTree.Parse(state, ref i, forForLoop: true); while (Tools.IsWhiteSpace(state.Code[i])) { i++; } if (state.Code[i] != ')') { ExceptionHelper.Throw((new SyntaxError("Expected \";\" at + " + CodeCoordinates.FromTextPosition(state.Code, i, 0)))); } i++; Tools.SkipSpaces(state.Code, ref i); state.AllowBreak.Push(true); state.AllowContinue.Push(true); try { body = Parser.Parse(state, ref i, 0); var vds = body as VariableDefinition; if (vds != null) { if (vds.Kind >= VariableKind.ConstantInLexicalScope) { ExceptionHelper.ThrowSyntaxError("Block scope variables can not be declared in for-loop directly", state.Code, body.Position); } state.Message?.Invoke(MessageLevel.Warning, body.Position, body.Length, "Do not declare variables in for-loop directly"); } } finally { state.AllowBreak.Pop(); state.AllowContinue.Pop(); } int startPos = index; index = i; result = new For { _body = body, _condition = condition, _initializer = init, _post = post, labels = state.Labels.GetRange(state.Labels.Count - labelsCount, labelsCount).ToArray(), Position = startPos, Length = index - startPos }; var vars = CodeBlock.extractVariables(state, oldVariablesCount); result = new CodeBlock(new[] { result }) { _variables = vars, Position = result.Position, Length = result.Length }; } finally { state.LexicalScopeLevel--; } return(result); }