Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.69/1283: Рейтинг темы: голосов - 1283, средняя оценка - 4.69
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926

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

20.06.2009, 20:03. Показов 250982. Ответов 464
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой.

Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz
Если кто-то пользуется Subversion,скачать исходники можно так:
Code
1
svn co https://basin.svn.sourceforge.net/svnroot/basin basin
Эти темы возникли в результате моих вопросов по ходу написания:
Технический приём для формирования согласованных данных
https://www.cyberforum.ru/c-linux/thread46096.html
Вопрос по svn (Subversion)
Создание системы тестирования ПО.
Вопрос про разные реализации бэйсиков
Можно ли выразить порядковый номер элемента массива через индексы?
[C++] Какие флаги указать линкеру для компиляции программы?
Как можно определить переменную в файле configure.in,чтобы её можно было использовать в Makefile?
Странный SIGSEGV, или что зависит от порядка написания интерфейса класса
https://www.cyberforum.ru/c-linux/thread61324.html
Альтернативная версия интерпретатора от Evg на C
Это простая реализация разбора выражений, написанная Evg на C:
Представление выражения в двоичном дереве
*****************
Первое сообщение:
*****************
Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
C++
1
2
r = 2.5
area = pi*r*r
Программа калькулятора выведет:
C++
1
2
2.5
19.635
Получили такой код:
LexicalAnalyzer.h
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
// LexicalAnalyzer.h
#ifndef LEXICALANALYZER_H_INCLUDED
#define LEXICALANALYZER_H_INCLUDED
 
#include <cctype>
#include <string>
#include <map>
#include <iostream>
 
enum Token_value {
    NAME,       NUMBER,      END,
    PLUS = '+', MINUS = '-', MUL = '*', DIV = '/',
    PRINT = ';',ASSIGN = '=',LP = '(',  RP = ')'
};
extern Token_value curr_tok;
extern std::map<std::string,double>table;
extern int no_of_errors;
 
Token_value get_token();
 
double expr(bool);
double term (bool);
double prim (bool);
int error(const std::string&);
 
#endif // LEXICALANALYZER_H_INCLUDED

LexicalAnalyzer.cpp
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
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
// LexicalAnalyzer.cpp
#include "LexicalAnalyzer.h"
 
 
std::map<std::string,double>table;
Token_value curr_tok=PRINT;
 
double expr (bool get)
{
    double left = term(get);
 
    for (;;)
        switch (curr_tok) {
            case PLUS:
                 left += term(true);
            break;
            case MINUS:
                 left-= term(true);
            break;
            default:
                 return left;
        }
}
 
double term (bool get)
{
    double left = prim (get);
 
    for (;;)
        switch (curr_tok) {
            case MUL:
                 left*=prim(true);
            break;
            case DIV:
                 if (double d = prim (true)) {
                     left /= prim (true);
                     break;
                 }
                 return error("Деление на ноль");
            default:
                 return left;
        }
}
 
double number_value;
std::string string_value;
 
double prim (bool get)
{
    if (get) get_token();
    switch (curr_tok){
        case NUMBER:{
            double& v = number_value;
            get_token();
            return v;
        }
        case NAME:{
            double& v = table[string_value];
            if (get_token()==ASSIGN) v = expr(true);
            return v;
        }
        case MINUS:
            return -prim(true);
        case LP:{
            double e = expr(true);
            if (curr_tok!=RP) return error("Ожидалась )");
            get_token();
            return e;
        }
        default:
            return error("Ожидалось первичное выражение");
    }
}
 
Token_value get_token()
{
    char ch = 0;
 
    do {
        if (!std::cin.get(ch)) return curr_tok = END;
    } while (ch!='\n'&&isspace(ch));
 
    switch (ch) {
        case 0:
             return curr_tok = END;
        case ';':case '\n':
             return curr_tok = PRINT;
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
        case '0':case '1':case '2':case '3':case '4' :
        case '5':case '6':case '7':case '8':case '9':case '.':
             std::cin.putback(ch);
             std::cin>>number_value;
             return curr_tok=NUMBER;
        default:
             if (isalpha(ch)) {
                 string_value = ch;
                 while (std::cin.get(ch)&&isalnum(ch)) string_value.push_back(ch);
                 std::cin.putback(ch);
                 return curr_tok = NAME;
             }
             error ("Неправильная лексема");
             return curr_tok = PRINT;
    }
}
int no_of_errors=0;
int error (const std::string& s)
{
    no_of_errors++;
    std::cerr<<"Ошибка: "<<s<<'\n';
    return no_of_errors;
}

main.cpp
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// main.cpp
#include "LexicalAnalyzer.h"
 
 
int main()
{
    table["pi"]=3.1415926535897932385;
    table["e"]=2.7182818284590452354;
    while (std::cin) {
        get_token();
        if (curr_tok==END) break;
        if (curr_tok==PRINT) continue;
        std::cout<<expr(false)<<'\n';
    }
    return no_of_errors;
}

Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
C++
1
a = 3 + 6
,то получаем "a", равное первому элементу в выражении,то есть 3.В чём логическая ошибка данной программы?С этими каскадными вызовами она слегка запутана.Уверен,что кто-то уже делал это задание.

Добавлено через 2 часа 5 минут 30 секунд
Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ) Вот в этом куске кода в функции get_token():
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return Token_value(ch);
Нехватает смены значения curr_tok,что и приводит к ошибочной работе.
C++
1
2
        case '*':case'/':case '+':case '-':case '(':case ')':case '=':
             return curr_tok=Token_value(ch);
Теперь всё пашет,всем спасибо,вопрос можно считать закрытым,но есть вопрос поважнее: В функциях prim и term возвращается int при ошибке,но ведь они имеют тип double,как вообще это работает?Происходит неявное преобразование типа,так?Мне интересно,почему Страуструп прибег к такому способу,это распространённая практика?

Добавлено через 16 минут 19 секунд
И ещё опечатка была
C++
1
2
3
                 if (double d = prim (true)) {
                     left /= d;// было left /= prim (true)
                     break;
31
Лучшие ответы (1)
IT_Exp
Эксперт
34794 / 4073 / 2104
Регистрация: 17.06.2006
Сообщений: 32,602
Блог
20.06.2009, 20:03
Ответы с готовыми решениями:

Пишем свой интерпретатор языка BASIC
Добрый день. Я смотрю, тут на форуме была тема коллективного написания интерпретатора BASIC на языке С++. Я очень извиняюсь, но я...

Пишем свой strlen
Всем привет, вырвал часть задание из общего задание по написанию своего string. На данном этапе столкнулся с проблемой (хотел написать...

Пишем свой чекер
Я хочу написать свой чекер, но не знаю с чего начать? Кто знает основные принцип работы чекеров прошу объясните.

464
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.12.2009, 16:00
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от RazorQ Посмотреть сообщение
[*]Во-вторых, хотелось бы, чтобы интерпретатор не требовал обязательного присутствия SDL. Т.е. пользователь в праве решать, компилировать программу с поддержкой графики или без неё. Понимаю, задача сложная, но я думаю что результат будет более высокого качества.[/LIST]
В той или иной степени это уже обсуждалось. Этот пункт из тех, что можно отлодить "на потом", т.к. на остальное он не должен влиять. Так же я на примере показывал, как правильно писать код, чтобы на низкий уровень можно было подкладывать любую библиотеку, а не только SDL

Насколько я понимаю, SDL сейчас не конфликтует с IDE?
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
21.12.2009, 16:04
Цитата Сообщение от Evg Посмотреть сообщение
Насколько я понимаю, SDL сейчас не конфликтует с IDE?
Нет. Все в порядке.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.12.2009, 16:06
Цитата Сообщение от RazorQ Посмотреть сообщение
Нет. Все в порядке.
В общем, полезно в репозиторий положить текстовый файл, куда сваливать идеи и полезные мысли, чтобы они не потерялись. Либо рисовать FIXME, но когда их много, что в отдельном файле проще
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
21.12.2009, 21:57
Вот самый черновой вариант программы. Назвал так же, Basin-IDE, т.к. это вольется в один проект. Для компиляции нужна Qt не ниже 4.5. Вообще это не жесткое ограничение, просто в этой версии появилась возможность добавлять кнопку закрытия на вкладку. Для работы программы, нужно наличие интерпретатора в том же каталоге. Насчет имен файлов: желательно чтобы путь к файлу не содержал пробелов и кириллицы (вообще это только в теории, сам не пробовал).
Вложения
Тип файла: zip basin-ide.zip (105.3 Кб, 19 просмотров)
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
21.12.2009, 22:36
Я, конечно, не прочитав документации решил написать самую элементарную программу на basic
PureBasic
1
2
3
PRINT "input your name: "
INPUT nam$
PRINT nam$
Интересно то, что basin аварийно завершился
Code
1
2
3
4
$ ./basin test.bas 
terminate called after throwing an instance of 'std::out_of_range'
  what():  basic_string::at
Аварийный останов
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.12.2009, 22:47
RazorQ, неплохо, только отработку ошибок интерпретатора не сделал

Ну и чисто по мелочи замечания:
- логически "undo" и "redo" должны находиться рядом с "cut", "copy", "paste"
- у меня язык в системе выставлен английский, а все надписи по русски. Я так понимаю, что для многоязыковости надо отдельные локализации писать?

Добавлено через 2 минуты
Попробуй код без input'а, потому как подозреваю, что после реорганизации внутреннего представления input попросту слетел. Ну и синтаксис смотри по примеру или в каталоге tests, т.к. #pragma на строгость синтаксиса языка не вылизывал, потому как приоритетным было построение промежуточного представления.

#pragma, соглашайся забрать этот IDE Он мне понравился
2
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
21.12.2009, 22:48
Цитата Сообщение от Evg Посмотреть сообщение
- логически "undo" и "redo" должны находиться рядом с "cut", "copy", "paste"
Это без вопросов

Цитата Сообщение от Evg Посмотреть сообщение
- у меня язык в системе выставлен английский, а все надписи по русски. Я так понимаю, что для многоязыковости надо отдельные локализации писать?
Да, надо писать файлы-переводчики. Это не сложно, но руки не доходят. У меня есть в планах сделать поддержку как минимум английского и русского. Но сейчас в коде жестко закодирован русский язык, поэтому английский ты увидишь только в сообщениях об ошибках.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
21.12.2009, 22:51
Цитата Сообщение от RazorQ Посмотреть сообщение
Да, надо писать файлы-переводчики. Это не сложно, но руки не доходят. У меня есть в планах сделать поддержку как минимум английского и русского. Но сейчас в коде жестко закодирован русский язык, поэтому английский ты увидишь только в сообщениях об ошибках.
Это не к спеху, так, спросил. Я-то в этом не разбираюсь

Но отработка ошибок и позиционирование курсора на нужной строке - это делать по любому
1
21.12.2009, 22:57

Не по теме:

Вчера было полгода проекту! Поздравляю вас Evg и #pragma!

1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.12.2009, 23:33  [ТС]
Выглядит неплохо - простенько,аккуратно и со вкусом. Мне понравилось. Я так быстро не умею
Кое-какие ньюансы(мелочи): если можно,добавь нужные регекспы для отображения текста более красочно,но,в принципе,если неохота,я доделаю.
Комментарии наверное лучше чтобы становились серыми и с наклоном,как в С++,так лучше воспринимается основной текст,когда кореллирует с другим стилем.
Ещё такую мелочь заметил:когда открывается окно программы,по умолчанию открывается поле нового файла,что,в принципе,верно,но если пользоваетль решает сразу открыть готовый исходник,то его лучше загружать в это же поле,так как оно остаётся висеть вкладкой просто так.
Осталось только доделать эмулятор терминала,чтобы похож был на xterm и cmd (просто для подражания )
Ещё надо будет как-то сделать обработку ошибок интерфейсом,чтобы строку выделял цветом,или что-то навроде того,как я делал. В принципе,можно опираться на вывод интерпретатора,при ошибках он выведет строку,которая содержит слова "line: error:" и между ними должен быть номер строки. Там,правда,могут быть ньюансы с длинными путями,я не знаю,что будет,если длина строки окажется больше 255 символов.
А так вообще всё классно! Иконки лучше ставить из твоего варианта,они менее агрессивны,и более приятны глазу,только нужно найти подходящие для run и interpret.

Добавлено через 14 минут
Нашел,где была ошибка,отправлю правку позже:
кусок кода из syntax.cpp
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
  static expr_Node_t *syntax_IdentRValueInput ()
  {
     s_count pos = source.tellg();
     string name = ::parser_CurTokenStr;
     size3 i = FindNameOverVector (name,defined_vars);
     size3 j = FindNameOverVector (name,defined_arrays);
     if (i < 0 && j < 0)
     {
        if (parser_GetToken() == TOKEN_LEFT_PARENTH)
           error(UNDEFINED_ARRAY,name);
        source.seekg(pos);
        Types t;
        switch (name.at(name.size()-1)) // name вместо ::parser_CurTokenStr
        {
           case '%': t = INT;   break;
           case '&': t = LINT;  break;
           case '!': t = FLOAT; break;
           case '#': t = DOUBLE;break;
           case '$': t = STRING;break;
           default : t = INT;   break;
        }
        Value zero("0",t);
        Variable *var = memalloc(var,name); // name вместо ::parser_CurTokenStr
        defined_vars.push_back(var);
        defined_vars.back()->SetValue(zero);
        return expr_NewVariable(&name,t); // name вместо ::parser_CurTokenStr
     }
// Ну и надо ещё будет проглядеть,там могут быть ещё недочеты подобного рода


Добавлено через 12 минут
Ещё есть такая идея - сделать(опционально) автоотступ и показывать вертикалную линию после 80 знаков на строку для того,чтобы в результате код мог с удобством просматриваться в консоли,не требуя перемотки вправо .
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.12.2009, 09:55
Пока не забыл. В IDE надо сделать поиск и замену. При чём человеческие (вверх, вниз, case sensitive, whole word, regular expression, спрашивать или нет). При поиске уметь выделять все найденные подстроки. Так же "перейти на номер строки" и возможность включения нумерации строк (как в варианте #pragm'ы)
3
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
22.12.2009, 13:35
Цитата Сообщение от #pragma Посмотреть сообщение
Я так быстро не умею
Я тоже У меня был недоделанный блокнот, вот я и взял его за основу.
Цитата Сообщение от #pragma Посмотреть сообщение
Кое-какие ньюансы(мелочи): если можно,добавь нужные регекспы для отображения текста более красочно,но,в принципе,если неохота,я доделаю.
Сделаю. Сейчас в подсветки синтаксиса только одна проблема: если ключевое слово находится в комментариях, то оно выделится как ключевое, а этого не должно быть. Возможно, нужно задать правильный regexp.
Цитата Сообщение от #pragma Посмотреть сообщение
Ещё есть такая идея - сделать(опционально) автоотступ и показывать вертикалную линию после 80 знаков на строку для того,чтобы в результате код мог с удобством просматриваться в консоли,не требуя перемотки вправо .
Хорошо. Хотя честно, для меня это будет сложнее, т.к. с графикой в Qt не работал, но это дело времени
Цитата Сообщение от #pragma Посмотреть сообщение
Ещё такую мелочь заметил:когда открывается окно программы,по умолчанию открывается поле нового файла,что,в принципе,верно,но если пользоваетль решает сразу открыть готовый исходник,то его лучше загружать в это же поле,так как оно остаётся висеть вкладкой просто так.
Да, сам заметил. Подправлю.
2
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.12.2009, 16:38
Цитата Сообщение от Evg Посмотреть сообщение
Пока не забыл. В IDE надо сделать поиск и замену.
qscintilla ?
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.12.2009, 20:02
Цитата Сообщение от RazorQ Посмотреть сообщение
Хотя честно, для меня это будет сложнее, т.к. с графикой в Qt не работал, но это дело времени
#pragma тоже интерпретаторов не писал

> qscintilla ?

Ой.. это я уже не знаю. Как говорится, пользователю нужен поиск и замена, а как он сдела технически - его это не колышет
2
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.12.2009, 20:13
Я к тому, что это ооочень навороченный виджет, и создан именно для редакторов. там есть все что только может понадобиться. он так же кроссплатформенный как и Qt.
т.е. писать велосипед с нуля, при условии что получится все равно хуже, смысла нет
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.12.2009, 20:16
Цитата Сообщение от niXman Посмотреть сообщение
Я к тому, что это ооочень навороченный виджет, и создан именно для редакторов. там есть все что только может понадобиться. он так же кроссплатформенный как и Qt.
т.е. писать велосипед с нуля, при условии что получится все равно хуже, смысла нет
А смотря какую цель перед собой ставить: написать редактор или научиться программировать под Qt
2
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
22.12.2009, 20:18
поверь мне, помимо самого виджета редактора, будем ооочень много возможностей поучиться.
я просто предложил, вам решать.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
22.12.2009, 21:55
Цитата Сообщение от niXman Посмотреть сообщение
поверь мне, помимо самого виджета редактора, будем ооочень много возможностей поучиться.
я просто предложил, вам решать.
А я чо? Я в этом вообще ничего не понимаю
2
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
23.12.2009, 09:47  [ТС]
Evg, я тут пытаюсь осмыслить всё вышесказанное с точки зрения технической реализации. Я дёрнулся наводить порядок,но нужно сначала представить,хотя бы примерно,как будет выглядеть программа дальше,и что конкретно в ней изменится. Про память я понял,но это касается больше стадии интерпретации run-time.

Мне непонятен такой момент. Вот в исходнике встречается слово SUB,после чего создаётся процедура со своими свойствами.Внутри исходника процедуры встречается некая переменная с именем.Понятно,что переменная содержит указатель на свой стек(если создана),как ты пишешь,но как мы узнаем по имени,в каком стеке(странице) искать переменную?Создавать ли новую или это глобальная переменная? А может,это ошибка пользователя и переменная уже есть,и она другого типа,ну и так далее. До слов END SUB все новые переменные нужно писать в определённую страницу,но как об этом узнает следующая функция,создающая представление программы? Просто ты написал,что мой вариант не верен,и теперь я немного сбит с толку,так как не представляю,как это будет выглядеть технически.В run-time вроде понятно,там уже будут не имена переменных,а объекты,и в них уже ссылки на нужные страницы,а вот при создании представления немного неясно.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 30
23.12.2009, 11:00
Цитата Сообщение от #pragma Посмотреть сообщение
Evg, я тут пытаюсь осмыслить всё вышесказанное с точки зрения технической реализации. Я дёрнулся наводить порядок,но нужно сначала представить,хотя бы примерно,как будет выглядеть программа дальше,и что конкретно в ней изменится. Про память я понял,но это касается больше стадии интерпретации run-time.
В теории промежуточное представление остаётся как есть, только вместо одной цепочки statement'ов мы имеем их несколько (на каждую процедуру). И меняется метод хранения value в переменных

Цитата Сообщение от #pragma Посмотреть сообщение
Мне непонятен такой момент. Вот в исходнике встречается слово SUB,после чего создаётся процедура со своими свойствами.Внутри исходника процедуры встречается некая переменная с именем.Понятно,что переменная содержит указатель на свой стек(если создана),как ты пишешь,но как мы узнаем по имени,в каком стеке(странице) искать переменную?Создавать ли новую или это глобальная переменная? А может,это ошибка пользователя и переменная уже есть,и она другого типа,ну и так далее. До слов END SUB все новые переменные нужно писать в определённую страницу,но как об этом узнает следующая функция,создающая представление программы? Просто ты написал,что мой вариант не верен,и теперь я немного сбит с толку,так как не представляю,как это будет выглядеть технически.В run-time вроде понятно,там уже будут не имена переменных,а объекты,и в них уже ссылки на нужные страницы,а вот при создании представления немного неясно.
В момент построения представления ты должен строить дополнительные списки переменных, относящихся к текущему контексту. Список содержит соотвестве имени и указателя на экземпляр класса Variable. Т.е. пока ты находишься ВНЕ процедур ты работаешь со списком, в котором у тебя находятся все глобальные переменные. Когда появляется новая переменная, то ты проверяешь в списке, есть ли уже такая переменная или нет. Если есть, то используешь её, если нет, заводишь новую. Когда ты зашёл в SUB, то заводишь дополнительный список (который удаляешь по выходу из SUB). Заметь, я говорю НЕ о списке переменных, а о списке соответствия имени и переменной. И когда встретил переменную, то проверяешь сначала локальный список, а потом глобальный. Если бы мы делали SUB'ы внутри SUB'ов, то пришлось бы заводить стек из списков, но такого в бэйсике вроде нет. Ещё надо уточнить, как там с локалами. Т.е. если первый раз переменная встретилась внутри SUB'а, то она является локальной или нет? Или все локальные переменные должны явно объявляться, а если встретилась необъявленная переменная, то она глобальная? В общем надо выяснить, как правильно делается в Q-бэйсике.

В итоге ты получаешь представление, которое по большому счёту ничем не отличается от текущего. Но у каждой процедуры надо иметь список локальных переменных. Когда ты в момент исполнения заходишь в процедуру, то проходишь по этому списку и все значения переменных копируешь "куда-то в строноу", после чего инициализируешь все переменные нулями (если в бэйсике для локалов это тоже должно выполняться). Это "куда-то" должно иметь стековую структуру. Таким образом если ты зашёл в процедуру рекурсивно, то этим действием ты спас старые значения переменных. Когда выполняешь возврат из процедуры, то из этого "куда-то" переписываешь значения обратно в переменные. Этим ты по сути моделируешь run-time стэк

Точку сохранения-восстановления можно изменить. Т.е. спасать не во время входа в процедуру, а в тот момент, когда внутри процедуры делается CALL, а спасать, соотвественно, когда ты вернёшься из этого CALL'а. Как получается технически проще, так и нужно делать.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
23.12.2009, 11:00
Помогаю со студенческими работами здесь

пишем свой троян с нуля
Всем привет)))соглашусь, что изобретаю велосипед, но хочется сделать все своими ручками не прибегая к open source и т.п. для повышения...

Пишем свой класс, спецификатор доступа protected
Всем привет! Из книги Р. Лафоре относительно спецификатора доступа protected: Далее пишется следующее: Возникает вопросы:...

Интерпретатор небольшого языка программирования на С++
Здравствуйте, уважаемые форумчане! Я тут где-то год назад прочитал тему Evg и #pragma о создании интерпретатора, меня эта тема очень...

Не удается откомпилировать интерпретатор М-языка
Задача: взять интерпретатор М-языка на сайте http://cmcmsu.no-ip.info/2course/model.lang.parser.sample.htm и переработать его, добавив в...

Интерпретатор музыки стандарта BASIC PLAY на С++
У кого нибудь есть функция или класс, который сможет воспроизводить в С++ напрямую музыкальные строки, записанные в стандарте оператора...


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

Или воспользуйтесь поиском по форуму:
300
Закрытая тема Создать тему
Новые блоги и статьи
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
Фото: Daniel Greenwood
kumehtar 13.11.2025
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru