summaryrefslogtreecommitdiff
path: root/pyparsing/core.py
diff options
context:
space:
mode:
authorMax Fischer <maxfischer2781@gmail.com>2021-06-28 15:22:32 +0200
committerMax Fischer <maxfischer2781@gmail.com>2021-06-28 15:22:32 +0200
commit118e8b9dd0ba3bc4c8e2052decacf31f0471bd58 (patch)
tree582c66146c17515eb1e213c76900bde3acb9b0af /pyparsing/core.py
parent5a4d58c7ca4b1f35f60f8ba0b8774e6cb3d24cf6 (diff)
downloadpyparsing-git-118e8b9dd0ba3bc4c8e2052decacf31f0471bd58.tar.gz
left recursion memo size may be limited
Diffstat (limited to 'pyparsing/core.py')
-rw-r--r--pyparsing/core.py13
1 files changed, 12 insertions, 1 deletions
diff --git a/pyparsing/core.py b/pyparsing/core.py
index 4b4a437..c346aeb 100644
--- a/pyparsing/core.py
+++ b/pyparsing/core.py
@@ -1,6 +1,7 @@
#
# core.py
#
+from typing import Optional
from abc import ABC, abstractmethod
from enum import Enum
import string
@@ -23,6 +24,8 @@ from .util import (
_escapeRegexRangeChars,
_bslash,
_flatten,
+ LRUMemo as _LRUMemo,
+ UnboundedMemo as _UnboundedMemo,
)
from .exceptions import *
from .actions import *
@@ -790,7 +793,7 @@ class ParserElement(ABC):
ParserElement._parse = ParserElement._parseNoCache
@staticmethod
- def enable_left_recursion(*, force=False):
+ def enable_left_recursion(cache_size_limit: Optional[int] = None, *, force=False):
"""
Enables "bounded recursion" parsing, which allows for both direct and indirect
left-recursion. During parsing, left-recursive :class:`Forward` elements are
@@ -821,6 +824,12 @@ class ParserElement(ABC):
ParserElement.disable_memoization()
elif ParserElement._packratEnabled:
raise RuntimeError("Packrat and Bounded Recursion are not compatible")
+ if cache_size_limit is None:
+ ParserElement.recursion_memos = _UnboundedMemo()
+ elif cache_size_limit > 0:
+ ParserElement.recursion_memos = _LRUMemo(capacity=cache_size_limit)
+ else:
+ raise NotImplementedError("Memo size of %s" % cache_size_limit)
ParserElement._left_recursion_enabled = True
@staticmethod
@@ -4505,7 +4514,9 @@ class Forward(ParseElementEnhance):
# replace the match for doActions=False as well,
# in case the action did backtrack
prev_loc, prev_result = memo[peek_key] = memo[act_key]
+ del memo[peek_key], memo[act_key]
return prev_loc, prev_result.copy()
+ del memo[peek_key]
return prev_loc, prev_peek.copy()
# the match did get better: see if we can improve further
else: