// static
LLMessageTemplate * LLTemplateParser::parseMessage(LLTemplateTokenizer & tokens)
{
	LLMessageTemplate	*templatep = NULL;
	if(!tokens.want("{"))
	{
		return NULL;
	}

	// name first
	std::string template_name = tokens.next();
	
	// is name a legit C variable name
	if (!b_variable_ok(template_name.c_str()))
	{
		llerrs << "Not legit variable name: " << template_name << " at " << tokens.line() << llendl;
	}

	// ok, now get Frequency ("High", "Medium", or "Low")
	EMsgFrequency frequency = MFT_LOW;
	std::string freq_string = tokens.next();
	if (freq_string == "High")
	{
		frequency = MFT_HIGH;
	}
	else if (freq_string == "Medium")
	{
		frequency = MFT_MEDIUM;
	}
	else if (freq_string == "Low" || freq_string == "Fixed")
	{
		frequency = MFT_LOW;
	}
	else
	{
		llerrs << "Expected frequency, got " << freq_string << " at " << tokens.line() << llendl;
	}

	// TODO more explicit checking here pls
	U32 message_number = strtoul(tokens.next().c_str(),NULL,0);

	switch (frequency) {
	case MFT_HIGH:
		break;
	case MFT_MEDIUM:
		message_number = (255 << 8) | message_number;
		break;
	case MFT_LOW:
		message_number = (255 << 24) | (255 << 16) | message_number;
		break;
	default:
		llerrs << "Unknown frequency enum: " << frequency << llendl;
	}
   
	templatep = new LLMessageTemplate(
		template_name.c_str(),
		message_number,
		frequency);
		
	// Now get trust ("Trusted", "NotTrusted")
	std::string trust = tokens.next();
	if (trust == "Trusted")
	{
		templatep->setTrust(MT_TRUST);
	}
	else if (trust == "NotTrusted")
	{
		templatep->setTrust(MT_NOTRUST);
	}
	else
	{
		llerrs << "Bad trust " << trust << " at " << tokens.line() << llendl;
	}
	
	// get encoding
	std::string encoding = tokens.next();
	if(encoding == "Unencoded")
	{
		templatep->setEncoding(ME_UNENCODED);
	}
	else if(encoding == "Zerocoded")
	{
		templatep->setEncoding(ME_ZEROCODED);
	}
	else
	{
		llerrs << "Bad encoding " << encoding << " at " << tokens.line() << llendl;
	}

	// get deprecation
	if(tokens.want("Deprecated"))
	{
		templatep->setDeprecation(MD_DEPRECATED);
	}
	else if (tokens.want("UDPDeprecated"))
	{
		templatep->setDeprecation(MD_UDPDEPRECATED);
	}
	else if (tokens.want("UDPBlackListed"))
	{
		templatep->setDeprecation(MD_UDPBLACKLISTED);
	}	
	else if (tokens.want("NotDeprecated"))
	{
		// this is the default value, but it can't hurt to set it twice
		templatep->setDeprecation(MD_NOTDEPRECATED);
	}
	else {
		// It's probably a brace, let's just start block processing
	}

	while(LLMessageBlock * blockp = parseBlock(tokens))
	{
		templatep->addBlock(blockp);
	}
	
	if(!tokens.want("}"))
	{
		llerrs << "Expecting closing } for message " << template_name
			   << " at " << tokens.line() << llendl;
	}
	return templatep;
}