public override bool Parse(ParseContext context, IAstNode parent) { while (!context.Tokens.IsEndOfStream()) { if (context.Tokens.CurrentToken.TokenType == _terminatingTokenType) { break; } if (RParser.IsListTerminator(context, RParser.GetOpeningTokenType(_terminatingTokenType), context.Tokens.CurrentToken)) { AddStubArgument(context); break; } var item = this.CreateItem(this, context); if (item != null) { var currentPosition = context.Tokens.Position; if (item.Parse(context, this)) { _arguments.Add(item); } else { // Item could not be parser. We attempt to recover by // walking forward and finding the nearest comma // that can be used as a terminator for this argument. if (!AddErrorArgument(context, currentPosition)) { // Failed to figure out the recovery point break; } } } else { AddStubArgument(context); break; // unexpected item } } if (_arguments.Count > 0 && _arguments[_arguments.Count - 1].Comma != null) { AddStubArgument(context); } // Do not include empty list in the tree since // it has no positioning information. if (_arguments.Count > 1 || (_arguments.Count == 1 && !(_arguments[0] is StubArgument))) { return(base.Parse(context, parent)); } return(true); }