@dearname

Как переходить между состояниями?

Добрый вечер, не могу понять, как переходить между состояниями в лексическом анализаторе. Вот взял я один символ из файла, потом определяю, что он цифра, но возможно 3 случая тогда, к примеру,
a=3 - я должен вставить в вектор, индификатор "a"; да, но так как нету пробела, у меня "a=3" заносится в одну ячейку вектора.
c a= 3 - так же "a=" - в одной ячейке.
вот только это работает a = 3.
как мне вот запоминать, я ведь все время работаю, с одним символом.
Можно хотя бы с цифрами пояснить, то есть показать, как в данном случае будет переход состояний осуществляться. Мы должны с каждым новым символом находится в каком-то состоянии, это я понимаю, но вот как это в коде, хотя бы на таком маленьком примере, можете показать. Дальше я сам реализую.

Данный код, считывает файл, и заносит в вектор все слова этого файла. Предположим у меня в попалась вот такая вот конструкция a=3 - как мне разрешить эту ситуацию, чтобы в векторе было не "a=3", а "a", "=", "3" то есть 3 ячейки занимает в векторе эта строка.
#include "stdafx.h"
#include <cstdlib>
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
#include <vector>

using namespace std;

struct Lexeme {	
	int start, end;
	string lexeme;
};
vector<Lexeme> v;
void gToken(ifstream &fin, vector<Lexeme> &v);
void wToken();
int main()
{
	char filename[30];
	ifstream fin;
	char q;
	//cin >> filename;
	fin.open("text.txt");
	gToken(fin, v);
	fin.close();
	wToken();
	system("PAUSE");
	return EXIT_SUCCESS;
}
void gToken(ifstream &fin, vector<Lexeme> &v)
{
	int j = 0;
	char ch;
	Lexeme l;
	while (fin >> ch) 
	{
		int i = 0;
		l.lexeme += ch;
		while (fin.get(ch))
		{	
		if (ch != ' ' && ch != '\n')
		{
			cout << ch<<endl;
					l.lexeme += ch;
			}
		else
		{
			j++;
			l.start = j - i;
			l.end=j;
			break;
		}
		}
	v.push_back(l);
	l.lexeme ="";
	}
}
void wToken()
{
	for (int i = 0; i < v.size(); i++) cout << v[i].lexeme << endl;
}
  • Вопрос задан
  • 2462 просмотра
Пригласить эксперта
Ответы на вопрос 2
Rsa97
@Rsa97
Для правильного вопроса надо знать половину ответа
Вам нужно для начала расписать лексемы, построить конечный автомат и доработать его для вычисления значений лексем. Пример для алфавита [a-z0-9=], идентификаторов, целых чисел и присвоения:
<буква> := [a-z]
<цифра> := [0-9]
<равно> := [=]
<идентификатор> := <буква>(<буква>|<цифра>)*
<число> := <цифра>(<цифра>)*
Автомат:
_    [a-z]  [0-9]  [=]  ¬
s0    s1     s2    ok  end
s1    s1     s1    ok  ok
s2    ok     s2    ok  ok

Доработанный автомат:
_       in == ['a'-'z']                     in == ['0'-'9']                    in == ['=']           ¬
s0    val := in; next; s1                 val := in-'0'; next; s2            next; ret(ASSIGN)  ret(EOT)
s1    val := concat(val, in); next; s1    val := concat(val, in); next; s1   ret(IDENT, val)    ret(IDENT, val)
s2    ret(INTEGER, val)                   val := val*10+in-'0'; next; s2     ret(INTEGER, val)  ret(INTEGER, val)

s0 - исходное состояние, in - текущий символ, next - переход к следующему символу в потоке, ret возвращает тип лексемы и её значение.
Список переходов при анализе 'a1=95':
Первый вызов:
s0 ('a') -> val := 'a'; next; s1
s1 ('1') -> val := 'a1'; next; s1
s1 ('=') -> ret(IDENT, 'a1')

Второй вызов:
s0 ('=') -> next; ret(ASSIGN)
Третий вызов:
s0 ('9') -> val := 9; next; s2
s2 ('5') -> val := 95; next; s2
s2 (¬) -> ret(INTEGER, 95)

Следующие вызовы:
s0 (¬) -> ret(EOT)
Ответ написан
jcmvbkbc
@jcmvbkbc
"I'm here to consult you" © Dogbert
открой для себя flex
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы