in tapestry-framework/src/org/apache/tapestry/parse/TemplateParser.java [1296:1409]
private void closeTag() throws TemplateParseException
{
int cursorStart = _cursor;
int length = _templateData.length;
int startLine = _line;
ILocation startLocation = getCurrentLocation();
_cursor += CLOSE_TAG.length;
int tagStart = _cursor;
while (true)
{
if (_cursor >= length)
templateParseProblem(
Tapestry.format("TemplateParser.incomplete-close-tag", Integer.toString(startLine)),
startLocation,
startLine,
cursorStart);
char ch = _templateData[_cursor];
if (ch == '>')
break;
advance();
}
String tagName = new String(_templateData, tagStart, _cursor - tagStart);
int stackPos = _stack.size() - 1;
Tag tag = null;
while (stackPos >= 0)
{
tag = (Tag) _stack.get(stackPos);
if (tag.match(tagName))
break;
if (tag._mustBalance)
templateParseProblem(
Tapestry.format(
"TemplateParser.improperly-nested-close-tag",
new Object[] {
tagName,
Integer.toString(startLine),
tag._tagName,
Integer.toString(tag._line)}),
startLocation,
startLine,
cursorStart);
stackPos--;
}
if (stackPos < 0)
templateParseProblem(
Tapestry.format("TemplateParser.unmatched-close-tag", tagName, Integer.toString(startLine)),
startLocation,
startLine,
cursorStart);
// Special case for the content tag
if (tag._content)
{
addTextToken(cursorStart - 1);
// Advance the cursor right to the end.
_cursor = length;
_stack.clear();
return;
}
// When a component closes, add a CLOSE tag.
if (tag._component)
{
addTextToken(cursorStart - 1);
_tokens.add(_factory.createCloseToken(tagName, getCurrentLocation()));
} else
{
// The close of a static tag. Unless removing the tag
// entirely, make sure the block tag is part of a text block.
if (_blockStart < 0 && !tag._removeTag && !_ignoring)
_blockStart = cursorStart;
}
// Remove all elements at stackPos or above.
for (int i = _stack.size() - 1; i >= stackPos; i--)
_stack.remove(i);
// Advance cursor past '>'
advance();
// If editting out the tag (i.e., $remove$) then kill any whitespace.
// For components that simply don't contain a body, removeTag will
// be false.
if (tag._removeTag)
advanceOverWhitespace();
// If we were ignoring the body of the tag, then clear the ignoring
// flag, since we're out of the body.
if (tag._ignoringBody)
_ignoring = false;
}