# File lib/html5/tokenizer.rb, line 137
    def consume_entity(from_attribute=false)
      char = nil
      char_stack = [@stream.char]
      if SPACE_CHARACTERS.include?(char_stack[0]) or [:EOF, '<', '&'].include?(char_stack[0])
        @stream.unget(char_stack)
      elsif char_stack[0] == '#'
        # We might have a number entity here.
        char_stack += [@stream.char, @stream.char]
        if char_stack[0 .. 1].include? :EOF
          # If we reach the end of the file put everything up to :EOF
          # back in the queue
          char_stack = char_stack[0...char_stack.index(:EOF)]
          @stream.unget(char_stack)
          @token_queue << {:type => :ParseError, :data => "expected-numeric-entity-but-got-eof"}
        else
          if char_stack[1].downcase == "x" and HEX_DIGITS.include? char_stack[2]
            # Hexadecimal entity detected.
            @stream.unget(char_stack[2])
            char = consume_number_entity(true)
          elsif DIGITS.include? char_stack[1]
            # Decimal entity detected.
            @stream.unget(char_stack[1..-1])
            char = consume_number_entity(false)
          else
            # No number entity detected.
            @stream.unget(char_stack)
            @token_queue << {:type => :ParseError, :data => "expected-numeric-entity"}
          end
        end
      else
        # At this point in the process might have named entity. Entities
        # are stored in the global variable "entities".
        #
        # Consume characters and compare to these to a substring of the
        # entity names in the list until the substring no longer matches.
        filteredEntityList = ENTITIES.keys
        filteredEntityList.reject! {|e| e[0].chr != char_stack[0]}
        entityName = nil

        # Try to find the longest entity the string will match to take care
        # of &noti for instance.
        while char_stack.last != :EOF
          name = char_stack.join('')
          if filteredEntityList.any? {|e| e[0...name.length] == name}
            filteredEntityList.reject! {|e| e[0...name.length] != name}
            char_stack.push(@stream.char)
          else
            break
          end

          if ENTITIES.include? name
            entityName = name
            break if entityName[-1] == ';'
          end
        end

        if entityName != nil
          char = ENTITIES[entityName]

          # Check whether or not the last character returned can be
          # discarded or needs to be put back.
          if entityName[-1] != ?;
            @token_queue << {:type => :ParseError, :data => "named-entity-without-semicolon"}
          end

          if entityName[-1] != ";" and from_attribute and
             (ASCII_LETTERS.include?(char_stack[entityName.length]) or
              DIGITS.include?(char_stack[entityName.length]))
            @stream.unget(char_stack)
            char = '&'
          else
            @stream.unget(char_stack[entityName.length..-1])
          end
        else
          @token_queue << {:type => :ParseError, :data => "expected-named-entity"}
          @stream.unget(char_stack)
        end
      end
      return char
    end