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] == '#'
char_stack += [@stream.char, @stream.char]
if char_stack[0 .. 1].include? :EOF
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]
@stream.unget(char_stack[2])
char = consume_number_entity(true)
elsif DIGITS.include? char_stack[1]
@stream.unget(char_stack[1..-1])
char = consume_number_entity(false)
else
@stream.unget(char_stack)
@token_queue << {:type => :ParseError, :data => "expected-numeric-entity"}
end
end
else
filteredEntityList = ENTITIES.keys
filteredEntityList.reject! {|e| e[0].chr != char_stack[0]}
entityName = nil
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]
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