예제 #1
0
/**********************************************************************************************
 *
 * ReadProcessingInstruction
 *
 * ProcessingInstruction = '<?' QualifiedName ( Whitespace (Character)* ) ? '?>' ;
 *
 *********************************************************************************************/
XMLScanner::TOKEN XMLScanner::ReadProcessingInstruction () {
    QualfiedName targer = ReadQualifiedName ();
    if (isWhitespace (current)) {
        while (ReadCharacter ()) {
            if (current == '?') {
                ReadCharacter ();
                if (current == '>') {
                    ReadCharacter ();
                    return TOKEN_PROCESSING_INSTRUCTION;

                } else {
                    output.Append ('?');
                    output.Append (current);
                    continue;
                }

            } else {
                output.Append (current);
            }
        }
        throw UnexpectedEndException ();

    } else {
        throw UnexpectedCharacterException ();
    }
}
예제 #2
0
/**********************************************************************************************
 *
 * ReadReference
 *
 * Reference = EntityReference | CharacterReference ;
 *
 * CharacterReference = "&#" [0-9]+ ";" | "&#x" [0-9a-fA-F]+ ";" ;
 *
 * EntityReference = "&lt;" | "&amp;" | "&gt;" | "&quot;" | "&apos;" ;
 *
 *********************************************************************************************/
void XMLParser::ReadReference () {
    if (current == '&') ReadCharacter ();
    else throw InvalidStateException ();

    if (current == '#') {
        if (current == 'x') {
            /* hexadecimal encoded unicode character. */
            while (ReadCharacter ()) {
                // TODO ...
                if (current == ';') break;
            }

        } else {
            /* decimal encoded unicode character. */
            do {
                // TODO ...
                if (current == ';') break;
            } while (ReadCharacter ());
        }

    } else {
        /* named entity */
        do {
            // TODO ...
            if (current == ';') break;
        } while (ReadCharacter ());
    }
}
예제 #3
0
/******************************************************************************
 * read float
 * checks for positive and negative float
 * checks for a valid range of numbers
 *****************************************************************************/
int ReadFloat(float *f)
{
	int c;
	int minus = 0;
	float d = 0.0f;

	*f = 0.0f;
	
	if ((c = ReadCharacter()) == EOF) return 0;
	if (c == '-') minus = 1;
	else if (c != '+') UngetCharacter(c);

	c = ReadCharacter();
	if ((c < '0' || c > '9') && c != '.')
	{
		UngetCharacter(c);
		return 0;
	}
	UngetCharacter(c);
	while((c = ReadCharacter()) != EOF)
	{
		if (c == '.')
		{
			if (d == 0.0f)
			{
				d = 1.0f;
				continue;
			}
			else
			{
				UngetCharacter(c);
				return 1;
			}
		}
		if (c >= '0' && c <= '9')
		{
			if (d == 0.0f) *f = *f * 10.0f + (float)(c - '0');
			else *f += (float)(c - '0') / (d *= 10.0f);
		 	continue;
		}
		UngetCharacter(c);
		if (d != 1.0f)
		{
			if (minus) *f = -*f;
			return 1;
		}
		else return 0;
	}
	if (d != 1.0f)
	{
			if (minus) *f = -*f;
			return 1;
	}
	else return 0;
}
예제 #4
0
/******************************************************************************
 * read signed integer
 * used in the coaster definition file
 *****************************************************************************/
int ReadSignedInt(int *i)
{
	int c, minus = 0;

	if ((c = ReadCharacter()) == EOF)
	{
		PrintError("Integer expected");
		return 0;
	}
	switch(c)
	{
		case '-':
			minus = 1;
			break;
		case '+':
			break;
		default :
			UngetCharacter(c);
	}
	if (!ReadInteger(i))
	{
		PrintError("Integer expected");
		return 0;
	}
	if (minus) *i = -*i;
	return 1;
}
예제 #5
0
/**********************************************************************************************
 *
 * ReadCDATASection
 *
 * CDATASection = '<![CDATA[' Character *  ']]>' ;
 *
 *********************************************************************************************/
void XMLScanner::ReadCDATASection () {
    if (current == '[') {
        ReadCharacter ();
        if (current == 'C') {
            ReadCharacter ();
            if (current == 'D') {
                ReadCharacter ();
                if (current == 'A') {
                    ReadCharacter ();
                    if (current == 'T') {
                        ReadCharacter ();
                        if (current == 'A') {
                            ReadCharacter ();
                            if (current == '[') {
                                /* CDATA section content */
                                while (ReadCharacter ()) {
                                    if (current == ']') {
                                        ReadCharacter ();
                                        if (current == ']') {
                                            ReadCharacter ();
                                            if (current == '>') {
                                                ReadCharacter ();
                                                return ;
                                            } else {
                                                output.Append (']');
                                                output.Append (']');
                                                output.Append (current);
                                            }
                                        } else {
                                            output.Append (']');
                                            output.Append (current);
                                        }
                                    } else {
                                        output.Append (current);
                                    }
                                }
                                throw UnexpectedEndException ();
                            }
                        }
                    }
                }
            }
        }
    }
    throw UnexpectedCharacterException ();
}
예제 #6
0
/******************************************************************************
 * skip comment
 * comment will start with '#'
 *****************************************************************************/
void SkipComment()
{
	int c;

	SkipWhitespace();
	if ((c = ReadCharacter()) == EOF) return;
	while(c == LF || c=='#')
	{
		if (c == '#')
		{
			c = ReadCharacter();
			while(c != EOF && c != LF) c = ReadCharacter();
		}
		SkipWhitespace();
		c = ReadCharacter();
	}
	UngetCharacter(c);
}
예제 #7
0
/**********************************************************************************************
 *
 * ReadQualifiedName
 *
 * QualifiedName = Name ? ":" ? Name ;
 *
 * Name = NameStartCharacter ( NameCharacter )* ;
 *
 * NameStartCharacter = "_" | [A-Z] | [a-z] ;
 *
 * NameCharacter = NameStartCharacter | "-" | "." | [0-9] ;
 *
 *********************************************************************************************/
QualifiedName XMLParser::ReadQualifiedName () {
    static const int name_charachters [] = {
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,
        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,
        0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
        1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0
    };

    bool first = true;
    bool valid = true;

    std::string specifier;
    std::string name;

    do {
        if (valid && current == ':') {
            if (specifier == "") {
                specifier = output.toString ();
                output.Reset ();
            } else {
                valid = false;
            }

        } else if (current == '\x20' || current == '\x9' || current ==  '\xD' || current == '\xA') {
            Position end = position;

            if (!valid) throw InvalidNameException     ();
            if (first ) throw UnexpectedTokenException ();

            return QualifiedName (specifier, name);

        } else if ('\0' <= current && current < '\x7f' && name_characters [(int) current] == 1) {
            if ((first && '9' < current) || !first) {
                first = false;
                output.AppendIgnoreCase (current);
            } else {
                valid = false;
            }

        } else {
            valid = false;
            continue;
        }

    } while (ReadCharacter ());

    return UnexpectedEndException ();
}
예제 #8
0
/******************************************************************************
 * skip whitespace
 *****************************************************************************/
void SkipWhitespace()
{
	int c;

	while((c = ReadCharacter()) != EOF)
	{
		if (c != ' ' && c != '\t')
		{
			UngetCharacter(c);
			return;
		}
	}
}
 // This puts "<!" into destinationForReadCharacters if it is not NULL, then
 // reads in characters from xmlStream until the next "]]>", placing
 // them all into destinationForReadCharacters if it is not NULL. It throws
 // an exception if it fails to read in "]]>".
 inline void
 RestrictedXmlParser::ReadCdata( std::ostream* destinationForReadCharacters )
 {
   if( destinationForReadCharacters != NULL )
   {
     (*destinationForReadCharacters) << "<![";
   }
   while( ReadToNextHalt( ']',
                          NULL,
                          destinationForReadCharacters )
          &&
          ReadCharacter( destinationForReadCharacters )
          &&
          ( currentCharacter == ']' )
          &&
          ReadCharacter( destinationForReadCharacters ) )
   {
     if( currentCharacter == '>' )
     {
       return;
     }
   }
   throw std::runtime_error( "Failed to close <[...]]> structure!" );
 }
 // This puts characters from xmlStream into destinationWithoutHalt if it is
 // not NULL and destinationIncludingHalt if it is not NULL (if both are
 // NULL, the characters are discarded) until it reads in the first instance
 // of haltCharacter (which is put into destinationIncludingHalt but not
 // into destinationWithoutHalt).
 inline bool RestrictedXmlParser::ReadToNextHalt( char const haltCharacter,
                                         std::ostream* destinationWithoutHalt,
                                      std::ostream* destinationIncludingHalt )
 {
   while( ReadCharacter( destinationIncludingHalt )
          &&
          ( currentCharacter != haltCharacter ) )
   {
     if( destinationWithoutHalt != NULL )
     {
       (*destinationWithoutHalt) << currentCharacter;
     }
   }
   return ( currentCharacter == haltCharacter );
 }
예제 #11
0
/**********************************************************************************************
 *
 * ReadLiteral
 *
 * Literal = '"' ([^<&"] | Reference)* '"' | "'" ([^<&'] | Reference)* "'" ;
 *
 *********************************************************************************************/
XMLScanner::TOKEN XMLParser::ReadLiteral () {
    char quote = '\0';
    if (current == '\"' || current == '\'') {
        quote = current;
        output.Reset ();
    }

    while (ReadCharacter ()) {
        if (current == quote) {
            ReadCharacter ();
            break;

        } else if (current == '<') {
            throw UnexpectedCharacterException ();

        } else if (current == '&') {
            ReadReference ();

        } else {
            output.Append (current);
        }
    }
    return Literal (output.toString ());
}
예제 #12
0
/******************************************************************************
 * read a section SECTION
 * construct the section SECTION character by character
 *****************************************************************************/
int ReadSectionName(char *str, int length)
{
	int c;
	int i = 0;

	str[i] = 0;
	if ((c = ReadCharacter()) == EOF) return 0;
	UngetCharacter(c);
	if (c < 'a' || c > 'z') return 0;
	while((c = ReadCharacter()) != EOF)
	{
		if (c >= 'a' && c <= 'z')
		{
			if (i < length - 1) str[i++] = c;
			else str[i] = 0;
			continue;
		}
		str[i] = 0;
		UngetCharacter(c);
		return 1;
	}
	str[i] = 0;
	return 1;
}
예제 #13
0
/******************************************************************************
 * rean an integer
 * validate the range of the integer
 *****************************************************************************/
int ReadInteger(int *i)
{
	int c;

	*i = 0;
	if ((c = ReadCharacter()) == EOF) return 0;
	if (c < '0' || c > '9')
	{
		UngetCharacter(c);
		return 0;
	}
	UngetCharacter(c);
	while((c = ReadCharacter()) != EOF)
	{
		if (c >= '0' && c <= '9')
		{
			*i = *i * 10 + c - '0';
		 	continue;
		}
		UngetCharacter(c);
		return 1;
	}
	return 1;
}
 // This puts characters from xmlStream into destinationWithoutHalt if it is
 // not NULL and destinationIncludingHalt if it is not NULL (if both are
 // NULL, the characters are discarded) until it reads in the first instance
 // of any of the characters in haltCharacters (which is put into
 // destinationIncludingHalt but not into destinationWithoutHalt).
 inline bool
 RestrictedXmlParser::ReadToNextHalt( std::string const& haltCharacters,
                                      std::ostream* destinationWithoutHalt,
                                      std::ostream* destinationIncludingHalt )
 {
   while( ReadCharacter( destinationIncludingHalt )
          &&
          !(ParsingUtilities::CharacterIsInString( currentCharacter,
                                                   haltCharacters )) )
   {
     if( destinationWithoutHalt != NULL )
     {
       (*destinationWithoutHalt) << currentCharacter;
     }
   }
   return ParsingUtilities::CharacterIsInString( currentCharacter,
                                                 haltCharacters );
 }
예제 #15
0
/******************************************************************************
 * read separator
 * separator can be ';' or ','
 *****************************************************************************/
int ReadSeparator()
{
	int c;

	SkipWhitespace();
	c = ReadCharacter();
	if (c == ';' || c==',')
	{
		SkipWhitespace();
		return 1;
	}
	else
	{
		UngetCharacter(c);
		PrintError("Separator expected");
		return 0;
	}
}
 // This reads characters from xmlStream into currentChar until the first
 // non-whitespace character is read in, returning true unless the stream
 // ended without any non-whitespace character being read in. If
 // destinationForReadCharacters is not NULL, all read characters (including
 // the first non-whitespace character) are put into it.
 inline bool RestrictedXmlParser::SkipWhitespace(
                                  std::ostream* destinationForReadCharacters )
 {
   // If the name is followed by whitespace, we keep going to the first
   // non-whitespace character, discarding all the whitespace characters
   // along the way.
   while( ParsingUtilities::CharacterIsInString( currentCharacter,
                                                AllowedWhitespaceChars() ) )
   {
     // If we run out of characters from the stream before finding a
     // non-whitespace character, we return false. Evaluating the
     // conditional does work.
     if( !(ReadCharacter( destinationForReadCharacters )) )
     {
       return false;
     }
   }
   return true;
 }
 // This puts "<?" into destinationForReadCharacters if it is not NULL, then
 // reads in characters from xmlStream until the next "?>", placing
 // them all into destinationForReadCharacters if it is not NULL. It throws
 // an exception if it fails to read in "?>".
 inline void RestrictedXmlParser::CloseQuestionMark(
                                  std::ostream* destinationForReadCharacters )
 {
   if( destinationForReadCharacters != NULL )
   {
     (*destinationForReadCharacters) << "<?";
   }
   while( ReadToNextHalt( '?',
                          NULL,
                          destinationForReadCharacters )
          &&
          ReadCharacter( destinationForReadCharacters ) )
   {
     if( currentCharacter == '>' )
     {
       return;
     }
   }
   throw std::runtime_error( "Failed to close processing instruction!" );
 }
 // This returns true if the attribute was correctly formed, assuming that
 // the first character of the attribute name is already in nameStream,
 // putting the rest of the name into nameStream and the value into
 // valueStream (without the quote marks), and all read characters into
 // tagRecord if it is not NULL.
 bool TryToReadValidAttribute( std::ostream& nameStream,
                               std::ostream& valueStream,
                               std::ostream* tagRecord )
 { return ( ReadToNextHalt( ( AllowedWhitespaceChars() + "=" ),
                            &nameStream,
                            tagRecord )
            &&
            SkipWhitespace( tagRecord )
            &&
            ( currentCharacter == '=' )
            &&
            ReadCharacter( tagRecord )
            &&
            SkipWhitespace( tagRecord )
            &&
            ( ( currentCharacter == '\'' ) || ( currentCharacter == '\"' ) )
            &&
            ReadToNextHalt( currentCharacter,
                            &valueStream,
                            tagRecord ) ); }
예제 #19
0
bool StyleSheetParser::FindToken(String& buffer, const char* tokens, bool remove_token)
{
	buffer.Clear();
	char character;
	while (ReadCharacter(character))
	{
		if (strchr(tokens, character) != NULL)
		{
			if (remove_token)
				parse_buffer_pos++;
			return true;
		}
		else
		{
			buffer.Append(character);
			parse_buffer_pos++;
		}
	}

	return false;
}
 // This reads xmlStream until the end of the start or empty-element tag is
 // reached, parsing attributes along the way into attributeDestination,
 // throwing an exception if it does not reach the end of the tag without
 // the stream ending or finding malformed XML. All the characters of the
 // tag get put into tagRecord if it is not NULL.
 inline void
 RestrictedXmlParser::CloseStartTag( AttributeMap* attributeDestination,
                                     std::ostream* tagRecord )
 {
   if( !(SkipWhitespace( tagRecord )) )
   {
     throw std::runtime_error( "Could not find end of start tag!" );
   }
   // Now currentChar is the end of the start tag ('>'), or the first
   // character of the end of an empty element tag ('/' in "/>") (or the
   // tag is malformed with a '/' out of place), or is the first character
   // of an attribute name.
   if( TagIsStillOpen( tagRecord ) )
   {
     ParseAttribute( attributeDestination,
                     tagRecord );
     if( !(ReadCharacter( tagRecord )) )
     {
       throw std::runtime_error( "Could not find end of start tag!" );
     }
     CloseStartTag( attributeDestination,
                    tagRecord );
   }
 }
 // This returns false if currentCharacter is '>' or if it is '/' and the
 // next character is '>', first setting currentElementIsEmpty
 // appropriately. It throws an exception if currentCharacter is '/' and is
 // not followed immediately by '>'. It returns true otherwise.
 inline bool
 RestrictedXmlParser::TagIsStillOpen( std::ostream* tagRecord )
 {
   if( currentCharacter == '>' )
   {
     currentElementIsEmpty = false;
     return false;
   }
   else if( currentCharacter == '/' )
   {
     if( ReadCharacter( tagRecord )
         &&
         ( currentCharacter == '>' ) )
     {
       currentElementIsEmpty = true;
       return false;
     }
     else
     {
       throw std::runtime_error( "Attribute name cannot begin with \'/\'" );
     }
   }
   return true;
 }
예제 #22
0
/**********************************************************************************************
 *
 * ReadComment
 *
 * Comment = '<!--' ((Character - '-') | ('-' (Character - '-')))*  '-->' ;
 *
 *********************************************************************************************/
void XMLScanner::ReadComment () {
    if (current == '-') {
        ReadCharacter ();
        if (current == '-') {
            ReadCharacter ();
            while (ReadCharacter ()) {
                if (current == '-') {
                    ReadCharacter ();
                    if (current == '-') {
                        ReadCharacter ();
                        if (current == '>') {
                            ReadCharacter ();
                            return ;
                        } else {
                            // TODO : Warning : Illegal sequence '--' inside comment
                        }
                    }
                }
            }
            throw UnexpectedEndException ();
        }
    }
    throw UnexpectedCharacterException ();
}
예제 #23
0
/*
// GetTextLine
//
// Gets a line of text from the source file without # directive
// processing, or processing past a EOL.
//
// Returns 1 on success, 0 on error
*/
static int GetTextLine( SOURCEFILE *ps, char *Dst, int MaxLen, int *pLength, int *pEOF )
{
    int c;
    int  idx;
    int  commentFlag,quoteFlag;

    /* Remove leading white space */
    do
    {
        c = ReadCharacter( ps );
    } while( c==' ' || c==0x9 || c==0xa );

    /*
    // Process line watching for comments and quotes
    */
    idx=0;
    commentFlag=0;
    quoteFlag=0;
    for(;;)
    {
        /* Process quotes and comments */
        if( c=='"' )
            quoteFlag^=1;

        if( quoteFlag )
            commentFlag=0;

        if( (commentFlag && c=='/') || (!quoteFlag && c==';') )
        {
            if( c=='/' && idx>0 )
                idx--;
            while( c!=0 && c!=-1 && c!=0xa )
                c = ReadCharacter( ps );
            break;
        }

        if( c=='/' )
            commentFlag=1;
        else
            commentFlag=0;

        /* If this character terminated the line, break now */
        if( c==0 || c==-1 || c==0xa )
            break;

        /* We didn't consume this charater */
        if( idx<(MaxLen-1) )
            Dst[idx++]=c;
        else
            { Report(ps,REP_ERROR,"Line too long"); return(0); }

        c = ReadCharacter( ps );
    }

    /* Back off white space */
    while( idx>0 && (Dst[idx-1]==' ' || Dst[idx-1]==0x9) )
        idx--;

    /* Null terminate the output */
    Dst[idx] = 0;

    if( quoteFlag )
        Report(ps,REP_ERROR,"Open Quotes");

    if( pLength )
        *pLength = idx;

    if( pEOF )
    {
        if( idx || c!=-1 )
            *pEOF=0;
        else
            *pEOF=1;
    }

    return(1);
}
예제 #24
0
bool StyleSheetParser::ReadProperties(PropertyDictionary& properties)
{
	int rule_line_number = line_number;
	String name;
	String value;

	enum ParseState { NAME, VALUE, QUOTE };
	ParseState state = NAME;

	char character;
	char previous_character = 0;
	while (ReadCharacter(character))
	{
		parse_buffer_pos++;

		switch (state)
		{
			case NAME:
			{
				if (character == ';')
				{
					name = StringUtilities::StripWhitespace(name);
					if (!name.Empty())
					{
						Log::Message(Log::LT_WARNING, "Found name with no value parsing property declaration '%s' at %s:%d", name.CString(), stream_file_name.CString(), line_number);
						name.Clear();
					}
				}
				else if (character == '}')
				{
					name = StringUtilities::StripWhitespace(name);
					if (!StringUtilities::StripWhitespace(name).Empty())
						Log::Message(Log::LT_WARNING, "End of rule encountered while parsing property declaration '%s' at %s:%d", name.CString(), stream_file_name.CString(), line_number);
					return true;
				}
				else if (character == ':')
				{
					name = StringUtilities::StripWhitespace(name);
					state = VALUE;
				}
				else
					name.Append(character);
			}
			break;
			
			case VALUE:
			{
				if (character == ';')
				{
					value = StringUtilities::StripWhitespace(value);

					if (!StyleSheetSpecification::ParsePropertyDeclaration(properties, name, value, stream_file_name, rule_line_number))
						Log::Message(Log::LT_WARNING, "Syntax error parsing property declaration '%s: %s;' in %s: %d.", name.CString(), value.CString(), stream_file_name.CString(), line_number);

					name.Clear();
					value.Clear();
					state = NAME;
				}
				else if (character == '}')
				{
					Log::Message(Log::LT_WARNING, "End of rule encountered while parsing property declaration '%s: %s;' in %s: %d.", name.CString(), value.CString(), stream_file_name.CString(), line_number);
					return true;
				}
				else
				{
					value.Append(character);
					if (character == '"')
						state = QUOTE;
				}
			}
			break;

			case QUOTE:
			{
				value.Append(character);
				if (character == '"' && previous_character != '/')
					state = VALUE;
			}
			break;
		}

		previous_character = character;
	}

	if (!name.Empty() || !value.Empty())
		Log::Message(Log::LT_WARNING, "Invalid property declaration at %s:%d", stream_file_name.CString(), line_number);
	
	return true;
}
예제 #25
0
/**********************************************************************************************
 *
 * Whitespaces
 *
 * Whitespaces = (#x20 | #x9 | #xD | #xA)+ ;
 *
 *********************************************************************************************/
void XMLParser::SkipWhitespaces () {
    do {
        if (current != '\x20' && current != '\x9' && current != '\xD' && current != '\xA') break;
    } while (ReadCharacter ());
}
예제 #26
0
/**********************************************************************************************
 * NextToken
 *********************************************************************************************/
XMLScanner::TOKEN XMLScanner::NextToken () {
    if (state == STATE_STREAM_END)
        return TOKEN_STREAM_END;

    do {
        switch (state) {
        /* Content */
        case STATE_CONTENT:
            switch (current) {
            /* Element tag */
            case '<' :
                state = STATE_ELEMENT_TAG;
                if (! output.isEmpty ()) {
                    // TODO : check for whitespace only elements ...
                    return TOKEN_CHARACTER_DATA;
                }
                break;

            case '&' :
                ReadReference ();
                break;

            case ']' :
                /* checks for invalid CDATA section end */
                ReadCharacter ();
                if (current == ']') {
                    ReadCharacter ();
                    if (current == '>') {
                        ReadCharacter ();
                        throw IllegalCharacterException ();
                    } else {
                        output.Append (']');
                        output.Append (']');
                        output.Append (current);
                    }
                } else {
                    output.Append (']');
                    output.Append (current);
                }
                break;

            default :
                output.Append (current);
                break;
            }
            break;

        /* Element Tag */
        case STATE_ELEMENT_START_OPENING:
            if (current == '!') {
                ReadCharacter ();
                state = STATE_SPECIAL_ELEMENT;

            } else if (current == '?') {
                ReadCharacter ();
                state = STATE_CONTENT;
                return ReadProcessingInstruction ();

            } else if (current == '/') {
                ReadCharacter ();
                state = STATE_ELEMENT_END_NAME;
                return TOKEN_ELEMENT_END_TAG;

            } else if (isNameFirst (current)) {
                state = STATE_ELEMENT_START_NAME;
                return TOKEN_ELEMENT_START_OPENING;

            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;

        /* Special elements (comments and CDATA sections etc ...) */
        /* '<!' ... */
        case STATE_SPECIAL_ELEMENT:
            if (current == '-') {
                ReadComment ();
            } else if (current == '[') {
                ReadCDATASection ();
            } else {
                throw UnsupportedFeatureException (position);
            }
            state = STATE_CONTENT;
            break;

        /* Element start name target */
        /* '<' ... */
        case STATE_ELEMENT_START_NAME:
            if (isNameFirst (current)) {
                state = STATE_ELEMENT_ATTRIBUTES_START;
                return ReadQualifiedName ();
            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;

        /* Element start name target */
        /* '</' ... */
        case STATE_ELEMENT_END_NAME:
            if (isNameFirst (current)) {
                state = STATE_ELEMENT_END_TAG;
                return ReadQualifiedName ();
            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;

        /* Attributes */
        case STATE_ATTRIBUTES_START:
            if (isWhitespace (current)) {
                state = STATE_ATTRIBUTES;

            } else if (current == '/') {
                state = STATE_ELEMENT_END_CLOSING;

            } else if (current == '>') {
                state = STATE_CONTENT;
                return TOKEN_ELEMENT_START_CLOSING;

            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;

        /* '<' QualifiedName ... */
        case STATE_ATTRIBUTES :
            if (isWhitespace (current)) {
                break;

            } else if (isNameFirst (current)) {
                state = STATE_ATTRIBUTE_EQUAL;
                return ReadQualifiedName ();

            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;

        case STATE_ELEMENT_END_CLOSING:
            if (current == '>') {
                state = STATE_CONTENT;
                return TOKEN_ELEMENT_END_CLOSING;

            } else {
                throw UnexpectedCharacterException (previous);
            }
            break;


        case STATE_ATTRIBUTE_EQUAL:
            if (current == '\'' || current == '\"') {
                state = STATE_ATTRIBUTES_START;
                return ReadLiteral ();
            }
            break;

        case STATE_ELEMENT_END_TAG:
            if (current == '>') {
                state = STATE_CONTENT;
                return TOKEN_ELEMENT_END_TAG_CLOSING;
            }
            break;
        }

    } while (ReadCharacter ());

    /* Stream end */
    return TOKEN_STREAM_END;
}
void Mouse(int btn, int state, int x, int y)    {
	if (stat.turnedON)	{
		if (btn == GLUT_LEFT_BUTTON && (x > 15 && x<70) && (y>455 && y<505) && state == GLUT_DOWN)    {
			ReadCharacter('0');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>90 && x<145) && (y>455 && y<505) && state == GLUT_DOWN)   {
			if (stat.decimalOperation == 0) {
				if (stat.currentOperand == 0)   {
					stat.operandLength++;
					if (stat.operandLength > 10) {
						return;
					}
					operand1Str[opr1Index++] = '.';
					stat.decimalOperation = 1;
				}
				else if (stat.currentOperand == 1)  {
					stat.operandLength++;
					if (stat.operandLength > 10) {
						return;
					}
					operand2Str[opr2Index++] = '.';
					stat.decimalOperation = 1;
				}
				totalExp[expIndex++] = '.';
			}
			else if (stat.decimalOperation == 1)
				return;
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x > 15 && x<70) && (y>380 && y<430) && state == GLUT_DOWN)   {
			ReadCharacter('1');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>90 && x<145) && (y>380 && y<430) && state == GLUT_DOWN)   {
			ReadCharacter('2');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>165 && x<220) && (y>380 && y<430) && state == GLUT_DOWN)   {
			ReadCharacter('3');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>15 && x<70) && (y>305 && y<355) && state == GLUT_DOWN)   {
			ReadCharacter('4');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>90 && x<145) && (y>305 && y<355) && state == GLUT_DOWN)   {
			ReadCharacter('5');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>165 && x<220) && (y>305 && y<355) && state == GLUT_DOWN)   {
			ReadCharacter('6');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>15 && x<70) && (y>230 && y<280) && state == GLUT_DOWN)   {
			ReadCharacter('7');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>90 && x<145) && (y>230 && y<280) && state == GLUT_DOWN)   {
			ReadCharacter('8');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>165 && x<220) && (y>230 && y<280) && state == GLUT_DOWN)   {
			ReadCharacter('9');
			glutPostRedisplay();
		}

		else if (btn == GLUT_LEFT_BUTTON && (x>240 && x<295) && (y>455 && y<505) && state == GLUT_DOWN)   {
			ReadOperator('+');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>240 && x<295) && (y>380 && y<430) && state == GLUT_DOWN)   {
			ReadOperator('-');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>240 && x<295) && (y>305 && y<355) && state == GLUT_DOWN)   {
			ReadOperator('*');
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>240 && x<295) && (y>230 && y<280) && state == GLUT_DOWN)   {
			ReadOperator('/');
			glutPostRedisplay();
		}

		else if (btn == GLUT_LEFT_BUTTON && (x > 165 && x<295) && (y>155 && y<205) && state == GLUT_DOWN)   {
			//AC is clicked
			ClearEverything();
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>165 && x<220) && (y>455 && y < 505) && state == GLUT_DOWN)   {
			// = is clicked
			CalculateResult();
			glutPostRedisplay();
		}
		else if (btn == GLUT_LEFT_BUTTON && (x>90 && x<145) && (y>155 && y<205) && state == GLUT_DOWN)   {
			exit(0);
		}
	}
	else if (btn == GLUT_LEFT_BUTTON && (x>15 && x<70) && (y>155 && y<205) && state == GLUT_DOWN)   {
		stat.turnedON = 1;
		glutPostRedisplay();
	}

}
void Keys(unsigned char key, int x, int y)  {
	if (stat.turnedON)	{
		switch (key) {
		case '0':
		case '1':
		case '2':
		case '3':
		case '4':
		case '5':
		case '6':
		case '7':
		case '8':
		case '9':
			ReadCharacter(key);
			break;

		case '.':
			if (stat.decimalOperation == 0) {
				if (stat.currentOperand == 0)   {
					stat.operandLength++;
					if (stat.operandLength > 10) {
						return;
					}
					operand1Str[opr1Index++] = '.';
					stat.decimalOperation = 1;
				}
				else if (stat.currentOperand == 1)  {
					stat.operandLength++;
					if (stat.operandLength > 10) {
						return;
					}
					operand2Str[opr2Index++] = '.';
					stat.decimalOperation = 1;
				}
				totalExp[expIndex++] = '.';
			}
			else if (stat.decimalOperation == 1)
				return;
			break;

		case '+':
			ReadOperator('+');
			break;
		case '-':
			ReadOperator('-');
			break;
		case '*':
			ReadOperator('*');
			break;
		case '/':
			ReadOperator('/');
			break;

		case '=':
		case 13:							//ASCII value of return key
			CalculateResult();
			break;

		case 27:							//ASCII value of Escape key
			ClearEverything();
			break;

		default:
			printf("Invalid Character Chosen\n");
			return;
			break;
		}
		glutPostRedisplay();
	}
	else
		return;
}