void (@NotNull SyntaxTreeBuilder.Marker expr, boolean isSlice) { SyntaxTreeBuilder.Marker sliceOrTupleStart = myBuilder.mark(); SyntaxTreeBuilder.Marker sliceItemStart = myBuilder.mark(); if (atToken(PyTokenTypes.COLON)) { sliceOrTupleStart.drop(); SyntaxTreeBuilder.Marker sliceMarker = myBuilder.mark(); sliceMarker.done(PyElementTypes.EMPTY_EXPRESSION); parseSliceEnd(expr, sliceItemStart); } else { var hadExpression = isSlice ? parseSingleExpression(false) : parseNamedTestExpression(false, false); if (atToken(PyTokenTypes.COLON)) { if (!isSlice) { sliceOrTupleStart.rollbackTo(); parseSliceOrSubscriptionExpression(expr, true); return; } sliceOrTupleStart.drop(); parseSliceEnd(expr, sliceItemStart); } else if (atToken(PyTokenTypes.COMMA)) { sliceItemStart.done(PyElementTypes.SLICE_ITEM); if (!parseSliceListTail(expr, sliceOrTupleStart)) { sliceOrTupleStart.rollbackTo(); if (!parseTupleExpression(false, false, false)) { myBuilder.error(message("tuple.expression.expected")); } checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION); } } else { if (!hadExpression) { myBuilder.error(message("PARSE.expected.expression")); } sliceOrTupleStart.drop(); sliceItemStart.drop(); checkMatches(PyTokenTypes.RBRACKET, message("PARSE.expected.rbracket")); expr.done(PyElementTypes.SUBSCRIPTION_EXPRESSION); } } }