Форум программистов, компьютерный форум CyberForum.ru

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

Восстановить пароль Регистрация
Другие темы раздела
C++ Меню и список http://www.cyberforum.ru/cpp-beginners/thread41194.html
Здравствуйте форумчане. Помоги пожалуйста в следующем вопросе: У меня есть 2связный список, написано меню. Но в моменте когда написано make a list и delete custom необходимо чтобы выводились: Введите элемент и номер. вот сам код: #ifndef __list_h #define __list_h #include <iostream>
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!!! Вот текст программы, которая выводит на экран набор треугольников и квадратов, которые произвольно двигаются и меняют размер только квадратов. Проблема в том, что необходимо исправить код, чтоб фигуры не исчезали за экран (т.е. 640х460) и были компактным набором, т.е. двигались неменяя своего положения относительно друг друга и стукаясь об стенку экрана меняли свое...
C++ Округление дробного числа до целого в большую сторону. http://www.cyberforum.ru/cpp-beginners/thread41139.html
Доброго дня. Я новичок в программирование на Visual C++. Проблема такая программа должна считать кол-во месяцев, если числа целые то программа шла дальше, если дробное то (например 3.33333) программа не округляет это число (в большую сторону) до 4. Перелопатил тонны литературы, но пропустил или не нашёл этого, большая просьба написать функцию которая могла бы это делать, или способ какой.
C++ Код из Delphi в C++ Нужно написать курсовую на C++. Сам я в программировании плохо шарю (не программист). Попросил у народу помощи, помогли. Но решение на Delphi: {$APPTYPE CONSOLE} type byteset=set of byte; var d:array of longint; procedure c; var a,b,i:longint; подробнее

Показать сообщение отдельно
Evg
Эксперт С++Автор FAQ
 Аватар для Evg
16821 / 5242 / 318
Регистрация: 30.03.2009
Сообщений: 14,118
Записей в блоге: 26
17.08.2009, 17:52     Пишем свой интерпретатор языка BASIC
Цитата Сообщение от #pragma Посмотреть сообщение
Я посмотрел твои исходники,вроде всё понятно,но я не представляю,что изменить именно в моей реализации,как-то смутно всё.Как будто снова вернулся к отправной точке,когда только начинал перекраивать калькулятор.Просто не могу представить механизм работы после промежуточного представления. Может,я просто морально не готов писать всё заново Но если бы точно представлял,что и как сделать,то наверное переделал бы.
Морально быть готовым написать заново - тоже важно И в этом вопросе я тебя понимаю.

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

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

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

PureBasic
1
2
3
4
LET a = 5
LET b = 3
PRINT a
PRINT b
Считаем, что у анс есть простая реализация языка, в которой в переменную можно присвоить значение (пока без выражения), и можно распечатать переменную. Итого, у нас есть два оператора: "LET <var> = <value>" и "PRINT <var>". Теперь нам эту программу нужно сохранить в некотором внутреннем виде, чтобы дальше можно было работать без файла.

Промежуточное представление будет состоять из statement'ов. Все они провязаны в список по очереди через поле next (см. ниже). Структура для хранения представления statement'а в таком упрощённом случае следующая

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
enum StatementKind
{
  STMK_LET,
  STMK_PRINT
};
 
struct Statement
{
  // Через это поле мы провязываем всё в список
  struct Statement *next;
 
  // Тип statement'а
  StatementKind kind;
 
  union
  {
    // Данные для LET
    struct
    {
      Variable *var; // левая часть присваивания
      Value *val;  // правая часть присваивания
    } let;
 
    // Данные для PRINT
    struct
    {
      Variable *var; // в простейшем случае у нас только один аргумент в виде переменной
    } print;
  } data;
}
Я здесь для переменных испольхзую ссылку Variable. Ты у себя в коде использовал некое целое число, которое определяет положение в векторе. Можно хранить и число, но на мой взгляд удобнее хранить непосредственно ссылку на Variable. Ты для начала делай так, как тебе более понятно, а потом уже будем пределывать "как правильно"

При таком раскладе привожу код, который "вручную" создаёт промежуточное представление. Чтобы понятно было, что у нас в итоге получится. Понятно, что аналогичное представление у тебя будет строиться в процессе работы парсера. Разделяю построение каждого оператора отдельно (ибо реально они будут отдельно), перменная Last моделирует некую глобальную переменную

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
Statement *s1 = new (хз как там правильно), *s2, *s3, *s4 - создаются аналогично динамически
Statement *Last = NULL;
 
// Создание промежуточного представдения оператора "LET a=5"
s1->next = NULL;
s1->kind = STMK_LET;
s1->data.let.var = var; // подразумеваем, что в 'var' уже лежит указаель на созданную Variable, соотвествующую нашей 'a'
s1->data.let.val = val; // подразумеваем, что в 'val' уже создана Value, соотвествующая константе 5
Last = s1;
 
// Создание промежуточного представдения оператора "LET b=3"
s2->next = NULL;
s2->kind = STMK_LET;
s2->data.let.var = var; // подразумеваем, что в 'var' уже лежит указаель на созданную Variable, соотвествующую нашей 'b'
s2->data.let.val = val; // подразумеваем, что в 'val' уже создана Value, соотвествующая константе 3
Last->next = s2; // прицепляем к последнему оператору
Last = s2;
 
// Создание промежуточного представдения оператора "PRINT a"
s3->next = NULL;
s3->kind = STMK_PRINT;
s3->data.print.var = var; // подразумеваем, что в 'var' уже лежит указаель на созданную Variable, соотвествующую нашей 'a' (точно такой же указатель, как и в "LET a=5")
Last->next = s3; // прицепляем к последнему оператору
Last = s3;
 
// Создание промежуточного представдения оператора "PRINT b"
s4->next = NULL;
s4->kind = STMK_PRINT;
s4->data.print.var = var; // подразумеваем, что в 'var' уже лежит указаель на созданную Variable, соотвествующую нашей 'b' (точно такой же указатель, как и в "LET b=3")
Last->next = s4; // прицепляем к последнему оператору
Last = s4;
В итоге мы получили в памяти интерпретатора некий набор данных, который целиком отразил нашу исходную программу. С этого момента файл нам больше не нужен. После построения промежточного представления запускается второй проход, который его интерпретирует. В нашем простом случае мы просто проходимся по цепочке операций, в каждой операции смотрим поле kind, понимаем, что это за операция, смотрим в data для соотвествующего типа (kind) операции. Когда мы видим операцию присваивания, мы понимаем, что нам нужно исполнить что-то типа "s->data.let.var->SetValue(s->data.let.val)" (ну или как там оно у тебя реализовано, с ходу не помню). Когда мы видим операцию печати, то делаем "(s->data.print.var->GetValue()).PrintValue". Я всё это пишу условно, без детальной привязки к тому, как у тебя реализованы сейчас Variable и Value

Давай пока на этом остановлюсь. И жду уже более конкретных вопросов

Цитата Сообщение от #pragma Посмотреть сообщение
Я решил проблему с динамической памятью,оказалось,всё просто.С самого начала я не пользовался динамической памятью,но тогда прога вылетала,и я ошибочно подумал,что это необходимо,использовать new.Теперь я просто передаю сами объекты из функций.Всё использование динамической памяти было полностью убрано из программы.
Ну подобные моменты я видел, планировал устранить это в процессе капитальной чистки мусора после того, как наметится окончательная схема. Ну если сам разобрался - одной проблемой меньше

Цитата Сообщение от #pragma Посмотреть сообщение
Ещё я добавил оператор GOTO.
Вперёд он тоже прыгает? И приведи пример исходника, который уже работает (попробуй включить GOTO вовнутрь IF'а)
 
Текущее время: 15:20. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru