diff --git a/extra/peg/ebnf/ebnf.factor b/extra/peg/ebnf/ebnf.factor
index be4beab3f1..ed0dea0410 100644
--- a/extra/peg/ebnf/ebnf.factor
+++ b/extra/peg/ebnf/ebnf.factor
@@ -266,7 +266,7 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   ] [ ] make delay sp ;
 
 : transform-ebnf ( string -- object )
-  'ebnf' [ parse ] packrat-parse parse-result-ast transform ;
+  'ebnf' packrat-parse parse-result-ast transform ;
 
 : check-parse-result ( result -- result )
   dup [
@@ -281,7 +281,7 @@ M: ebnf-non-terminal (transform) ( ast -- parser )
   ] if ;
 
 : ebnf>quot ( string -- hashtable quot )
-  'ebnf' [ parse ] with-packrat check-parse-result 
+  'ebnf' packrat-parse check-parse-result 
   parse-result-ast transform dup main swap at compile 1quotation ;
 
 : [EBNF "EBNF]" parse-multiline-string ebnf>quot nip parsed ; parsing
diff --git a/extra/peg/peg-docs.factor b/extra/peg/peg-docs.factor
index 30e7f0e72f..c93d1af830 100644
--- a/extra/peg/peg-docs.factor
+++ b/extra/peg/peg-docs.factor
@@ -12,7 +12,7 @@ HELP: parse
 { $description 
     "Given the input string, parse it using the given parser. The result is a <parse-result> object if "
     "the parse was successful, otherwise it is f." } 
-{ $see-also compile with-packrat } ;
+{ $see-also compile with-packrat packrat-parse } ;
 
 HELP: with-packrat
 { $values 
@@ -23,8 +23,30 @@ HELP: with-packrat
     "Calls the quotation with a packrat cache in scope. Usually the quotation will "
     "call " { $link parse } " or call a word produced by " { $link compile } "."
     "The cache is used to avoid the possible exponential time performace that pegs "
-    "can have, instead giving linear time at the cost of increased memory usage."  } 
-{ $see-also compile parse } ;
+    "can have, instead giving linear time at the cost of increased memory usage. "
+    "Use of this packrat option also allows direct and indirect recursion to "
+    "be handled in the parser without entering an infinite loop."  } 
+{ $see-also compile parse packrat-parse packrat-call } ;
+
+HELP: packrat-parse
+{ $values 
+  { "input" "a string" } 
+  { "parser" "a parser" } 
+  { "result" "a parse-result or f" } 
+}
+{ $description 
+    "Compiles and calls the parser with a packrat cache in scope."  } 
+{ $see-also compile parse packrat-call with-packrat } ;
+
+HELP: packrat-call
+{ $values 
+  { "input" "a string" } 
+  { "quot" "a quotation with stack effect ( input -- result )" } 
+  { "result" "a parse-result or f" } 
+}
+{ $description 
+    "Calls the compiled parser with a packrat cache in scope."  } 
+{ $see-also compile packrat-call packrat-parse with-packrat } ;
 
 HELP: compile
 { $values 
@@ -36,7 +58,7 @@ HELP: compile
     "The mapping from parser to compiled word is kept in a cache. If you later change "
     "the definition of a parser you'll need to clear this cache with " 
     { $link reset-compiled-parsers } " before using " { $link compile } " on that parser again." } 
-{ $see-also compile with-packrat reset-compiled-parsers } ;
+{ $see-also compile with-packrat reset-compiled-parsers packrat-call packrat-parse } ;
 
 HELP: reset-compiled-parsers
 { $description 
diff --git a/extra/peg/peg.factor b/extra/peg/peg.factor
index e5632d645c..246dbc7962 100755
--- a/extra/peg/peg.factor
+++ b/extra/peg/peg.factor
@@ -67,11 +67,17 @@ GENERIC: (compile) ( parser -- quot )
   [ compiled-parser ] with-compilation-unit ;
 
 : parse ( state parser -- result )
-  compile execute ;
+  compile execute ; inline
 
 : with-packrat ( quot -- result )
   #! Run the quotation with a packrat cache active.
-  [ H{ } clone packrat ] dip with-variable ;
+  [ H{ } clone packrat ] dip with-variable ; inline
+
+: packrat-parse ( state parser -- result )
+  [ parse ] with-packrat ;
+
+: packrat-call ( state quot -- result )
+  with-packrat ; inline
 
 <PRIVATE