Форум программистов, компьютерный форум, киберфорум
Наши страницы
С++ для начинающих
Войти
Регистрация
Восстановить пароль
 
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
1

Свой компилятор: а правильно ли я разместил наборы токенов?

02.11.2017, 22:52. Просмотров 205. Ответов 14

Продолжаю тему пустого трепа и размышлений о том "как лучше и приятнее" сделать некоторые фичи компилятора на коленках.
На этот раз оглянулся назад к лексическому анализатору, замечу сразу, он работает сносно, мне нравится =)

Если конкретнее, то вопрос касается не самого анализатора, а набора токенов, которые он ищет.
Так как я работаю в ООП парадигме, с самого начала решено было инкапсулировать всё что связано с лексикой в класс Lexer.
Куда всё жёстче стало когда я закончил работу. Вышло так, что внутри Lexer'а у меня появился нехилый набор констант-токенов (в виде enum)

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
public:
    
    /*
     * Перечисление всех возможных типов токенов
     */
    enum TokenType {
        KEY_WORD,
        ONE_LIT_DELIM,
        TWO_LIT_DELIM,
        INTEGER,
        IDENTIFIER,
        LITERAL,
    };
    
    enum OneLitDelim {
        INPUT_END,
        LINE_DELIM,
        PLUS,
        MINUS,
        MULT,
        DIV,
        POW,
        ASSIGN,
        LPAREN,
        RPAREN,
        LBRACKET,
        RBRACKET,
        LBRACE,
        RBRACE,
        MORE,
        LESS,
        NOT,
        COMMA,
    };
    
    enum TwoLitDelim {
        PLUS_ASSIGN,
        MINUS_ASSIGN,
        DIV_ASSIGN,
        MULT_ASSIGN,
        INCR,
        DECR,
        EQUALS,
        MORE_OR_EQ,
        LESS_OR_EQ,
        NOT_EQ,
    };
    
    enum KeyWord {
        KEY_PROGRAM,
        KEY_VAR,
        KEY_IF,
        KEY_PRINT,
    };
Красота, НО вот крутость в том, что сейчас, когда я достал этот Lexer и использую его для синтаксического анализа, то мне крайне докучают постоянные
C++
1
2
3
4
5
6
7
//тут был код
Lexer::KEY_WORD
//тут тоже
Lexer::ONE_LIT_DELIM Lexer::PLUS Lexer::MINUS
//бла бла бла
Lexer:: Lexer:: Lexer::Lexer::Lexer::Lexer::Lexer::
//просто ужас
Короче, видимость - это жестоко. Уже пальцы болят нажимать на двоеточие. Возникло два варианта движения дальше:
1. Вынести эти константы куда нибудь ещё - пространство имён там, или ещё один класс, а в Lexer'е и синтаксическом анализаторе просто подключать это пространство с помощью using
2. Плевать на всё, ничего не менять, а просто использовать Lexer как неймспейс, юзать его (жестоко, но сработает же )
3. Не делать ничего, ибо хардкор он для крутых

Конечно, это не срочно, не принципиально, но я ведь думаю об этом, да и вопрос довольно интересный, в архитектурном плане, так что вот

P.S. Лексер у меня ещё с универских лаб, которые я потихоньку доделываю сейчас, тогда меня заставили использовать раздельные наборы для разных типов лексем, а при получении токена брать две константы вместо одной (типа парами - ONE_LIT_DELIM, PLUS - вот так). Причём на множественные вопросы "для чего" ответа не было. Ну надо, значит надо, сделал, а зачем, до сих пор не знаю, мб кто знает...
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
02.11.2017, 22:52
Ответы с готовыми решениями:

Свой компилятор C++
Приветствую всех. Меня интересует, можно ли взять какой нибудь компилятор C++,...

Свой компилятор: обработка ошибок
В рамках развития и стремления к высшему делаю свой компилятор. Пишу на плюсах....

Компилятор не хочит выполнять свою работу правильно
Вот код: // test1.cpp : Defines the entry point for the console application....

Как правильно подключить свой заголовочный файл?
Есть два файла. Основной файл - "2.cpp" #include <iostream> #include...

Как правильно предавать наборы контролов в представление из контроллера
В представлении нужно построить сложную таблицу. Таблица должна содержать...

14
Pechkin80
19 / 18 / 7
Регистрация: 14.03.2014
Сообщений: 251
02.11.2017, 23:02 2
DrankUser, Ну а стандарт вам не подсказчик ?
ISO 14882:2003 2.4
preprocessing-token:
header-name
identifier
pp-number
character-literal
string-literal
preprocessing-op-or-punc
each non-white-space character that cannot be one of the above
ISO 14882:2003 2.6
token:
identifier
keyword
literal
operator
punctuator

Там же и фазы трансляции расписаны чтоб голова не пухла от обилия задач.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
02.11.2017, 23:26  [ТС] 3
Pechkin80, я туплю что-то
Что за стандарт? Си++?

Окей, но набор токенов я уже завершил, а если надо будет ещё добавить, то дело нескольких секунд

Сам по себе вопрос темы немного в другом, или я не вкуриваю смысла вами сказанного...
0
Pechkin80
19 / 18 / 7
Регистрация: 14.03.2014
Сообщений: 251
02.11.2017, 23:39 4
DrankUser, Вы компилятор по си++ пишите ? для языка программирования c++ существует международный стандарт. Он имеет разные версии, в зависимости от года выпуска стандарта: c++98(ISO 14882:1998), c++03(ISO 14882:2003), c++11(ISO 14882:2011), c++14(ISO 14882:2014), c++17(пока не опубликован). Я рекомендую использовать версию 2003 года так как она не такая огромная.

Добавлено через 4 минуты
Стандарт это нормативный документ, где формально изложено само описание языка. Другие источники, включая книжку Страуструпа это неофициально всё. Стандарт даёт хорошее преставление о структуре грамматики языка и о многом другом.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
02.11.2017, 23:41  [ТС] 5
Pechkin80, странно, но я нигде не писал о c++, я просто пишу что-то своё, ограниченное лишь моей фантазией, и небольшим ТЗ из универа, которое я постоянно нарушаю, насколько это возможно, ибо так хочу
0
Pechkin80
19 / 18 / 7
Регистрация: 14.03.2014
Сообщений: 251
02.11.2017, 23:43 6
DrankUser, Ну даже если итак, то чтение первых трёх глав даст хорошую пищу как двигаться дальше.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
02.11.2017, 23:46  [ТС] 7
Pechkin80, о чём вообще идёт речь?

Вопрос мой о размещении набора констант в структуре проекта, причём тут вообще с++, его стандарты и движение дальше.
Конечно, за заметку спасибо, я подумаю над этим, но в данной теме это немного оффтоп
0
Croessmah
++Ͻ
14776 / 8452 / 1605
Регистрация: 27.09.2012
Сообщений: 20,800
Записей в блоге: 2
Завершенные тесты: 1
02.11.2017, 23:49 8
Возможно, Вам будет полезно:
1
woldemas
444 / 316 / 173
Регистрация: 06.09.2013
Сообщений: 957
03.11.2017, 09:28 9
Цитата Сообщение от DrankUser Посмотреть сообщение
Так как я работаю в ООП парадигме
В ООП парадигме может быть правильнее было бы некоторые подмножества лексем определить как реализации абстрактного класса (интерфейса) лексемы.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
03.11.2017, 10:05  [ТС] 10
woldemas, ну наконец-то хоть что-то по теме

Да, как вариант можно этот набор выложить в отдельный класс...
Так, сейчас я кстати ещё немного подумал о таблицах неконстантных токенов, можно сделать отдельный класс для них, и на его объект ссылаться во всех анализах, это как вариант
0
woldemas
444 / 316 / 173
Регистрация: 06.09.2013
Сообщений: 957
03.11.2017, 10:27 11
Цитата Сообщение от DrankUser Посмотреть сообщение
Да, как вариант можно этот набор выложить в отдельный класс...
Я имел в виду скорее такую конструкцию:
Кликните здесь для просмотра всего текста

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
class Lexem {
public:    
    const std::string & getValue() const;
    // Для обеспечение диспетчиризации по типу
    // без использования switch конструкций можно
    // попробовать использовать паттерн Visitor
    virtual void Accept(SyntaxAnalyzer &analyzer) = 0;
};
 
class NumericConstant : public Lexem {    
    //...    
    virtual void Accept(SyntaxAnalyzer &analyzer) {
        analyzer.ProcessNumericConstant(*this);
    }
};
 
class Variable : public Lexem {       
    //...
};
 
class Keyword : public Lexem {    
    //...
};
 
class BinaryOperator : public Lexem {    
    //...
};
 
// Анализатор может быть таким
// и по сути представляет собой конечный автомат
// вызовы методов Process осуществляются в нужной
// последовательности вырабатваемой лексером
class SyntaxAnalyzer {
public:
    virtual void ProcessNumericConstant(NumericConstant &nc) = 0;
    virtual void ProcessOperator(BinaryOperator &op) = 0;
    //...
};


Я когда-то писал что-то подобное, но там был не язык программирования, а язык описания данных, с довольно сложной грамматикой и синтаксическими конструкциями.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
03.11.2017, 10:41  [ТС] 12
woldemas, аа, я вижу
На самом деле когда я только взялся за лексер, у меня тоже были такие мысли, но на деле оказалось что создавать классы для токенов мне не надо, так как то что я показал вверху - это просто числовые константы, а класс для хранения одной константы звучит как-то бесполезно.

Вместо этого я сделал структуру Token, которая хранит в себе целочисленную пару тип-id для поиска нужной лексемы среди вышеуказанных енамов. Причём раньше у меня был всего один enum для всех констант, а потому даже надобность в паре отсутствовала, но увы, сейчас, по велению преподавательского состава, у меня несколько енамов.

А проблема сейчас лишь только в неудобстве размещения этих енамов, так как классов, работающих с ними много.

Сейчас я уже подумываю просто обернуть весь компилятор в неймспейс и сделать эти константы глобальными в этой области

Добавлено через 2 минуты
woldemas, хотя сейчас я перечитал ваш код, пораскинул мозгами, и понял, что это выглядит круто

Прикрутить к своему проекту я уже не смогу, так как это куча работы по рефакторингу, времени нет

Но вот в будущем может быть попробую поработать над такой структурой
0
Pechkin80
19 / 18 / 7
Регистрация: 14.03.2014
Сообщений: 251
03.11.2017, 10:52 13
enum лучше вообще не использовать. Граматику лучше задавать текстовым файлом в виде формул бекуса нуара. Тогда после парсинга можно получить структуру что во что вложено.
0
DrankUser
0 / 2 / 3
Регистрация: 29.01.2017
Сообщений: 83
Завершенные тесты: 2
03.11.2017, 13:18  [ТС] 14
Pechkin80, отлично, прямо сейчас я брошу всё что сделал, и вместо того чтоб добиться хоть какого-то результата начну опять полгода рыться в книжках и читать про парсинг грамматик

Понимаете, я не то что бы считаю себя выше этого, нет, напротив, я думал об этом, но всё же более целесообразным считаю доделать хотя бы этот маленький проект. Плюс, вопрос тут вообще не в том, что лучше - enum, просто массив, или же структура ООП. Вопрос в том, как это всё обернуть для более удобного и рационального задания области видимости
0
Pechkin80
19 / 18 / 7
Регистрация: 14.03.2014
Сообщений: 251
03.11.2017, 14:17 15
DrankUser, Всё уже украдено до вас. Никакие полгода не нужно. Если лень делать парсер формул б.с., то берёте готовую библиотеку xml парсинга (в кьюте например или libxml) приспосабливаете формат под свои нужды, за пару часов это делается. Я вам как раз и подсказываю как время сэкономить. Задавать все правила в коде постоянно это вы утоните в нём))) Для правил разрешения имён тоже лучше чтото скриптовое иметь.

Добавлено через 1 минуту
И я вам настоятельно рекомендую почитать стандарт. Как в нём реализовано то что вы хотите сделать, тоже разрешение имён.
1
03.11.2017, 14:17
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
03.11.2017, 14:17

Eclipse + свой компилятор. Как?
Доброе утро! Наконец у меня что-то начало продвигаться в безнадежном деле......

Написал свой синтаксический анализатор+компилятор выражений
Не знаю, можно ли так поступать на этом форуме. Хочу показать вам свои...

Нужен компилятор с возможностью установить свой значок и изменить информацию
Нужен компилятор с возможностью установить свой значок и изменить...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
15
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru