Форум программистов, компьютерный форум, киберфорум
Наши страницы

Пишем свой интерпретатор языка BASIC - C++

Войти
Регистрация
Восстановить пароль
Другие темы раздела
C++ Меню и список http://www.cyberforum.ru/cpp-beginners/thread41194.html
Здравствуйте форумчане. Помоги пожалуйста в следующем вопросе: У меня есть 2связный список, написано меню. Но в моменте когда написано make a list и delete custom необходимо чтобы выводились:...
C++ Здравствуйте! Не могу поместить class в один файл с программой. file.hpp #include "Cat.hpp" // здесь классы "2)" Cat::Cat(int initialAge) { itsAge = initialAge; } Cat::~Cat() { http://www.cyberforum.ru/cpp-beginners/thread41186.html
Массивы строк C++
Привет всем! Задан массив строк. Как узнать который символ встечаетса найбольшое количество раз в етом массиве?
C++ вывод на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер
Please, help me!!! Вот текст программы, которая выводит на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер только квадратов. Проблема в том, что необходимо...
C++ Округление дробного числа до целого в большую сторону. http://www.cyberforum.ru/cpp-beginners/thread41139.html
Доброго дня. Я новичок в программирование на Visual C++. Проблема такая программа должна считать кол-во месяцев, если числа целые то программа шла дальше, если дробное то (например 3.33333) ...
C++ Код из Delphi в C++ Нужно написать курсовую на C++. Сам я в программировании плохо шарю (не программист). Попросил у народу помощи, помогли. Но решение на Delphi: {$APPTYPE CONSOLE} type byteset=set of byte; ... подробнее

Показать сообщение отдельно
Evg
Эксперт CАвтор FAQ
18920 / 6880 / 504
Регистрация: 30.03.2009
Сообщений: 19,379
Записей в блоге: 30
04.08.2009, 17:44
Сам понимаешь, после отпуска с ходу сложно что-то сделать полезное для человечество. Некоторое время должно пройти в традиционно российском виде спорта - борьбе с ленью

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

По поводу неявного приведения типа. Приведение к более широкому типу - я в первый раз такое слышу. По стандарту, как мне казалось, всегда второй операнд приводится к типу первого. Т.е. int+double эквивалентно "int+(int)double". Но на всякий случай уточню

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

Как у тебя реализованы IF'ы? То, что ты ввёл FI, даёт мне повод заподозрить, что одну из альтернатив ты просто пропускаешь без разбора. А потому, если в пропущенной альтернативе есть синтаксическая ошибка, то ты её в этот момент не поймаешь. А поймаешь только тогда, когда исполнение пойдёт по этой альтернативе. Сие означает, что твоя программа, содержащая синтаксическую ошибку, может довольно долго работать (к примеру, несколько дней), но потом сломаться из-за досадной опечатки. Понятно, что для тренировочной программы это мелочь, но вообще проблема серьёзная.

Добавлено через 6 минут 49 секунд
Цитата Сообщение от qwert Посмотреть сообщение
А как называется книга из которой этот пример? Судя по коду она не для начинающих.
Попробую немного более расширенно ответить.

Изначально #pragma делал просто задачу из книги, в которой простенький разбор выражений с печатью результата. В одной из других тем, я спросил его, насколько серьёзно он собирается заниматься программированием. Он ответил, что серьёзно. А потому данную задачу я предложил ему "чуть-чуть" расширить, а потом это "чуть-чуть" вылилось в довольно серьёзную задачу.

В книжках этого ты нигде не найдёшь (разве что готовое решение с краткими пояснениями). Ну и большая практическая польза была в том, что pragma в данном случае прошёл по пути, когда делается неправильное решение, потом переделывается на более правильное. При этом весь процесс работы он ведёт самостоятельно, я лишь делаю небольшие теоретические выкладки (которых тоже, к сожалению, в книжке скорее всего не встретишь). К тому же параллельно зацепляется очень много моментов по технике программирования: задача из нескольких модуле, правильная организация структур данных да и просто программирование на Си++. Всё это делается "под конкретного человека", потому как многие идеи и технические решения pragm'ы остаются за кадром. С моей стороны вся теоретическая часть в теме присутсвует. Так что если есть интерес, попробуй прочти всю тему с начала и повторить всё это безобразие на практике

Добавлено через 1 час 52 минуты 30 секунд
На текущий момент мне видится следующий порядок действий (именно в таком порядке):
  1. Учимся работать с svn. Если ты ещё не перешёл на хранение исходников под управлением svn.
  2. Делаем тестовый пакет с автоматическим запуском и проверкой. Ты уже успел заметить, что после некоторых твоих правок у тебя протухла работа ELSE. Чтобы такого не происходило в дальнейшем, нужно ставить на контроль функциональность твоего интепретатора. Если пояснить на пальцах, то, например, имеем несколько тестовых исходников на бейсике, в которых делается некая контрольная печать, по которой можно сделать вывод о правильной работоспособности той или иной конструкции. Есть эталонная печать. Тестирование заключается в запуске всех тестов и сравнении выдачи с эталонной. Догадываюсь, что этим заниматься лениво, особенно сейчас, но без этого ты не сможешь удерживать стабильность работы интерпретатора
  3. Обсуждаем дальнейшую внутреннюю структуру интерпретатора. Сейчас у тебя наконец появилось общее понимание того, как работает интерпретатор, а потому уже можно приступать к обсуждению. Проблема сам понимаешь какая: построение работы таким образом, чтобы наиболее просто работать с НЕпоследовательной интерпретацией
  4. Реализация базы интерпретатора. Т.е. строим все управляющие конструкции: IF, FOR, GOTO, WHILE, функции. После чего нужно окинуть критическим взглядом реализованное и начать наводить порядок. Потому как дальнейшее развитие поддержки языка будет, в основном, лишь в части добавления новых операторов, базовая часть при этом, скорее всего, останется в неизменном виде (если опять не возникнет желания навести порядок). В том числе будем разбираться и с динамической памятью (в чём заключается проблема, я пока не понял)

Более далёкая перспектива
  1. Допиливание конструкций, внимательное изучение языка (бейсика) с целью привести наш интерпретатор как можно ближе к стандартным бэйсикам. В том числе и можно решать, как у нас быдет язык чувствовать регистр букв (т.е. "IF" и "if" будет одно и тоже или нет и т.п.)
  2. Перенос интерпретатора на другую платформу (например, windows). Итоговое написание интерпретатора в виде кросс-платформенной программы. Идеальным вариантом будет поддержка в интерпретаторе графики: под виндой и линухом это строится на совершенно разных принципах
  3. Реализация IDE для интерпретатора (по типу всяких билдеров)
  4. Реализация отладчика. ХЗ, есть ли отладчики у интерпретаторов, но в теории вроде бы это ничему не противоречит. Если делать только под текстовый режим, то 100% это реализуемо и не особенно сложно

Добавлено через 6 часов 58 минут 9 секунд
отом могу забыть. Ещё в линуксовом разделе заведи отдельную тему по Makefile. Покажу, как с использованием gcc строить автоматические зависимости от .h файлов (чтобы постоянно Makefile не хачить при изменении структуры include'ов)

Добавлено через 13 минут 5 секунд
Немного по стилю написания

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
void syntax_parserStmtKwLET()
{
...
    if (parser_GetToken() == TOKEN_IDENT)
    {
        int i = FindNameOverVector (::parser_CurTokenStr,defined_vars);
 
        if (i >= 0)
        {
            if (parser_GetToken() == TOKEN_DELIM_EQUAL)
            {
                defined_vars.at(i) = syntax_parserBinaryExpr ();
                defined_vars.at(i).SetInitialization(true);
            }
            else error(WRONG_LET_STATEMENT);
        }
        else error(UNDEFINED_SYMBOL, ::parser_CurTokenStr);
    }
    else error(WRONG_LET_STATEMENT);
}
Такой код тяжело читать, потому что интересующий нас фрагмент находится глубоко во вложении. При этом образное мышление у тебя линейное: сначала ДОЛЖНО быть имя переменной, затем ДОЛЖЕН быть знак "равно" затем ДОЛЖНО быть выражение

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

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Разбор конструкции LET Ident "=" Expr
// Слово LET разобрано в месте вызова
void syntax_parserStmtKwLET()
{
...
    // Ident
    if (parser_GetToken() != TOKEN_IDENT)
      error(WRONG_LET_STATEMENT)
 
    // Поиск переменной по имени
    int i = FindNameOverVector (::parser_CurTokenStr,defined_vars);
 
    if (i < 0)
      error(UNDEFINED_SYMBOL, ::parser_CurTokenStr);
 
    // "="
    if (parser_GetToken() != TOKEN_DELIM_EQUAL)
      error(WRONG_LET_STATEMENT);
 
    // Expr
    defined_vars.at(i) = syntax_parserBinaryExpr ();
    defined_vars.at(i).SetInitialization(true);
}
1
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.
Рейтинг@Mail.ru