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

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

20.06.2009, 20:03. Показов 253265. Ответов 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
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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
21281 / 8305 / 637
Регистрация: 30.03.2009
Сообщений: 22,660
Записей в блоге: 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
Закрытая тема Создать тему
Новые блоги и статьи
сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
WordPad для Windows 11
Jel 10.01.2026
WordPad для Windows 11 — это приложение, которое восстанавливает классический текстовый редактор WordPad в операционной системе Windows 11. После того как Microsoft исключила WordPad из. . .
Classic Notepad for Windows 11
Jel 10.01.2026
Old Classic Notepad for Windows 11 Приложение для Windows 11, позволяющее пользователям вернуть классическую версию текстового редактора «Блокнот» из Windows 10. Программа предоставляет более. . .
Почему дизайн решает?
Neotwalker 09.01.2026
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
Модель микоризы: классовый агентный подход 3
anaschu 06.01.2026
aa0a7f55b50dd51c5ec569d2d10c54f6/ O1rJuneU_ls https:/ / vkvideo. ru/ video-115721503_456239114
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR
ФедосеевПавел 06.01.2026
Owen Logic: О недопустимости использования связки «аналоговый ПИД» + RegKZR ВВЕДЕНИЕ Введу сокращения: аналоговый ПИД — ПИД регулятор с управляющим выходом в виде числа в диапазоне от 0% до. . .
Модель микоризы: классовый агентный подход 2
anaschu 06.01.2026
репозиторий https:/ / github. com/ shumilovas/ fungi ветка по-частям. коммит Create переделка под биомассу. txt вход sc, но sm считается внутри мицелия. кстати, обьем тоже должен там считаться. . . .
Расчёт токов в цепи постоянного тока
igorrr37 05.01.2026
/ * Дана цепь постоянного тока с сопротивлениями и источниками (напряжения, ЭДС и тока). Найти токи и напряжения во всех элементах. Программа составляет систему уравнений по 1 и 2 законам Кирхгофа и. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru