protected function emitToken($token, $checkStream = true, $dry = false) {
        if ($checkStream) {
            // Emit errors from input stream.
            while ($this->stream->errors) {
                $this->emitToken(array_shift($this->stream->errors), false);
            }
        }
        if($token['type'] === self::ENDTAG && !empty($token['attr'])) {
            for ($i = 0; $i < count($token['attr']); $i++) {
                $this->emitToken(array(
                    'type' => self::PARSEERROR,
                    'data' => 'attributes-in-end-tag'
                ));
            }
        }
        if($token['type'] === self::ENDTAG && !empty($token['self-closing'])) {
            $this->emitToken(array(
                'type' => self::PARSEERROR,
                'data' => 'self-closing-flag-on-end-tag',
            ));
        }
        if($token['type'] === self::STARTTAG) {
            // This could be changed to actually pass the tree-builder a hash
            $hash = array();
            foreach ($token['attr'] as $keypair) {
                if (isset($hash[$keypair['name']])) {
                    $this->emitToken(array(
                        'type' => self::PARSEERROR,
                        'data' => 'duplicate-attribute',
                    ));
                } else {
                    $hash[$keypair['name']] = $keypair['value'];
                }
            }
        }

        if(!$dry) {
            // the current structure of attributes is not a terribly good one
            $this->tree->emitToken($token);
        }

        if(!$dry && is_int($this->tree->content_model)) {
            $this->content_model = $this->tree->content_model;
            $this->tree->content_model = null;

        } elseif($token['type'] === self::ENDTAG) {
            $this->content_model = self::PCDATA;
        }
    }