Блог программиста

Цель: пассивный доход 100 тыс. руб. в мес.

Задачи:

  1. Разработка языка Cj
  2. ...
  3. ...


Также в блоге: изучаем и разрабатываем что-то новое, делимся опытом.

Подписывайтесь:
Cj - язык программирования

Новый язык программирования, для разработки сайтов и приложений, подробнее...


Спецификация:

  1. Комментарии
  2. Типы данных, переменные, функции
  3. ...

Lexer - лексический анализатор

Напишем универсальный лексер - лексический анализатор. Он будет выглядеть примерно так:

class Lexer {
public:
	Lexer();
	~Lexer();

	virtual void start(Str s);
	virtual Str step();

	virtual Str run(Str s);

	virtual bool isLetter(char a);
	virtual bool isNumeral(char a);
	virtual bool isSpecial(char a);

	virtual bool isIdentifier(Str lexema);
	virtual bool isNumber(Str lexema);
	virtual bool isSpecial(Str lexema);
	virtual LexemaType getLexemaType(Str lexema);
	
	virtual Token getToken(Str lexema);
};

Рассмотрим исходный код класса Lexer подробнее. С конструктором и деструктором всё понятно - они должны быть, практически, в любом классе.

Функция run(), в которую передаётся исходник программы, пробегает по всему коду и возвращает список лексем:

Str Lexer::run(Str s) {
	start(s);
	Str result;
	while (true) {
		Str lex = step();
		result += lex + "\r\n";
		if (pos >= len) break;
	}
	return result;
}

Использовать её в таком виде можно если пишем только один лексер или для тестов. Если нам нужно использовать лексический анализатор, например, в каком-нибудь парсере, мы вызываем start() и этим парсером крутим в цикле функцию step().

Лексический анализатор работает с тремя видами символов: буквами, цифрами и специальными символами. Для этого нужны функции соответственно isLetter(), isNumeral() и isSpecial(). А также с тремя типами лексем: идентификаторами isIdentifier(), числами isNumber() и специальными лексемами isSpecial().

Заметим, что две функции isSpecial отличаются друг от друга параметрами. Одна работает с одним символом, другая с лексемой, то есть со строкой. Не путайте их.

Определив тип лексем getLexemaType(), мы можем сформировать и вернуть, например, парсеру токен getToken(), который, в отличии от лексемы, содержит и лексему и её тип.

Мы просто следуем Википедии:

В простых случаях понятия «лексема» и «токен» идентичны, но более сложные токенизаторы дополнительно классифицируют лексемы по различным типам...

Наш лексический анализатор подходит и для продвинутого парсера. Мы должны в этом случае не просто в цикле крутить step(), а ещё и формировать токены, примерно как-то так:

start(s);
while (true) {
	Str lexema = step();
	Token token = getToken(lexema);
	...
}

На данный момент, мы научили лексер анализировать примечания // и /* */, а также строчки, заключённые в двойные кавычки "".

Пример использования нашего лексического анализатора можно найти на Гитхабе.


Отправить комментарий
Контакты
vk.com/sitev_ru
Skype: sitev.ru
E-mail: mike@sitev.ru
github.com/sitev

Рейтинг@Mail.ru

Besucherzahler
счетчик посещений