Exercise 2: A Void Element With Real Attributes — Possible Solution ==================================================================== THE TEST ------------------------------ tokenize("") RESULT ------------------------------ [voidtag('input', {'type': 'text', 'value': '42'})] token.kind == 'voidtag' token.attrs == {'type': 'text', 'value': '42'} WHY input NEEDS NO CLOSING TAG, ATTRIBUTES OR NOT ------------------------------ 'input' is one of the fourteen names in VOID_ELEMENTS, checked AFTER attribute parsing has already happened -- the tag name and the attribute string are split apart from the raw tag content first (everything up to the first whitespace is the name; everything after is handed to parse_attrs), and only then does tokenize ask whether that specific name belongs to the void set. Having real, meaningful attributes on the tag has no bearing on that check at all -- the void-vs-not decision is made purely by tag NAME, independent of whatever attributes happen to be present. This matters because it would be easy to assume, incorrectly, that "self-closing" and "void" mean the same thing, or that an element needs to look empty/attribute-free to qualify as void. Real HTML void elements are usually the OPPOSITE of attribute-free -- , , and are essentially always written with several attributes, since the attributes are the whole reason those elements exist (a value, a source URL, a stylesheet href). The void designation is a fixed property of the ELEMENT TYPE ITSELF, decided once in the HTML specification, not something inferred from how a particular tag happens to be written in the source.