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

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

20.06.2009, 20:03. Показов 261085. Ответов 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
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
20.12.2009, 14:11
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от RazorQ Посмотреть сообщение
Evg, ты не мог бы дать мне список ключевых слов и саму программку. Я пока поэкспериментирую.
Пишем свой интерпретатор языка BASIC

Скачиваешь, пишешь make. Запускаешь "./basin source.bas"
Только нужно будет libSDL установить

Добавлено через 15 минут
Правда последняя версия из-под cvs у меня что-то не компилится

Code
1
2
In file included from editor.cpp:22:
editor.h:22:26: error: QPlainTextEdit: No such file or directory
Та версия, которая у меня осталась (хз как посмотреть номер ревизии), тоже не компилится. После переустановки линуха может Qt не той версии или ещё чего

Code
1
libgui/src/libgui.so: undefined reference to `QString::indexOf(QRegExp&, int) const'
2
20.12.2009, 14:14

Не по теме:

Выполнил make. Всё собралось как надо, потом выполнил make clean и basin тоже удалился. Т.е. остаются только исходники. Так задумано?

И ошибка в программе: после выполнения тестовой программы source.bas остается окно с квадратиками.

1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
20.12.2009, 14:20
Цитата Сообщение от RazorQ Посмотреть сообщение
Выполнил make. Всё собралось как надо, потом выполнил make clean и basin тоже удалился. Т.е. остаются только исходники. Так задумано?
Ну в общем-то все программы, собирающиеся через make делают так. А что у тебя вызвало сомнение?

Цитата Сообщение от RazorQ Посмотреть сообщение
И ошибка в программе: после выполнения тестовой программы source.bas остается окно с квадратиками
Я так понимаю, что там пробел надо нажать (чтобы окно раньше времени не пропадало). Или ты имеешь в виду какие-то артефакты?
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
20.12.2009, 14:23
Цитата Сообщение от Evg Посмотреть сообщение
Ну в общем-то все программы, собирающиеся через make делают так. А что у тебя вызвало сомнение?
Я имею в виду, что исполняемый файл тоже удаляется. Если программа устанавливается в систему, то тогда все в порядке, но т.к. я её не устанавливаю, то рассчитываю на то, что исполняемый файл останется.

Цитата Сообщение от Evg Посмотреть сообщение
Я так понимаю, что там пробел надо нажать (чтобы окно раньше времени не пропадало). Или ты имеешь в виду какие-то артефакты?
Нажал пробел и окно пропало, но если нажимать на крестик, то оно остается.
1
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
20.12.2009, 14:33
Цитата Сообщение от RazorQ Посмотреть сообщение
Я имею в виду, что исполняемый файл тоже удаляется. Если программа устанавливается в систему, то тогда все в порядке, но т.к. я её не устанавливаю, то рассчитываю на то, что исполняемый файл останется.
А... в "нормальном" случае так действительно не делается. Но #pragma пока всё "под себя" в первую очередь пишет. Хотя для порядка наверное стОит учесть

Цитата Сообщение от RazorQ Посмотреть сообщение
Нажал пробел и окно пропало, но если нажимать на крестик, то оно остается.
Насколько я понимаю, это какие-то особенности libSDL. В общем #pragma придёт - он тебе на все вопросы ответит

Добавлено через 3 минуты
RazorQ, может ты знаешь, чего надо в убунте нажать, чтобы qt установилось?
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
20.12.2009, 14:35
Цитата Сообщение от Evg Посмотреть сообщение
RazorQ, может ты знаешь, чего надо в убунте нажать, чтобы qt установилось?
У тебя есть на компьютере SDK или исходники? Или ты хочешь из репов загрузить?
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
20.12.2009, 20:24  [ТС]
Ой,сколько интересного я пропустил
Ну во-первых,спасибо RazorQ за инициативу с помощью.В принципе я хотел сделать сам,но в-общем я уже сделал какой-то минимальный GUI,выглядит сейчас так:

Окно с ошибками теперь показывается только когда они есть.
Т.е. заготовка есть (хотя по большому счёту там просто слепленные примеры с документации Qt4).Поковырявшись с Qt4,я примерно понял,как с ней работать,мне этого достаточно,так что можно даже полностью переделать GUI (только надо позаботиться,чтобы первоначальный вариант не пропал)
У меня есть несколько альтернатив решения этого вопроса.
1) Можно просто скачать исходники отсюда http://basin.svn.sourceforge.net/viewvc/basin/ там внизу есть ссылка на tar-ball.Это будет всегда последняя версия репозитория.
2) Скачать через svn тут https://sourceforge.net/projects/basin/develop
В этих случаях придётся как-то менятся исходниками потом.
3) По идее я бы мог добавить для RazorQ свою ветку в svn-репозитории,а также права на доступ,на странице проекта эту ветку видно не будет,но знающие смогут скачать,зная адрес.
4) Можно добавить git-репозиторий,а также cvs,и это будет как отдельная ветка.
5) Ну или ещё какой-нибудь вариант.
Насчёт пропадания окошка - там нужно нажать любую клавишу,и окно пропадёт.Просто я не знал,как правильно сделать это в SDL,и добавил в деструктор код по отлавливанию нажатия любой клавиши(по идее костыль):
выглядит так (graphics.cpp)
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
  inline Graphics::~Graphics ()
  {
     bool flag = false;
     if (initialized)
     {// FIXME !
        SDL_Event event;
        cout << "\nPress any key to continue.\n";
        while (true)
        {
           SDL_PollEvent(&event);
           switch (event.type)
           {
              case SDL_KEYDOWN: SDL_Quit();flag = true;
              break;
              default:;
           }
           SDL_Delay(1); // this is because otherwise this code taking 100% CPU
           if (flag) break;
        }
     }
  }
А про удаление проги - это просто надо главный Makefile поменять,я это сделал для тестовой компиляции,чтобы сразу после проверки отправлять правки в хранилище,и чтобы на этот момент ничего лишнего в папках не было.Все файлы,генерирующиеся автоматом,тоже удаляются (moc_* и другие).

P.S. на счёт написанного Evg про функции,надо подумать,потом я ответ напишу.

>Evg, ты не мог бы дать мне список ключевых слов и саму программку. Я пока поэкспериментирую.
Кстати,у нас разные версии интерпретаторов,у Evg-на C,у меня - смесь С и С++ (основной костяк промежуточного представления я взял из версии Evg ).

Добавлено через 10 минут
Мой список синтаксиса есть в файле SYNTAX,который прилагается к проекту,вот на него ссылка - http://basin.svn.sourceforge.n... iew=markup
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
20.12.2009, 23:11
Цитата Сообщение от RazorQ Посмотреть сообщение
У тебя есть на компьютере SDK или исходники? Или ты хочешь из репов загрузить?
Мне всё равно что. Я хочу скомпилять исходники интерпретатора. SDK установленная есть

> У меня есть несколько альтернатив решения этого вопроса.

Для начала можно просто отдать RazorQ'у исходники, а он из нич что-то склепает. Если тебе понравится - включишь в свой репозиторий и будешь думать, как доступ организовывать. Даже если пароль взломают - всего можно будет откатить на нормальную версию, ибо взломанным паролем можно только испортить исходники, но нельзя испоганить хранилище (по идее)
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
20.12.2009, 23:26  [ТС]
Цитата Сообщение от Evg Посмотреть сообщение
Мне всё равно что. Я хочу скомпилять исходники интерпретатора. SDK установленная есть
По идее под Линухом должно всё компилиться,если устанавливал qt4-qmake,а также libqt4-dev,ну и может libqt4-gui.
Под виндой надо читать доку,как скомпилить Qt4 там что-то вроде запускаешь config,указываешь платформу(компилятор) ,и всё должно скомпилиться.

Самое правильное - запусти ./configure скрипт,он должен все зависимости выявить,и что нужно поставь.
0
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
20.12.2009, 23:37
Цитата Сообщение от Evg Посмотреть сообщение
RazorQ, может ты знаешь, чего надо в убунте нажать, чтобы qt установилось?
так
sudo apt-get install libqt4-dev
Добавлено через 5 минут
в каталоге с сорцами должен быть .pro файл(это файл сценарий для qmake).
вводишь:
qmake
make
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
20.12.2009, 23:59  [ТС]
Цитата Сообщение от niXman Посмотреть сообщение
в каталоге с сорцами должен быть .pro файл(это файл сценарий для qmake).
вводишь:
У меня там несколько иначе,.pro файл генерируется автоматом при запуске главного Makefile,у меня там написано:
Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
TARGET    = basin
SUBTARGET = Basin-IDE
CP        = /bin/cp
LS        = /bin/ls
CURRDIR   = `pwd`
OPT       = *.h *.cpp */*.h */*.cpp
LSFLAGS   = -R $(OPT)
SUBDIR    = ./Basin-IDE
MAKE      = /usr/bin/make
QMAKE     = /usr/bin/qmake
QMKFLAGS  = -project
 
$(SUBDIR)/$(TARGET):        
     cd $(SUBDIR) && $(QMAKE) $(QMKFLAGS) $($(LS) $(LSFLAGS)) \
     && $(QMAKE) && $(MAKE) \
     && cd .. && $(CP) ./$(TARGET) $(SUBDIR)/$(TARGET)
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
21.12.2009, 00:07
Цитата Сообщение от #pragma Посмотреть сообщение
По идее под Линухом должно всё компилиться,если устанавливал qt4-qmake,а также libqt4-dev,ну и может libqt4-gui.
Про первое пишет, что нет такого, вторые два установлены (по итогу qmake присутсвует)

Цитата Сообщение от #pragma Посмотреть сообщение
Самое правильное - запусти ./configure скрипт,он должен все зависимости выявить,и что нужно поставь.
Вообще говоря, configure обычно запускают ПЕРЕД сборкой.

Code
1
2
3
4
$ ./configure
checking for ./basin and define PATH_TO_INTERPRETER... configure: error: in `/home/mareev/basin':
configure: error: ./basin program not found.Please view configure.in file,string number 39-42 to fix the problem.
See `config.log' for more details.
Но если сначала запустить make, дождаться, пока он обломается на сборке IDE, а после этого опять запустить configure, то всё будет нормально. Как-то это немного с ног на голову

Code
1
2
3
4
5
6
$ export QTDIR=/opt/qtsdk-2009.04/qt 
$ ./configure
...
checking for main in -lQtCore... yes
checking for main in -lQtGui... yes
...
Однако дальше всё равно облом

[code]g++ -c -pipe -fpermissive -g -Wall -W -D_REENTRANT -DQT_SHARED -DQT_GUI_LIB -DQT_CORE_LIB -I/usr/share/qt4/mkspecs/linux-g++ -I. -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtCore -I/usr/include/qt4/QtGui -I/usr/include/qt4/QtGui -I/usr/include/qt4 -I. -I. -I. -o editor.o editor.cpp
In file included from editor.cpp:22:
editor.h:22:26: error: QPlainTextEdit: No such file or directory[code]

Т.е. система конфигурации не подхватила правильные настройки установленного Qt из SDK (по крайней мере по части инклюдов) и полагается на то, что оно установлено по стандартным путям. Либо переменная QTDIR в нынешних версиях как-то по другому отрабатывается

Сейчас я имею по сути две Qt: одну из SDK, установленную в /opt, другую установленную через "apt-get" по стандартным путям. В /opt/qtsdk-2009.04/qt/include/QtGui этот файл у меня есть, а в /usr/include/qt4/QtGui - нету

Цитата Сообщение от niXman Посмотреть сообщение
так
Это сделал, но чего-то там не хватает

Добавлено через 2 минуты
До генерации qmake.pro у меня дело не дошло
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.12.2009, 00:11  [ТС]
Ой,точно,я перепутал с configure скриптом ,это исправлю,правда как через configure проверить путь и сделать define,если интерпретатор ещё не собран? В-общем,там где-то по мелочи надо поменять,чтобы этот define делался после сборки первой цели.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
21.12.2009, 00:17
Хм... на ubuntu-9.10 всё нормально установилось, а проблема была на ubuntu-8.04.1

Добавлено через 3 минуты
И даже запустилось

В общем на мой взгляд IDE нужно вылизывать как минимум с пользовательской точки зрения (удобство пользования и т.п.). Если ты считаешь, что с Qt для самообразования более-менее разобрался, то имеет смысл отдать кому-то IDE на доработку и доведение до нормального пользовательского уровня.

Короче, думай

Добавлено через 2 минуты
Кстати, ещё бы встроенный отладчик сделать надо. Хотя его надо делать только после того, как окончательно утрясётся с низкоуровневым представлением (если решишь всё-таки поддерживать функции)
1
Эксперт С++
 Аватар для niXman
3211 / 1459 / 74
Регистрация: 09.08.2009
Сообщений: 3,441
Записей в блоге: 2
21.12.2009, 00:20
Цитата Сообщение от Evg Посмотреть сообщение
имеет смысл отдать кому-то IDE на доработку и доведение до нормального пользовательского уровня.
могу помочь консультацией, советом, и на вопросы поотвечать
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.12.2009, 06:32  [ТС]
Да,я не против,если RazorQ хочет сделать - пожалуйста,предоставлю любой из возможных вариантов.Можно и в главной ветке,какая разница,всё равно есть ревизии и т.п.,и кроме того,я уже не планировал добавлять что-то в сделанный GUI,а просто доделать его,там,сделать окошко настройки пути к интерпретатору,чтобы запоминалось в файле .conf,ну и ещё кое-какие мелочи.
А насчёт функций я так представляю - можно добавить переменную-указатель(и) на текущую функцию во всех Statements,при разборе её стек будет подаваться параметром ( у меня уже есть функция проверки отдельных блоков,можно до слова RETURN,или END SUB, или END FUNCTION),туда будут писаться все переменные,а при интерпретации в run-time эти указатели будут использоваться для поиска переменных,и придачи им начальных значений. Придётся,конечно,перелопатить пол-программы,но основной структуры это коснуться не должно. Evg,твоё предложение наверняка более рациональное,но я пока в него не очень въехал,надо покумекать ещё

>могу помочь консультацией, советом, и на вопросы поотвечать
Ну вот,ещё желающий помочь,спасибо,выслушаю советы =),хотя наверное доделывать будет RazorQ

Добавлено через 5 часов 57 минут
Сейчас подумал,наверное,попробую сделать так:
Создаём таблицу функций.Минимальный размер таблицы единица и там будет создаваться главная функция.У неё глобальный стек переменных,массивов. Метки наверное стоит сделать только глобальными,но можно и локальные метки.В структуре Statements будет указатель на текущую функцию,в которой находится инструкция.
Потом по мере создания представления,если встречается слово SUB или FUNCTION,создаётся функция а также её стеки,и указатель на неё передаётся дальше при провязывании в список или ещё как-то.
Возможно,ещё придется где-то хранить указатель на предыдущую функцию,или просто переходить к предыдущей (они в одной таблице) после того как заканчивается построение представления для функции.Имя функции в программе - просто безымянная метка перехода на нужное место в памяти.
При вызове функции считаются начальные значения параметров,присваиваются нужным переменным,и далее интерпретация идёт как обычно,только с той разницей,что переменные берутся из локального стека. Правда придётся организовать какую-то "кучу",или как там это называется,чтобы при рекурсивном вызове все предыдущие значения переменных вызывающей функции запоминались,а после вычислений брались значения с самого "верха". Можно сделать общий для всех функций контейнер только для тех переменных,которые передаются параметрами,и в нём и складировать все их значения при рекурсии... Или не общий,а для каждой функции по спец.контейнеру. Вот.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
21.12.2009, 10:01
По поводу функций. Твой вариант реализации - типичная затычка. Можешь его попробовать из тех же самый соображений - нужно испытать на себе неправильные варианты реализации.

То представление, которое мы имеем сейчас формально не совсем является представлением исходной программы. Statement'ы отражают операторы языка и на самом деле отражают языковые конструкции. Variable'ы точно так же отражают переменные языка. НО. Внутри Variable'ов у нас содержится Value, которое НЕ является конструкцией языка, а является run-time свойством программы. Таким образом сейчас в наше представление замешаны сразу две вещи: отображение исходной программы и отображение run-time состояния программы (которое в нашем случае является значением всех переменных).

Пока мы имели простой язык без функций, технически "два в одном" выглядело просто и без сложных зависимостей компонент одна от другой. Когда появляются функции, то run-time состояние (т.е. значения всех переменных) больше не могут однозначно коррелировать с представлением программы, поскольку для каждой функции отображение программы только одно, а run-time состояний может быть несколько (по количеству активаций процедуры в стеке процедурных вызовов). Поэтому представление нужно выбирать таким образом, чтобы на один экземпляр представления процедуры легко привинчивалось несколько состояний переменных. Т.е. в представлении надо аккуратно отделить отображение языковых конструкций (statement'ы, expression'ы, variable'ы) от run-time сосотояния (Value'ы). Другими словами надо ввести некое понятие "память". И из каждой Variable должна торчать ссылка на Value, а вот сама Value должна храниться в "памяти". При этом к моменту запуска (начало фазы интерпретации) программы, в "памяти" уже расположены значения глобальных переменных. В "памяти" так же создаётся некое подобие стека. При входе в процедуру в этом стеке мы выделяем окно под количество переменных в процедуре и у всех Variable'ов процедуры настраиваем Value на этот стек.

В конечном итоге представление вроде бы как остаётся одно, но в нём меняется механизм соответствия Variable и Value. Главное правильно отделить мух от котлет: представление программы отдельно, run-time состояние отдельно
1
Временно недоступен
 Аватар для #pragma
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
21.12.2009, 11:00  [ТС]
Хорошо.Пока смутно,но понимаю,о чём ты толкуешь. Значит надо начать наводить какой-то порядок,чтобы потом было проще.Тогда я вернусь обратно на 71-ю ревизию и начну делать отладочные печати. Попробую сделать как надо. Дальше уже виднее будет.
Был такой вопрос у меня ещё- может,стоит сделать define-ы для доступа к полям структур представления? коли уж классы не использую,так зачем там пихать кучу ненужных функций.Там есть очень много таких,которые просто возвращают значение,и больше ничего не делают.
0
Evg
Эксперт CАвтор FAQ
 Аватар для Evg
21285 / 8310 / 637
Регистрация: 30.03.2009
Сообщений: 22,671
Записей в блоге: 30
21.12.2009, 13:04
Цитата Сообщение от #pragma Посмотреть сообщение
Хорошо.Пока смутно,но понимаю,о чём ты толкуешь. Значит надо начать наводить какой-то порядок,чтобы потом было проще.Тогда я вернусь обратно на 71-ю ревизию и начну делать отладочные печати. Попробую сделать как надо. Дальше уже виднее будет.
Собственно, переход на новую концепцию как минимум требует времени на осмысливание всего этого добра. А порядок он никогда лишним не будет. Заодно в процессе наведения исходи из новой концепции

Цитата Сообщение от #pragma Посмотреть сообщение
Был такой вопрос у меня ещё- может,стоит сделать define-ы для доступа к полям структур представления? коли уж классы не использую,так зачем там пихать кучу ненужных функций.Там есть очень много таких,которые просто возвращают значение,и больше ничего не делают.
На мой взгляд лучше всё-таки делать классы и методы Set, Get. Всё то, что у меня сделано в виде процедур (типа stmt_NewStmtLET) - это всё так же должно быть методом класса. Попросту говоря, нужно перписать всё это на Си++. Я на Си пишу макросы только для Get'ов, а Set'ы не делаю, т.к. идеологически они все запрятаны внутри процедур типа той же самой stmt_NewStmtLET (т.е. снаружи не должны использоваться вообще). Такая несимметричность зачастую помогает при наведении порядка. Когда ты просто изменил поле структуры и изменил Set и Get, то всё автоматически срастается. А когда нет Set'ов, то надо все записи в поля править ручками - а это всегда означает, что лишний раз отсмотришь все записи в поля "глазками". По природе Set'ов всегда меньше, чем Get'ов и они в "нормальных" случаях сильно локализованы. Поэтому в данном случае я не боюсь потерять лишних 5 минут на замену, зато в очередной раз убедиться, что там всё в порядке (или не в порядке)
1
 Аватар для RazorQ
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
21.12.2009, 15:31
Разработка IDE идет полным ходом. Я раньше писал редактор с возможностью работы с несколькими документами, вот решил его взять за основу для будущей IDE. Немного просмотрел исходники Basin-IDE, которую написал #pragma, и позволю несколько замечаний:
  • Во-первых, мне кажется не лучшим вариантом мешать STL и Qt. В частности, лучше использовать QVector вместо std::vector. Так же не нужно использовать char*. При работе с Qt вообще можно забыть о существовании этого типа (по крайней мере явно создавать переменные этого типа не надо). Гораздо удобней использовать QString. Это заметка для начинающего программиста на Qt.
  • Во-вторых, хотелось бы, чтобы интерпретатор не требовал обязательного присутствия SDL. Т.е. пользователь в праве решать, компилировать программу с поддержкой графики или без неё. Понимаю, задача сложная, но я думаю что результат будет более высокого качества.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
BasicMan
Эксперт
29316 / 5623 / 2384
Регистрация: 17.02.2009
Сообщений: 30,364
Блог
21.12.2009, 15:31

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

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

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

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

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


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

Или воспользуйтесь поиском по форуму:
280
Закрытая тема Создать тему
Новые блоги и статьи
Копировать Windows на новый диск на UEFI
damix 17.10.2026
https:/ / uriesk. wordpress. com/ 2016/ 11/ 01/ move-window-10-to-ssd-on-a-uefi-dualboot-system-with-basic-linux-tools/ TL DR Вставляем диск, а старый подключаем через переходник, грузимся с лайва. . .
ИИ не может найти нужный язык в списке
Supersumestria 05.10.2026
Я ему даю вот такое изображение и прошу найти и подчеркнуть немецкий язык. Возвращает он вот это: https:/ / i. **********/ vqBWLe2. png Нужную строчку в 3й колонке просто выдумал. . Это. . .
Новая последняя моя музыка в SUNO
zorxor 05.10.2026
Здравствуйте, дорогие мои друзья! С большой радостью я хотел бы представить вам свою новую последнею музыку, которую сгенерировала мне по моей просьбе нейросеть SUNO. С уважением, zorxor. Это. . .
Программный домашний кинотеатр
russiannick 27.09.2026
Сподобился на программный домашний кинотеатр. В качестве ЯВУ по традиции выбрал js. В помощники взял Яндекс-Алису. Было создано три зала на разные интересы. исторические и ретро сериал Хичкок. . .
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru