             }
         } catch {
             if matches == 0 && skippable {
-                let lexerContext = lexer.proceed()
-                let result = MatchResult.ignoreFailure(atIndex: lexerContext.range.lowerBound)
+                lexer.rewind()
+                let result = MatchResult.ignoreFailure(atIndex: lexer.index)
                 if structural {
                     ir.didEvaluate(token: produces, annotations: annotations, matchResult: result)
                 }

                        throw error
                    }
                }
                if behaviour.negate {
                    throw TestError(with: behaviour, and: annotations, whenUsing: lexer, causes: nil)
                }

        do {
            while unlimited || matches < behaviour.cardinality.maximumMatches! {
                do {
                    //If the match is negated success means we need to rewind afterwards
                    if behaviour.negate {
                        lexer.mark()
                    }

                    if lexer.endOfInput {
                        throw TestError.scanningError(message: "End of input", position: lexer.index, causes: [])
                    }

                    try matcher(lexer, ir)

                    //If it's negated and did match (in this case didn't throw) then we should rewind because we added an extra mark earlier
                    if behaviour.negate {
                        lexer.rewind()
                    }
                } catch {
                    if behaviour.negate {
                        //We had taken an extra mark due to negation earlier, now we have to take it out
                        lexer.rewind()
                        matches += 1
                        try lexer.scanNext()
                        continue
