protected function decodeCharacterReference($inAttribute = false) {

        // If it fails this, it's definitely not an entity.
        if ($this->scanner->current() != '&') {
            return false;
        }

        // Next char after &.
        $tok = $this->scanner->next();
        $entity = '';
        $start = $this->scanner->position();

        if ($tok == false) {
            return '&';
        }

        // These indicate not an entity. We return just
        // the &.
        if (strspn($tok, static::WHITE . "&<") == 1) {
            // $this->scanner->next();
            return '&';
        }

        // Numeric entity
        if ($tok == '#') {
            $tok = $this->scanner->next();

            // Hexidecimal encoding.
            // X[0-9a-fA-F]+;
            // x[0-9a-fA-F]+;
            if ($tok == 'x' || $tok == 'X') {
                $tok = $this->scanner->next(); // Consume x
                // Convert from hex code to char.
                $hex = $this->scanner->getHex();
                if (empty($hex)) {
                    $this->parseError("Expected &#xHEX;, got &#x%s", $tok);
                    // We unconsume because we don't know what parser rules might
                    // be in effect for the remaining chars. For example. '&#>'
                    // might result in a specific parsing rule inside of tag
                    // contexts, while not inside of pcdata context.
                    $this->scanner->unconsume(2);
                    return '&';
                }
                $entity = HTML5_Parser_CharacterReference::lookupHex($hex);
            }             // Decimal encoding.
            // [0-9]+;
            else {
                // Convert from decimal to char.
                $numeric = $this->scanner->getNumeric();
                if ($numeric === false) {
                    $this->parseError("Expected &#DIGITS;, got &#%s", $tok);
                    $this->scanner->unconsume(2);
                    return '&';
                }
                $entity = HTML5_Parser_CharacterReference::lookupDecimal($numeric);
            }
        }         // String entity.
        else {
            // Attempt to consume a string up to a ';'.
            // [a-zA-Z0-9]+;
            $cname = $this->scanner->getAsciiAlpha();
            $entity = HTML5_Parser_CharacterReference::lookupName($cname);
            if ($entity == null) {
                $this->parseError("No match in entity table for '%s'", $entity);
            }
        }

        // The scanner has advanced the cursor for us.
        $tok = $this->scanner->current();

        // We have an entity. We're done here.
        if ($tok == ';') {
            $this->scanner->next();
            return $entity;
        }

        // If in an attribute, then failing to match ; means unconsume the
        // entire string. Otherwise, failure to match is an error.
        if ($inAttribute) {
            $this->scanner->unconsume($this->scanner->position() - $start);
            return '&';
        }

        $this->parseError("Expected &ENTITY;, got &ENTITY%s (no trailing ;) ", $tok);
        return '&' . $entity;
    }