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

Пишем свой интерпретатор языка 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
18689 / 6654 / 468
Регистрация: 30.03.2009
Сообщений: 18,619
Записей в блоге: 29
17.08.2009, 17:52
Цитата Сообщение от #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'а)
1
 
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2018, vBulletin Solutions, Inc.