 
 : with-packrat ( quot -- result )
   #! Run the quotation with a packrat cache active.
-  [ H{ } clone packrat ] dip with-variable ; inline
+  H{ } clone \ heads [ [ H{ } clone packrat ] dip with-variable ] with-variable ; inline
 
 : packrat-parse ( state parser -- result )
   [ parse ] with-packrat ;

    f
  ] if 
  "<<handle-left-recursive-result " write dup . ;
         
:: grow-lr ( input quot parser m -- result )
  #! 'Grow the Seed' algorithm to handle left recursion
  ">>grow-lr " write input . " for parser " write parser . " m is " write m . 
  [let* | ans [ input quot call ] |
    [ ans not ] [ ans [ ans remaining>> input-from m remaining>> input-from <= ] [ f ] if ] 2array || [ 
      "recursion exiting with = " write ans . "m was " write m . 
      ans        
    ] [
      "recursion with = " write ans . 
      input quot ans grow-lr
    ] if
  ] 
  "<<grow-lr " write input . " for parser " write parser . " m is " write m . " result is " write dup .  
  ;

:: cached-result ( input-cache input quot parser -- result )
  #! Get the cached result for input position 

  parse-result construct-boa ;

SYMBOL: packrat
SYMBOL: lrstack

TUPLE: phead rule involved-set eval-set ;
C: <head> phead 

: input-from ( input -- n )
  #! Return the index from the original string that the
  #! input slice is based on.
  dup slice? [ slice-from ] [ drop 0 ] if ;

: heads ( input -- h )
  input-from \ heads get at ;


: compiled-parsers ( -- cache )
  \ compiled-parsers get-global [ H{ } clone dup \ compiled-parsers set-global ] unless* ;

: reset-compiled-parsers ( -- )
  H{ } clone \ compiled-parsers set-global ;

GENERIC: (compile) ( parser -- quot )

: input-cache ( id -- cache )
  #! From the packrat cache, obtain the cache for the parser quotation 
  #! that maps the input string position to the parser result.
  packrat get [ drop H{ } clone ] cache ;

TUPLE: left-recursion seed rule head next ;
C: <left-recursion> left-recursion

USE: prettyprint
