docs: function Backtracker(input) {
  
      /**
       * Private Variables
       */
      var stream;
  
      /**
       * Streaming Handling
       * ==================
       *
       * Stream - object 
       * ---------------
       * behaves similar to LISP-Pairs
       *
       * notes:
       * - original Input has to be stored separatly in Parser (Backtracker) itself
       *
       * @overload Stream(obj, restStream)
       *   This overload commonly is used to prepend an input to an existing stream
       *   [Object] obj                  any object, that will be used as `first`
       *   [Stream] restStream           the rest of the stream.
       *
       * @overload Stream(streamable, pos?)
       *   Stream is constructed from string or array with optional position
       *   [String, Array] streamable    the object, which should be converted into a stream
       *   [Number] pos                  position of the first element within the streamable 
       *                                 object
       *
       * @return Stream
       */
      function Stream(streamable, rest_or_pos) {
  
        var pos;
  
        // First overload:
        //   Stream(obj, restStream)
        if(rest_or_pos instanceof Stream) {
  
          var restStream = rest_or_pos;
              pos = restStream.pos;
  
          this.first = function() { return streamable; }
          this.rest  = function() { return restStream; }
          this.eos   = function() { return restStream === undefined; }
  
        // Second overload:
        //   Stream(streamable, pos?)
        } else {
  
          var length = streamable.length;
              pos = rest_or_pos || 0;
  
          this.first = function() {
            if(pos >= length)
              throw "End of stream";
            
             return streamable[pos]; 
          }
          this.rest = function() {
            var rest = new Stream(streamable, pos+1);
            // patch rest() to only calculate it once
            this.rest = function() { return rest; }
            return rest;
          }
          this.eos = function() { return pos >= length }
        }
  
        this.pos = function() { return pos; }
  
         // required by capture operator < ... >
        this.upTo = function(other) {
  
          if(typeof streamable === 'string')
            return streamable.slice(pos, other.pos());
  
          var consumed = [],
              current = this;
  
          while(current.pos() < after.pos()) {
            consumed.push(current.first());
            current = current.rest();
          }
          return consumed;
        }
        
        this.input = function() { return streamable; }
      }
  
      stream = new Stream(input);
  
      // only for debug
      //this.stream = function() { return stream }
  
      // Only used by rule anything
      this.consume = function() {
        try {
          var el = stream.first();
          stream = stream.rest();
          return el;
        } catch(e) {
          this.mismatch("End of Stream");
        }      
      }
  
      this.current_state = function() { return stream; }
      this.restore = function(state) { stream = state; }
      this.pos = function() { return stream.pos(); }    
      this.prepend = function(el) { stream = new Stream(el, stream); }
  
      // temporarily replace input by a streamable object (mostly arrays or strings)
      // in order to allow pattern matching on arrays (i.e. rule = [char char foo])
      this.inject = function(streamable) { stream = new Stream(streamable); }
    
      // problem: proxied captures won't work well, because they wont find the end
      this.capture = function(action, context) {
  
        var before = stream,
            after;          
  
        action.call(context);
        after = stream;   
  
        return before.upTo(after); // array of consumed items
      }
  
      this.captureIndex = function(action, context) {
  
        var before = stream,
            after;
  
        action.call(context);
        after = stream;
  
        return context.position_info(input, before.pos(), after.pos());
      }
  
      /**
       * Foreign Rule Invocation
       * =======================
       * Allow to borrow the input stream for foreign rule invocation
       * the stream is proxied to not fall back on old memoization entires
       */
      function Proxied(stream) {
        var rest;
  
        return inherit(stream, {
          original: function() { return stream; },
          rest: function() { 
            return rest ? rest : Proxied(stream.rest()) }
        });
      }
  
      this.borrow = function() {
        stream = Proxied(stream);
        return this;
      }
  
      this.take_back = function() {
        stream = stream.original();
        return this;
      }
      
      /**
       * Memoization
       * ===========
       */
      // Mixin to allow a stream to memoize rules
      function Memoizing(stream) {
  
        var memo = {};
  
        stream.memoize = function(ruleName, result) {
          return memo[ruleName] = result;
        }
  
        stream.remember = function(ruleName) {
          return memo[ruleName];
        }
  
        return stream;
      }
  
      // Is used by memoizer to flag the occurance of recursion
      function Flag() { this.detected = false };
  
      this.memoized = function(ruleName, grammar) {
  
        var memo;
  
        // the stream has not yet been enabled for memoization -> apply Mixin Memoizing
        // hasOwnProperty is needed to recognize proxied streams
        if(!stream.hasOwnProperty('remember') || !typeof stream.remember == 'function') {
          Memoizing(stream);
  
        } else {
          memo = stream.remember(ruleName);
        }
  
        // no memo entry for this rule
        if(memo === undefined) {
  
          var state = this.current_state();
  
          var recursion = new Flag(),
              rule = grammar[ruleName];
          
          if(rule === undefined)
            throw 'Tried to apply undefined rule "' + ruleName + '"';
  
          // Do the seed-pass. Store the flag as memoRecord and apply `rule`
          // for the first time. If rule calls itself recursivly the flag will be used
          // and the recursion will be detected.
          stream.memoize(ruleName, recursion);
          memo = stream.memoize(ruleName, {
            ans:   rule.call(grammar),
            state: this.current_state()
          });
  
          // the recursion flag has been set for this rule -> Recursion detected!
          if(recursion.detected) {
  
            var sentinel = this.current_state(),
                ans;
  
            while(true) {
              // restore-position and reuse the original input
              this.restore(state);
  
              try { ans = rule.call(grammar); } 
              catch (f) { 
                this.catch_mismatch(f);
                break;
              }
  
              // Same point as before
              if(this.current_state() === sentinel) {
                break;
              }
              // update memoRecord            
              memo.state = this.current_state();
              memo.ans   = ans;
            }
          }
  
        // The previous pass has been the seed-pass. Now flag it as recursive
        } else if(memo instanceof Flag) {
          memo.detected = true;
          this.mismatch("Recursion detected applying " + ruleName)
        }
      
        // There is a memo record - than use it
        // return the previous calculated ans and continue where the memoRecord left off
        this.restore(memo.state);
        return memo.ans;
      } 
  
  
      /**
       * Error Reporting
       * ===============
       * Error Reporting is inspired a little bit by PEG.js. It can be improved in future
       * work. For example the position calculating is still buggy and error reporting
       * is not generic enough to work fine with translations.
       */ 
      var latest_mismatch = 0,
          errors = {};
      
      function line_of(string, pos) {
  
        var lines  = 1,
            latest = 0,
            col    = 0;
  
        for(var i=0; i<pos; i++) {
  
          if(string[i] === "\n") {
            lines++;
            col = 0;
            latest = i;
          } else {
            col++;
          }
        }
        return {
          line_no: lines,
          col: col-1,
          line: string.slice(latest, pos+10)
        }
      }
  
      function Mismatch(msg) {
        this.msg = msg;
        this.pos = stream.pos();
      }
      Mismatch.prototype = {
        toString: function(indent) { 
          indent = indent || "";
          return [indent, this.msg, " at position: ", this.pos].join("");
        }
      }
  
      function RuleMismatch(ruleName, beforeState, reason) {
        this.rule = ruleName;
        this.pos = stream.pos();
        this.before = beforeState.pos();
        this.state = beforeState;
      }
      RuleMismatch.prototype = inherit(new Mismatch(), {
        toString: function(indent) {
          var line = line_of(input, this.pos);
          return [indent, "Tried to apply rule '",this.rule,"' at line ",line.line_no," at col ",line.col,"\n",
                  indent, "  ", line.line, "\n",
                  indent, "  ", Array(line.col).join(" "), "^"
                 ].join("")
        }
      });
      
  
      this.mismatch = function(msg, reason) {
        var mismatch = new Mismatch(msg, reason);
        throw mismatch;
      }
  
      this.mismatchRule = function(rule, state, reason) {
  
        var mismatch = new RuleMismatch(rule, state, reason);
  
        if(mismatch.pos > latest_mismatch) {
          errors = {};
          errors[mismatch.rule] = true;
          latest_mismatch = mismatch.pos;
        } else if (mismatch.pos == latest_mismatch) {
          errors[mismatch.rule] = true;
        }
  
        throw mismatch
      }
  
      this.catch_mismatch = function(error) {
        if(!error instanceof Mismatch) 
          throw error;
      }
  
      this.report_errors = function(e) {
    
        if(typeof input === 'string') {
  
          var line = line_of(input, latest_mismatch);
          return ["Could not continue to match at line ",line.line_no," at col ",line.col,"\n",
                  line.line_no,': ', line.line, "\n",
                  Array(line.line_no.toString().length + 2 + line.col+1).join(" "), "^\n\n",
                  "  ", "expected: ", Object.getOwnPropertyNames(errors).sort().join(', ')].join('');
  
        } else {
          return ["Could not continue to match, expected: ", 
                  Object.getOwnPropertyNames(errors).sort().join(', ')].join('');
        }
      }  
    }