Ejemplo n.º 1
0
Lexeme Lexal::readNumber(int startLine, int startPos, wchar_t first)
{
    std::wstring number;
    number += first;
    Lexeme::Type type = Lexeme::Integer;
    
    while (! reader.isEof()) {
        wchar_t ch = reader.getNextChar();
        pos++;
        if (isDigit(ch))
            number += ch;
        else if (L'.' == ch) {
            if (Lexeme::Integer == type) {
                type = Lexeme::Float;
                number += ch;
            } else
                throw Exception(L"To many dots in number at " + 
                        posToStr(line, pos));
        } else if ((! isSymbol(ch)) && (! isWhiteSpace(ch)))
            throw Exception(L"invalid number at " + posToStr(line, pos));
        else {
            pos--;
            reader.ungetChar(ch);
            break;
        }
    }

    if (L'.' == number[number.length() - 1])
        throw Exception(L"Missing digit after dot at " + posToStr(line, pos));

    return Lexeme(type, number, startLine, startPos);
}
Ejemplo n.º 2
0
/* Теперь сама функция для лексического анализа, выделяющая из входного
потока символов очередную лексему. Она предполагает, что при ее вызове
текущий символ - первый символ лексемы, после ее завершения текущий
символ - следующий за лексемой.
Возвращает она как раз найденную лексему.

А это регулярная грамматика, на основе которой производится разбор, здесь
\w обозначает букву, а \s пробельный символ (по аналогии с регулярными выражениями):

S -> \w W | [()] D | ! | ) | ( | $ | \s S
W -> \w W | eps
D -> &

Первая альтернатива в S - выделение констант (из алфавитных символов), вторая -
двусимвольного разделителя (&&), далее - разделители (отрицание, скобки) и конец
ввода. Последняя альтернатива в S - это правило для пропуска пробелов.

W выделяет константы (цепочки букв), а D - двухсимвольный разделитель (&&).
*/
Lexeme readNextLexeme() {
    enum State { S, W, D }; // Итак, у нас есть три состояния - дополнительных здесь объявлять не будем

    State currentState = S; // Переменная для состояния, начальное состояние - S

    std::string buf; // Это строка-буфер, в котором будут накапливаться символы, образующие лексему

    while (true) { // Цикл обработки
        switch (currentState) { // В зависимости от текущего состояния
            case S: // Если мы в начальном состоянии
                 // Если у нас здесь пробельный символ, то мы его просто пропускаем
                if ( currentChar == ' ' ) {
                    gc(); // То есть считываем следующий
                    currentState = S; // И остаемся в том же состоянии
                } else if ( isalpha( currentChar ) ) { // Если текущий символ - буква
                    buf += currentChar; // Тогда добавляем ее в буфер-накопитель лексемы
                    gc(); // Считываем следующий символ
                    currentState = W; // И переходим в состояние W - для констант
                } else if ( currentChar == '&' ) { // Если символ - & - то есть часть операции "И"
                    buf += currentChar; // Добавляем его в строку-буфер
                    gc(); // Считываем следующий символ
                    currentState = D; // И переходим в состояние D
                } else if ( currentChar == '!' || currentChar == '(' || currentChar == ')' ) { // Если же это односимвольный разделитель
                    buf += currentChar; // То добавляем его в строку-буфер
                    gc(); // Считываем следующий символ

                    int index = find( buf, LEX_DELIMS ); // Находим этот разделитель в таблице

                    return Lexeme( LEX_DELIM, index, buf ); // И возвращаем соответствующую лексему
                } else if ( currentChar == '\n' || currentChar == '\r' ) { // Если символ - конец ввода
                    return Lexeme( LEX_EOF, LEX_NULL, "$" ); // То возвращаем лексему конца ввода
                } else { // Иначе - какой-то непонятный символ
                    buf += currentChar; // Добавляем его в строку-буфер
                    return Lexeme( LEX_NULL, LEX_NULL, buf ); // И возвращаем ошибочную лексему
                }
                break;
            case W: // Состояние распознавания констант
                if ( isalpha( currentChar ) ) { // Если символ - буква
                    buf += currentChar; // То добавляем его в строку-буфер
                    gc(); // Считываем следующий
                    currentState = W; // И остаемся в том же состоянии
                } else { // Другой символ - значит константа уже закончилась
                    int index = find( buf, LEX_CONSTS ); // Находим ее в таблице

                    return Lexeme( LEX_CONST, index, buf ); // Просто возвращаем соответствующую константе лексему
                }
                break;
            case D: // Состояние распознавания двухсимвольного разделителя
                if ( currentChar == '&' ) { // Он у нас один - &&, и если это он
                    gc(); // То, считываем следующий символ
                    return Lexeme( LEX_DELIM, LEX_DEL_AND, "&&" ); // И возвращаем соответствующую лексему
                } else { // Иначе
                    buf += currentChar; // Добавляем символ в строку-буфер
                    return Lexeme( LEX_NULL, LEX_NULL, buf ); // И возвращаем ошибочную лексему
                }
                break;
        };
    }
}
Ejemplo n.º 3
0
Lexeme Lexal::getNext()
{
    skipSpaces();
    if (reader.isEof())
        return Lexeme(Lexeme::Eof, L"", line, pos);

    int startLine = line;
    int startPos = pos;

    wchar_t ch = reader.getNextChar();
    pos++;

    if (isIdentStart(ch))
        return readIdent(startLine, startPos, ch);
    else if (isDigit(ch))
        return readNumber(startLine, startPos, ch);
    else if (isQuote(ch))
        return readString(startLine, startPos, ch);
    else if (isSymbol(ch))
        return Lexeme(Lexeme::Symbol, toString(ch), startLine, startPos);
    
    throw Exception(L"Invalid character at "+ posToStr(startLine, startPos));
}
Ejemplo n.º 4
0
Lexeme Lexal::readIdent(int startLine, int startPos, wchar_t first)
{
    std::wstring ident;
    ident += first;
    
    while (! reader.isEof()) {
        wchar_t ch = reader.getNextChar();
        if (! isIdentCont(ch)) {
            reader.ungetChar(ch);
            break;
        }
        ident += ch;
        pos++;
    }

    return Lexeme(Lexeme::Ident, ident, startLine, startPos);
}
Ejemplo n.º 5
0
Lexeme Lexal::readString(int startLine, int startPos, wchar_t quote)
{
    std::wstring str;
    bool closed = false;
    
    while (! reader.isEof()) {
        wchar_t ch = reader.getNextChar();
        pos++;
        if ('\n' == ch) {
            line++;
            pos = 0;
            str += ch;
        } else if ('\\' == ch) {
            if (! reader.isEof()) {
                wchar_t nextCh = reader.getNextChar();
                if (isWhiteSpace(nextCh))
                    throw Exception(L"Invalid escape sequence at " +
                            posToStr(line, pos));
                pos++;
                switch (nextCh) {
                    case L'\t': str += L'\t'; break;
                    case L'\n': str += L'\n'; break;
                    case L'\r': str += L'\r'; break;
                    default:
                        str += nextCh;
                }
            }
        } else if (quote == ch) {
            closed = true;
            break;
        } else
            str += ch;
    }

    if (! closed)
        throw Exception(L"String at " + posToStr(startLine, startPos)
                + L" doesn't closed");

    return Lexeme(Lexeme::String, str, startLine, startPos);
}
//************************************************************************************
Lexeme CBCGPOutlineParser::GetNext (const CString& strIn, int& nOffset, const int nSearchTo)
{
	while (nOffset >= 0 && nOffset < strIn.GetLength () && nOffset <= nSearchTo)
	{
		if (IsEscapeSequence (strIn, nOffset))
		{
			continue;
		}

		for (int i = 0; i <= m_arrBlockTypes.GetUpperBound (); i++)
		{
			BlockType* pBlockType = m_arrBlockTypes [i];
			ASSERT (pBlockType != NULL);

			// Nested blocks:
			if (pBlockType->m_bAllowNestedBlocks)
			{
				int nEndOffset;
				if (Compare (strIn, nOffset, pBlockType->m_strOpen, nEndOffset))
				{
					Lexeme lexem (i, LT_BlockStart, nOffset, nEndOffset);
					nOffset += pBlockType->m_strOpen.GetLength ();
					return lexem;
				}
				else if (Compare (strIn, nOffset, pBlockType->m_strClose, nEndOffset))
				{
					Lexeme lexem (i, LT_BlockEnd, nOffset, nEndOffset);
					nOffset += pBlockType->m_strClose.GetLength ();
					return lexem;
				}
			}
			// NonNested blocks:
			else
			{
				int nEndOffset;
				if (Compare (strIn, nOffset, pBlockType->m_strOpen, nEndOffset))
				{
					Lexeme lexem (i, LT_CompleteBlock, nOffset, nEndOffset);
					nOffset += pBlockType->m_strOpen.GetLength ();

					if (!pBlockType->m_strClose.IsEmpty ())
					{
						// find close token skipping escape sequences:
						while  (nOffset >= 0 && 
								nOffset < strIn.GetLength () && 
								nOffset <= nSearchTo)
						{
							if (IsEscapeSequence (strIn, nOffset))
							{
								continue;
							}

							if (Compare (strIn, nOffset, pBlockType->m_strClose, nEndOffset))
							{
								nOffset += pBlockType->m_strClose.GetLength ();
								if (pBlockType->m_strClose == _T("\n"))
								{
									nOffset--;
								}

								lexem.m_nEnd = nOffset - 1;
								return lexem;
							}

							nOffset++;
						}
					}
					
					if (pBlockType->m_bIgnore)
					{
						nOffset = lexem.m_nStart;
					}
					else
					{
						lexem.m_nEnd = strIn.GetLength () - 1;
						return lexem;
					}
				}
			}

		}

		nOffset++;
	}

	return Lexeme (0, LT_EndOfText, 0, 0);
}
Ejemplo n.º 7
0
Lexeme Scanner::get_lex() {
	int number, j;
	current_state = START;
	type_of_lex tmp;
	do {
		switch(current_state) {
			case START:	
				if(next == ' ' || next == '\n' || next == '\t') {
					if(next == '\n') line++;
					get_next();
				} else if(isalpha(next)) {
					current_state = IDENT;
					clear_buffer();
					add_next_to_buffer();
					get_next();
				} else if(isdigit(next)) {
					current_state = NUMB;
					number = next - '0';
					get_next();
				} else if(next == '\'') {
					current_state = STRI1;
					clear_buffer();
					get_next();
				} else if(next == '\"') {
					current_state = STRI2;
					clear_buffer();
					get_next();
				} else if(next == '>' || next == '<' || next == '=' || next == '&' || next == '|' || next == '!' || next == '/' || next == '-' || next == '+') {
					current_state = DELIM2;
					clear_buffer();
					add_next_to_buffer();
					get_next();
				} else if(next == -1) {
					return Lexeme(LEX_FIN);
				} else {
					current_state = DELIM;
					clear_buffer();
					add_next_to_buffer();
				}
				break;

			case IDENT:
				if(isalpha(next) || isdigit(next)) {
					add_next_to_buffer();
					get_next();
				} else if(MJSWords.find(scan_buffer) != MJSWords.end()) {
					tmp = MJSWords[scan_buffer];
					if(tmp == LEX_TRUE) {
						return Lexeme(LEX_BOOL, true);
					} else if(tmp == LEX_FALSE) {
						return Lexeme(LEX_BOOL, false);
					} else {
						return Lexeme(tmp);
					}
				} else if(find(MJSFields.begin(), MJSFields.end(), scan_buffer) != MJSFields.end()) {
					return Lexeme(LEX_FIELDS, string(scan_buffer));
				} else if(find(MJSMethods.begin(), MJSMethods.end(), scan_buffer) != MJSMethods.end()) {
					return Lexeme(LEX_METHODS, string(scan_buffer));
				} else {
					return Lexeme(LEX_ID, TOI.put(scan_buffer));
				}
				break;

			case NUMB:
				if(isdigit(next)) {
					number = number * 10 + (next - '0');
					get_next();
				} else {
					return Lexeme(LEX_NUM, number);
				}
				break;

			case STRI1:
				if(next == '\'') {
					get_next();
					return Lexeme(LEX_STR, string(scan_buffer));
				} else if(next == -1) {
					throw lexical_exception(next, line, "Unexpected EOF in LEX_STR");
				} else if(next == '\\') {
					get_next();
					if(next == 'n') 
						add_to_buffer('\n');
					get_next();
				} else {
					add_next_to_buffer();
					get_next();
				}
				break;

			case STRI2:
				if(next == '\"') {
					get_next();
					return Lexeme(LEX_STR, string(scan_buffer));
				} else if(next == -1) {
					throw lexical_exception(next, line, "Unexpected EOF in LEX_STR");
				} else if(next == '\\') {
					get_next();
					if(next == 'n') {
						add_to_buffer('\n');
					} else {
						add_next_to_buffer();
					}
					get_next();
				} else {
					add_next_to_buffer();
					get_next();
				}
				break;

			case DELIM:
				if(MJSDelims.find(scan_buffer) != MJSDelims.end()) {
					get_next();
					return Lexeme(MJSDelims[scan_buffer]);
				} else {
					throw lexical_exception(next, line, "Forbidden symbol");
				}
				break;

			case DELIM2:
				add_next_to_buffer();
				if(scan_buffer[0] == '=' && next == '=') {
					current_state = DELIM3;
					get_next();
				} else if(MJSDelims.find(scan_buffer) != MJSDelims.end()) {
					get_next();
					if(MJSDelims[scan_buffer] == LEX_COMM) {
						current_state = COMM;
					} else {
						return Lexeme(MJSDelims[scan_buffer]);
					}
				} else {
					scan_buffer[1] = '\0';
					if(MJSDelims.find(scan_buffer) != MJSDelims.end()) {
						return Lexeme(MJSDelims[scan_buffer]);
					} else {
						throw lexical_exception(next, line, "Forbidden symbol");
					}
				}
				break;

			case DELIM3:
				if(next == '=') {
					get_next();
					return Lexeme(LEX_IDENT);
				} else {
					return Lexeme(LEX_EQ);
				}
				break;

			case COMM:
				if(next == '\n' || next == -1) {
					line++;
					current_state = START;
					clear_buffer();
					get_next();
				} else {
					get_next();
				}

			default:
				break;
		}
	} while(true);
}