mirror of
https://github.com/django/django.git
synced 2025-10-31 09:41:08 +00:00
Fixed #24372 - Replaced TokenParser usage with traditional parsing.
This commit is contained in:
committed by
Tim Graham
parent
8ca35d7c6a
commit
358850781f
@@ -431,122 +431,6 @@ class Parser(object):
|
||||
raise TemplateSyntaxError("Invalid filter: '%s'" % filter_name)
|
||||
|
||||
|
||||
class TokenParser(object):
|
||||
"""
|
||||
Subclass this and implement the top() method to parse a template line.
|
||||
When instantiating the parser, pass in the line from the Django template
|
||||
parser.
|
||||
|
||||
The parser's "tagname" instance-variable stores the name of the tag that
|
||||
the filter was called with.
|
||||
"""
|
||||
def __init__(self, subject):
|
||||
self.subject = subject
|
||||
self.pointer = 0
|
||||
self.backout = []
|
||||
self.tagname = self.tag()
|
||||
|
||||
def top(self):
|
||||
"""
|
||||
Overload this method to do the actual parsing and return the result.
|
||||
"""
|
||||
raise NotImplementedError('subclasses of Tokenparser must provide a top() method')
|
||||
|
||||
def more(self):
|
||||
"""
|
||||
Returns True if there is more stuff in the tag.
|
||||
"""
|
||||
return self.pointer < len(self.subject)
|
||||
|
||||
def back(self):
|
||||
"""
|
||||
Undoes the last microparser. Use this for lookahead and backtracking.
|
||||
"""
|
||||
if not len(self.backout):
|
||||
raise TemplateSyntaxError("back called without some previous "
|
||||
"parsing")
|
||||
self.pointer = self.backout.pop()
|
||||
|
||||
def tag(self):
|
||||
"""
|
||||
A microparser that just returns the next tag from the line.
|
||||
"""
|
||||
subject = self.subject
|
||||
i = self.pointer
|
||||
if i >= len(subject):
|
||||
raise TemplateSyntaxError("expected another tag, found "
|
||||
"end of string: %s" % subject)
|
||||
p = i
|
||||
while i < len(subject) and subject[i] not in (' ', '\t'):
|
||||
i += 1
|
||||
s = subject[p:i]
|
||||
while i < len(subject) and subject[i] in (' ', '\t'):
|
||||
i += 1
|
||||
self.backout.append(self.pointer)
|
||||
self.pointer = i
|
||||
return s
|
||||
|
||||
def value(self):
|
||||
"""
|
||||
A microparser that parses for a value: some string constant or
|
||||
variable name.
|
||||
"""
|
||||
subject = self.subject
|
||||
i = self.pointer
|
||||
|
||||
def next_space_index(subject, i):
|
||||
"""
|
||||
Increment pointer until a real space (i.e. a space not within
|
||||
quotes) is encountered
|
||||
"""
|
||||
while i < len(subject) and subject[i] not in (' ', '\t'):
|
||||
if subject[i] in ('"', "'"):
|
||||
c = subject[i]
|
||||
i += 1
|
||||
while i < len(subject) and subject[i] != c:
|
||||
i += 1
|
||||
if i >= len(subject):
|
||||
raise TemplateSyntaxError("Searching for value. "
|
||||
"Unexpected end of string in column %d: %s" %
|
||||
(i, subject))
|
||||
i += 1
|
||||
return i
|
||||
|
||||
if i >= len(subject):
|
||||
raise TemplateSyntaxError("Searching for value. Expected another "
|
||||
"value but found end of string: %s" %
|
||||
subject)
|
||||
if subject[i] in ('"', "'"):
|
||||
p = i
|
||||
i += 1
|
||||
while i < len(subject) and subject[i] != subject[p]:
|
||||
i += 1
|
||||
if i >= len(subject):
|
||||
raise TemplateSyntaxError("Searching for value. Unexpected "
|
||||
"end of string in column %d: %s" %
|
||||
(i, subject))
|
||||
i += 1
|
||||
|
||||
# Continue parsing until next "real" space,
|
||||
# so that filters are also included
|
||||
i = next_space_index(subject, i)
|
||||
|
||||
res = subject[p:i]
|
||||
while i < len(subject) and subject[i] in (' ', '\t'):
|
||||
i += 1
|
||||
self.backout.append(self.pointer)
|
||||
self.pointer = i
|
||||
return res
|
||||
else:
|
||||
p = i
|
||||
i = next_space_index(subject, i)
|
||||
s = subject[p:i]
|
||||
while i < len(subject) and subject[i] in (' ', '\t'):
|
||||
i += 1
|
||||
self.backout.append(self.pointer)
|
||||
self.pointer = i
|
||||
return s
|
||||
|
||||
# This only matches constant *strings* (things in quotes or marked for
|
||||
# translation). Numbers are treated as variables for implementation reasons
|
||||
# (so that they retain their type when passed to filters).
|
||||
|
||||
Reference in New Issue
Block a user