13c827367444ee418f129b2c238299f49d3264554Jarkko Poyry/*-------------------------------------------------------------------------
23c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * drawElements Quality Program Test Executor
33c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * ------------------------------------------
43c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
53c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Copyright 2014 The Android Open Source Project
63c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
73c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Licensed under the Apache License, Version 2.0 (the "License");
83c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * you may not use this file except in compliance with the License.
93c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * You may obtain a copy of the License at
103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *      http://www.apache.org/licenses/LICENSE-2.0
123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * Unless required by applicable law or agreed to in writing, software
143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * distributed under the License is distributed on an "AS IS" BASIS,
153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * See the License for the specific language governing permissions and
173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * limitations under the License.
183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *
193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*!
203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \file
213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry * \brief XML Parser.
223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry *//*--------------------------------------------------------------------*/
233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "xeXMLParser.hpp"
253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry#include "deInt32.h"
263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
273c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xe
283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
293c827367444ee418f129b2c238299f49d3264554Jarkko Poyrynamespace xml
303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
323c827367444ee418f129b2c238299f49d3264554Jarkko Poyryenum
333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	TOKENIZER_INITIAL_BUFFER_SIZE	= 1024
353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry};
363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
373c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isIdentifierStartChar (int ch)
383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::inRange<int>(ch, 'a', 'z') || de::inRange<int>(ch, 'A', 'Z');
403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
423c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isIdentifierChar (int ch)
433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return isIdentifierStartChar(ch) || de::inRange<int>(ch, '0', '9') || (ch == '-') || (ch == '_');
453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
473c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic inline bool isWhitespaceChar (int ch)
483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return ch == ' ' || ch == '\t' || ch == '\r' || ch == '\n';
503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
523c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic int getNextBufferSize (int curSize, int minNewSize)
533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return de::max(curSize*2, 1<<deLog2Ceil32(minNewSize));
553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
573c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTokenizer::Tokenizer (void)
583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_curToken	(TOKEN_INCOMPLETE)
593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_curTokenLen	(0)
603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state		(STATE_DATA)
613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_buf			(TOKENIZER_INITIAL_BUFFER_SIZE)
623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
653c827367444ee418f129b2c238299f49d3264554Jarkko PoyryTokenizer::~Tokenizer (void)
663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
693c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Tokenizer::clear (void)
703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_curToken		= TOKEN_INCOMPLETE;
723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_curTokenLen	= 0;
733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state			= STATE_DATA;
743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_buf.clear();
753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
773c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Tokenizer::error (const std::string& what)
783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	throw ParseError(what);
803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
823c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Tokenizer::feed (const deUint8* bytes, int numBytes)
833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Grow buffer if necessary.
853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_buf.getNumFree() < numBytes)
863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_buf.resize(getNextBufferSize(m_buf.getSize(), m_buf.getNumElements()+numBytes));
883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// Append to front.
913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_buf.pushFront(bytes, numBytes);
923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// If we haven't parsed complete token, re-try after data feed.
943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_curToken == TOKEN_INCOMPLETE)
953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		advance();
963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
983c827367444ee418f129b2c238299f49d3264554Jarkko Poyryint Tokenizer::getChar (int offset) const
993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(de::inRange(offset, 0, m_buf.getNumElements()));
1013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (offset < m_buf.getNumElements())
1033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return m_buf.peekBack(offset);
1043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	else
1053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return END_OF_BUFFER;
1063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
1073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1083c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Tokenizer::advance (void)
1093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
1103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_curToken != TOKEN_INCOMPLETE)
1113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Parser should not try to advance beyond end of string.
1133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_curToken != TOKEN_END_OF_STRING);
1143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If current token is tag end, change state to data.
1163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_curToken == TOKEN_TAG_END						||
1173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curToken == TOKEN_EMPTY_ELEMENT_END			||
1183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curToken == TOKEN_PROCESSING_INSTRUCTION_END	||
1193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curToken == TOKEN_COMMENT						||
1203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curToken == TOKEN_ENTITY)
1213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_state = STATE_DATA;
1223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Advance buffer by length of last token.
1243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_buf.popBack(m_curTokenLen);
1253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Reset state.
1273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_curToken		= TOKEN_INCOMPLETE;
1283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_curTokenLen	= 0;
1293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// If we hit end of string here, report it as end of string.
1313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (getChar(0) == END_OF_STRING)
1323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curToken		= TOKEN_END_OF_STRING;
1343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_curTokenLen	= 1;
1353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
1363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
1383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	int curChar = getChar(m_curTokenLen);
1403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
1423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
1433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (m_state == STATE_DATA)
1443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Advance until we hit end of buffer or tag start and treat that as data token.
1463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curChar == END_OF_STRING || curChar == (int)END_OF_BUFFER || curChar == '<' || curChar == '&')
1473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curChar == '<')
1493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_TAG;
1503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == '&')
1513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_ENTITY;
1523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_curTokenLen > 0)
1543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Report data token.
1563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken = TOKEN_DATA;
1573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
1583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == END_OF_STRING || curChar == (int)END_OF_BUFFER)
1603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Just return incomplete token, no data parsed.
1623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
1633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
1653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(m_state == STATE_TAG || m_state == STATE_ENTITY);
1673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					continue;
1683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
1713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		else
1723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
1733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Eat all whitespace if present.
1743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_curTokenLen == 0)
1753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				while (isWhitespaceChar(curChar))
1773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
1783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_buf.popBack();
1793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					curChar = getChar(0);
1803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
1813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			// Handle end of string / buffer.
1843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (curChar == END_OF_STRING)
1853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				error("Unexpected end of string");
1863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (curChar == (int)END_OF_BUFFER)
1873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_curToken == TOKEN_INCOMPLETE);
1893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
1903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
1913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
1923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			if (m_curTokenLen == 0)
1933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
1943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Expect start of identifier, value or special tag token.
1953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curChar == '\'' || curChar == '"')
1963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_VALUE;
1973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (isIdentifierStartChar(curChar))
1983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_IDENTIFIER;
1993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == '<' || curChar == '?' || curChar == '/')
2003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_TAG;
2013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == '&')
2023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					DE_ASSERT(m_state == STATE_ENTITY);
2033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == '=')
2043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken		= TOKEN_EQUAL;
2063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curTokenLen	= 1;
2073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
2083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curChar == '>')
2103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken		= TOKEN_TAG_END;
2123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curTokenLen	= 1;
2133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
2143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
2163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Unexpected character");
2173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_state == STATE_IDENTIFIER)
2193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (!isIdentifierChar(curChar))
2213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken = TOKEN_IDENTIFIER;
2233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
2243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_state == STATE_VALUE)
2273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// \todo [2012-06-07 pyry] Escapes.
2293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curChar == '\'' || curChar == '"')
2303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// \todo [2012-10-17 pyry] Should we actually do the check against getChar(0)?
2323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar != getChar(0))
2333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Mismatched quote");
2343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken		 = TOKEN_STRING;
2353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curTokenLen	+= 1;
2363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
2373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_state == STATE_COMMENT)
2403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_curTokenLen >= 2); // 2 characters have been parsed if we are in comment state.
2423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_curTokenLen <= 3)
2443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar != '-')
2463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Invalid comment start");
2473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
2493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int prev2 = m_curTokenLen > 5 ? getChar(m_curTokenLen-2) : 0;
2513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					int prev1 = m_curTokenLen > 4 ? getChar(m_curTokenLen-1) : 0;
2523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (prev2 == '-' && prev1 == '-')
2543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
2553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						if (curChar != '>')
2563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							error("Invalid comment end");
2573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curToken		 = TOKEN_COMMENT;
2583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curTokenLen	+= 1;
2593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
2603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
2613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else if (m_state == STATE_ENTITY)
2643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (m_curTokenLen >= 1)
2663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar == ';')
2683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
2693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curToken		 = TOKEN_ENTITY;
2703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curTokenLen	+= 1;
2713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
2723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
2733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (!de::inRange<int>(curChar, '0', '9')	&&
2743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 !de::inRange<int>(curChar, 'a', 'z')	&&
2753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry							 !de::inRange<int>(curChar, 'A', 'Z'))
2763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Invalid entity");
2773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
2783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
2793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			else
2803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{
2813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Special tokens are at most 2 characters.
2823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(m_state == STATE_TAG && m_curTokenLen == 1);
2833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				int prevChar = getChar(m_curTokenLen-1);
2853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
2863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (prevChar == '<')
2873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
2883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					// Tag start.
2893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar == '/')
2903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
2913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curToken		= TOKEN_END_TAG_START;
2923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curTokenLen	= 2;
2933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
2943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
2953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (curChar == '?')
2963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
2973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curToken		= TOKEN_PROCESSING_INSTRUCTION_START;
2983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curTokenLen	= 2;
2993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
3003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
3013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else if (curChar == '!')
3023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
3033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_state = STATE_COMMENT;
3043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
3053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					else
3063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					{
3073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curToken		= TOKEN_TAG_START;
3083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_curTokenLen	= 1;
3093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
3103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					}
3113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
3123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (prevChar == '?')
3133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
3143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar != '>')
3153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Invalid processing instruction end");
3163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken		= TOKEN_PROCESSING_INSTRUCTION_END;
3173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curTokenLen	= 2;
3183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
3193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
3203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (prevChar == '/')
3213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
3223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curChar != '>')
3233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Invalid empty element end");
3243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curToken		= TOKEN_EMPTY_ELEMENT_END;
3253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_curTokenLen	= 2;
3263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
3273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
3283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
3293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Could not parse special token");
3303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			}
3313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
3323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_curTokenLen	+= 1;
3343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		curChar			 = getChar(m_curTokenLen);
3353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3383c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Tokenizer::getString (std::string& dst) const
3393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_curToken == TOKEN_STRING);
3413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	dst.resize(m_curTokenLen-2);
3423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < m_curTokenLen-2; ndx++)
3433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		dst[ndx] = m_buf.peekBack(ndx+1);
3443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3463c827367444ee418f129b2c238299f49d3264554Jarkko PoyryParser::Parser (void)
3473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	: m_element		(ELEMENT_INCOMPLETE)
3483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	, m_state		(STATE_DATA)
3493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3523c827367444ee418f129b2c238299f49d3264554Jarkko PoyryParser::~Parser (void)
3533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3563c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Parser::clear (void)
3573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_tokenizer.clear();
3593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_elementName.clear();
3603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attributes.clear();
3613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_attribName.clear();
3623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_entityValue.clear();
3633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_element	= ELEMENT_INCOMPLETE;
3653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_state		= STATE_DATA;
3663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3683c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Parser::error (const std::string& what)
3693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	throw ParseError(what);
3713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3733c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Parser::feed (const deUint8* bytes, int numBytes)
3743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_tokenizer.feed(bytes, numBytes);
3763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_element == ELEMENT_INCOMPLETE)
3783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		advance();
3793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
3803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3813c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Parser::advance (void)
3823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
3833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_element == ELEMENT_START)
3843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_attributes.clear();
3853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	// \note No token is advanced when element end is reported.
3873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_state == STATE_YIELD_EMPTY_ELEMENT_END)
3883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		DE_ASSERT(m_element == ELEMENT_START);
3903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_element	= ELEMENT_END;
3913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_state		= STATE_DATA;
3923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		return;
3933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
3943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
3953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (m_element != ELEMENT_INCOMPLETE)
3963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
3973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_tokenizer.advance();
3983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_element = ELEMENT_INCOMPLETE;
3993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
4003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (;;)
4023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
4033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		Token curToken = m_tokenizer.getToken();
4043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		// Skip comments.
4063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		while (curToken == TOKEN_COMMENT)
4073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			m_tokenizer.advance();
4093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			curToken = m_tokenizer.getToken();
4103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (curToken == TOKEN_INCOMPLETE)
4133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			DE_ASSERT(m_element == ELEMENT_INCOMPLETE);
4153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return;
4163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
4173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		switch (m_state)
4193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		{
4203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_ENTITY:
4213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state = STATE_DATA;
4223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				// Fall-through to STATE_DATA processing.
4233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_DATA:
4253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				switch (curToken)
4263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_DATA:
4283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_element = ELEMENT_DATA;
4293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
4303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_END_OF_STRING:
4323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_element = ELEMENT_END_OF_STRING;
4333c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
4343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_TAG_START:
4363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_state = STATE_START_TAG_OPEN;
4373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
4383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_END_TAG_START:
4403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_state = STATE_END_TAG_OPEN;
4413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
4423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_PROCESSING_INSTRUCTION_START:
4443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_state = STATE_IN_PROCESSING_INSTRUCTION;
4453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						break;
4463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					case TOKEN_ENTITY:
4483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_state		= STATE_ENTITY;
4493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						m_element	= ELEMENT_DATA;
4503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						parseEntityValue();
4513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						return;
4523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					default:
4543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Unexpected token");
4553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4573c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_IN_PROCESSING_INSTRUCTION:
4593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken == TOKEN_PROCESSING_INSTRUCTION_END)
4603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_DATA;
4613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
4623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					if (curToken != TOKEN_IDENTIFIER && curToken != TOKEN_EQUAL && curToken != TOKEN_STRING)
4633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry						error("Unexpected token in processing instruction");
4643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_START_TAG_OPEN:
4673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken != TOKEN_IDENTIFIER)
4683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Expected identifier");
4693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_tokenizer.getTokenStr(m_elementName);
4703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state = STATE_ATTRIBUTE_LIST;
4713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_END_TAG_OPEN:
4743c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken != TOKEN_IDENTIFIER)
4753c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Expected identifier");
4763c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_tokenizer.getTokenStr(m_elementName);
4773c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state = STATE_EXPECTING_END_TAG_CLOSE;
4783c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
4793c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4803c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_EXPECTING_END_TAG_CLOSE:
4813c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken != TOKEN_TAG_END)
4823c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Expected tag end");
4833c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state		= STATE_DATA;
4843c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_element	= ELEMENT_END;
4853c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				return;
4863c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
4873c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_ATTRIBUTE_LIST:
4883c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken == TOKEN_IDENTIFIER)
4893c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4903c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_tokenizer.getTokenStr(m_attribName);
4913c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state = STATE_EXPECTING_ATTRIBUTE_EQ;
4923c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4933c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curToken == TOKEN_EMPTY_ELEMENT_END)
4943c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
4953c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state		= STATE_YIELD_EMPTY_ELEMENT_END;
4963c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_element	= ELEMENT_START;
4973c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
4983c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
4993c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else if (curToken == TOKEN_TAG_END)
5003c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				{
5013c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_state		= STATE_DATA;
5023c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					m_element	= ELEMENT_START;
5033c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					return;
5043c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				}
5053c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				else
5063c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Unexpected token");
5073c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
5083c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5093c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_EXPECTING_ATTRIBUTE_EQ:
5103c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken != TOKEN_EQUAL)
5113c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Expected '='");
5123c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state = STATE_EXPECTING_ATTRIBUTE_VALUE;
5133c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
5143c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5153c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			case STATE_EXPECTING_ATTRIBUTE_VALUE:
5163c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (curToken != TOKEN_STRING)
5173c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Expected value");
5183c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				if (hasAttribute(m_attribName.c_str()))
5193c827367444ee418f129b2c238299f49d3264554Jarkko Poyry					error("Duplicate attribute");
5203c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5213c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_tokenizer.getString(m_attributes[m_attribName]);
5223c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				m_state = STATE_ATTRIBUTE_LIST;
5233c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				break;
5243c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5253c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			default:
5263c827367444ee418f129b2c238299f49d3264554Jarkko Poyry				DE_ASSERT(false);
5273c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		}
5283c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5293c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		m_tokenizer.advance();
5303c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5313c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5323c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5333c827367444ee418f129b2c238299f49d3264554Jarkko Poyrystatic char getEntityValue (const std::string& entity)
5343c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5353c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	static const struct
5363c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5373c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		const char*		name;
5383c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		char			value;
5393c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	} s_entities[] =
5403c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5413c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "&lt;",			'<' },
5423c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "&gt;",			'>' },
5433c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "&amp;",			'&' },
5443c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "&apos;",			'\''},
5453c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			{ "&quot;",			'"' },
5463c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	};
5473c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5483c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(s_entities); ndx++)
5493c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	{
5503c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		if (entity == s_entities[ndx].name)
5513c827367444ee418f129b2c238299f49d3264554Jarkko Poyry			return s_entities[ndx].value;
5523c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	}
5533c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5543c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	return 0;
5553c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5563c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5573c827367444ee418f129b2c238299f49d3264554Jarkko Poyryvoid Parser::parseEntityValue (void)
5583c827367444ee418f129b2c238299f49d3264554Jarkko Poyry{
5593c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	DE_ASSERT(m_state == STATE_ENTITY && m_tokenizer.getToken() == TOKEN_ENTITY);
5603c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5613c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	std::string entity;
5623c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_tokenizer.getTokenStr(entity);
5633c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5643c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	const char value = getEntityValue(entity);
5653c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	if (value == 0)
5663c827367444ee418f129b2c238299f49d3264554Jarkko Poyry		error("Invalid entity '" + entity + "'");
5673c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5683c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_entityValue.resize(1);
5693c827367444ee418f129b2c238299f49d3264554Jarkko Poyry	m_entityValue[0] = value;
5703c827367444ee418f129b2c238299f49d3264554Jarkko Poyry}
5713c827367444ee418f129b2c238299f49d3264554Jarkko Poyry
5723c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xml
5733c827367444ee418f129b2c238299f49d3264554Jarkko Poyry} // xe
574