Скачиваний:
20
Добавлен:
01.05.2014
Размер:
6.35 Кб
Скачать
#include <istream>
#include <iostream>
#include <cstdio>
#include <cctype>

#include "TokenParser.hpp"

using namespace Parser_impl;

char* Parser_impl::tokenName[] = 
	{ 	"identifier",
		"var", "int", "float", "void", "begin", "end", "if",  
		"then", "else", "while", "do", "write", "return", "read", 
		"wasError", "exit",
		"=", "||", "&&", "+", "-", "*", "/", "%", "^", "!",
		"==", "!=", "<", "<=", ">", ">=", "-", "+", ";", ",", "(", ")", "EOF"
	};

TokenParser::MapStr2Token TokenParser::reservedWords;
	
void TokenParser::initReservedWords()
{
	if (reservedWords.size() >0)
		return;
		
	reservedWords["var"]		= T_VAR;
	reservedWords["int"] 		= T_INT;
	reservedWords["float"] 		= T_FLOAT;
	reservedWords["void"] 		= T_VOID;
	reservedWords["begin"] 		= T_BEGIN;
	reservedWords["end"] 		= T_END;
	reservedWords["if"] 		= T_IF;
	reservedWords["then"]		= T_THEN;
	reservedWords["else"] 		= T_ELSE;
	reservedWords["while"] 		= T_WHILE;
	reservedWords["do"] 		= T_DO;
	reservedWords["write"] 		= T_WRITE;
	reservedWords["return"] 	= T_RETURN;
	reservedWords["read"] 		= T_READ;
	reservedWords["wasError"] 	= T_WASERROR;
	reservedWords["exit"] 		= T_EXIT;
}

void TokenParser::makeDelimToken()
	{
		current.type = TYPE_DELIM;
		switch (ch) {
			
			case ';' : 
				current.value = T_SEMIC;
				break;
			case ',' : 
				current.value = T_COMMA;
				break;
			case '(' : 
				current.value = T_LBRACK;
				break;
			case ')' : 
				current.value = T_RBRACK;
				break;
			case EOF : 
				current.value = T_EOF;
				break;
		}
	}

namespace {
    
    void replaceAll(std::string& str, const char* find, const unsigned l1, 
                                      const char* replace)
    {
        using std::string;
        string::size_type pos = str.find(find,0);
        while (pos != string::npos) {
            str.replace(pos, l1, replace);
            pos = str.find(find,pos);
        }
    }
    
}

void TokenParser::makeOperationToken()
	{
		current.type = TYPE_OPER;
		switch (ch) {
			
			case '+' : 
				current.value = T_PLUS;
				break;
			case '-' : 
				current.value = T_MINUS;
				break;
			case '*' : 
				current.value = T_MUL;
				break;
			case '%' : 
				current.value = T_MOD;
				break;			
			case '/' : 
				current.value = T_DIV;
				break;
			case '^' : 
				current.value = T_DEG;
				break;
			case '=' : 
				current.value = T_ASS;
				break;
			case '!' : 
				current.value = T_NOT;
				break;
			case '<' : 
				current.value = T_LSS;
				break;
			case '>' : 
				current.value = T_GRT;
				break;
			default :
				std::cerr << "Wrong operation " << ch << "in TokenParser::makeOperationToken()!" << std::endl;
		}
	} 

void TokenParser::getNextToken()
{
	if (pushbacked) {
		pushbacked = false;
		return;
	}
	
	States state = ST_START;
	
	while (state != ST_FINISH)
	switch (state) {
		
		case ST_START:
			
			while (std::isspace(ch)) {
				if (ch == '\n') 
					++lineNumber;
				getNextChar();
			}
			
			if (std::isalpha(ch) || ch == '_') { // ID
				clearBuffer();
				addCharToBuffer();
				getNextChar();
				
				while( std::isalpha(ch) || ch == '_' || std::isdigit(ch) ){
					addCharToBuffer();
					getNextChar();
				}
				
				MapStr2Token::iterator pos = reservedWords.find(current.str);
				if ( pos != reservedWords.end()){
					current.type 	= TYPE_RES;
					current.value 	= pos->second;
				} else {
					current.type = TYPE_ID;					
				}									
				
				state = ST_FINISH;
								
			} else if (std::isdigit(ch) ){ // Number
				clearBuffer();
				
				do {				
					addCharToBuffer();
					getNextChar();					
				} while (std::isdigit(ch));
													
				current.isFloat = false;
				
				if (ch == '.') {
					current.isFloat = true;
					addCharToBuffer();
					getNextChar();
					while (std::isdigit(ch)){
						addCharToBuffer();
						getNextChar();
					}
				}
				current.type = TYPE_LIT;
				current.value = std::atof(current.str.c_str());
				
				state = ST_FINISH;
								
			} else if (ch == '{') { // Comment
				getNextChar();
				state = ST_COM;
				
			} else if (ch == '\"') { // String
				clearBuffer();
				getNextChar();
				state = ST_STR;
				
			} else if ( isOP() ) { // Operation: +, -, *, /, %, ^
				makeOperationToken();
				getNextChar();
				state = ST_FINISH;	
						
			} else if ( ch == '|' ) { // Operation: ||
				getNextChar();
				if (ch != '|')
					error(ch, '|');
				current.type = TYPE_OPER;
				current.value = T_OR;
				getNextChar();
				state = ST_FINISH;
				
			} else if ( ch == '&' ) { // Operation: &&
				getNextChar();
				if (ch != '&')
					error(ch, '&');
				current.type = TYPE_OPER;
				current.value = T_AND;
				getNextChar();
				state = ST_FINISH;
				
			} else if ( isOP3() ) { // Operation: =, !, <, >, ==, !=, <=, >=
				makeOperationToken();				
				getNextChar();
				if (ch == '='){
					switch (current.getLong()) {
						case T_ASS:
							current.value = T_EQ;
							break;
						case T_NOT:
							current.value = T_NEQ;
							break;
						case T_LSS:
							current.value = T_LSSEQ;
							break;
						case T_GRT:
							current.value = T_GRTEQ;
							break;
					}
					getNextChar();
				} 
				state = ST_FINISH;
				
			} else if ( isDelim() ) { // Delimiter: ;, ,, (, ), EOF
				makeDelimToken();
				getNextChar();
				state = ST_FINISH;
				
			} else {
				error(ch);
			}
			
			break; // ST_FINISH
		
		case ST_COM:			
			while (ch != '}'){
				if (ch == EOF) 
					throw TokenParserException("Not closed comment!");
				if (ch == '\n')
					++lineNumber;
				getNextChar();
			}
			getNextChar();
			state = ST_START;
			break; // ST_COM
		
		case ST_STR:			
			while (ch != '\"'){
				if (ch == EOF) 
					throw TokenParserException("Not closed string !");
				addCharToBuffer();
				getNextChar();
			}
			current.type = TYPE_LITSTR;
            replaceAll(current.str, "\\n", 2, "\n");
            replaceAll(current.str, "\\t", 2, "\t");
			getNextChar();
			state = ST_FINISH;
			break; // ST_STR
					
		case ST_FINISH:
			break; // ST_FINISH	
			
	} // switch
	
} // TokenParser::getNextToken()


Соседние файлы в папке MyLanguage