Source code for pyndn.util.regex.ndn_regex_repeat_matcher
# -*- Mode:python; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
#
# Copyright (C) 2017-2019 Regents of the University of California.
# Author: Yingdi Yu <http://irl.cs.ucla.edu/~yingdi/>
# Author: Jeff Thompson <[email protected]>
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# A copy of the GNU Lesser General Public License is in the file COPYING.
import re
from pyndn.util.regex.ndn_regex_matcher_base import NdnRegexMatcherBase
[docs]class NdnRegexRepeatMatcher(NdnRegexMatcherBase):
"""
Create an NdnRegexRepeatMatcher.
:param str expr:
:param NdnRegexBackrefManager backrefManager:
:param int indicator:
"""
def __init__(self, expr, backrefManager, indicator):
super(NdnRegexRepeatMatcher, self).__init__(
expr, NdnRegexMatcherBase.NdnRegexExprType.REPEAT_PATTERN, backrefManager)
self._repeatMin = 0
self._repeatMax = 0
self._indicator = indicator
self._compile()
[docs] def match(self, name, offset, length):
"""
:param Name name:
:param int offset:
:param int length:
:rtype: bool
"""
self._matchResult = []
if 0 == self._repeatMin:
if 0 == length:
return True
if self._recursiveMatch2(0, name, offset, length):
for i in range(offset, offset + length):
self._matchResult.append(name.get(i))
return True
else:
return False
def _compile(self):
"""
Compile the regular expression to generate more matchers when necessary.
"""
if '(' == self._expr[0]:
matcher = NdnRegexBackrefMatcher(
self._expr[0 : self._indicator], self._backrefManager)
self._backrefManager.pushRef(matcher)
matcher.lateCompile()
else:
matcher = NdnRegexComponentSetMatcher(
self._expr[0 : self._indicator], self._backrefManager)
self._matchers.append(matcher)
self._parseRepetition()
def _parseRepetition(self):
exprSize = len(self._expr)
MAX_REPETITIONS = 32767
if exprSize == self._indicator:
self._repeatMin = 1
self._repeatMax = 1
return True
else:
if exprSize == self._indicator + 1:
if '?' == self._expr[self._indicator]:
self._repeatMin = 0
self._repeatMax = 1
return True
if '+' == self._expr[self._indicator]:
self._repeatMin = 1
self._repeatMax = MAX_REPETITIONS
return True
if '*' == self._expr[self._indicator]:
self._repeatMin = 0
self._repeatMax = MAX_REPETITIONS
return True
else:
repeatStruct = self._expr[self._indicator : exprSize]
rsSize = len(repeatStruct)
min = 0
max = 0
if re.match("\\{[0-9]+,[0-9]+\\}", repeatStruct) != None:
separator = repeatStruct.index(',')
min = int(repeatStruct[1 : separator])
max = int(repeatStruct[separator + 1 : rsSize - 1])
elif re.match("\\{,[0-9]+\\}", repeatStruct) != None:
separator = repeatStruct.index(',')
min = 0
max = int(repeatStruct[separator + 1 : rsSize - 1])
elif re.match("\\{[0-9]+,\\}", repeatStruct) != None:
separator = repeatStruct.index(',')
min = int(repeatStruct[1 : separator])
max = MAX_REPETITIONS
elif re.match("\\{[0-9]+\\}", repeatStruct) != None:
min = int(repeatStruct[1 : rsSize - 1])
max = min
else:
raise NdnRegexMatcherBase.Error(
"Error: RegexRepeatMatcher.ParseRepetition(): Unrecognized format " +
self._expr)
if min > MAX_REPETITIONS or max > MAX_REPETITIONS or min > max:
raise NdnRegexMatcherBase.Error(
"Error: RegexRepeatMatcher.ParseRepetition(): Wrong number " +
self._expr)
self._repeatMin = min
self._repeatMax = max
return True
return False
def _recursiveMatch2(self, repeat, name, offset, length):
"""
:param int repeat:
:param Name name:
:param int offset:
:param int length:
:rtype bool:
"""
tried = length
matcher = self._matchers[0]
if 0 < length and repeat >= self._repeatMax:
return False
if 0 == length and repeat < self._repeatMin:
return False
if 0 == length and repeat >= self._repeatMin:
return True
while tried >= 0:
if (matcher.match(name, offset, tried) and
self._recursiveMatch2(repeat + 1, name, offset + tried,
length - tried)):
return True
tried -= 1
return False
# Put these last to avoid an import loop.
from pyndn.util.regex.ndn_regex_backref_matcher import NdnRegexBackrefMatcher
from pyndn.util.regex.ndn_regex_component_set_matcher import NdnRegexComponentSetMatcher