|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Пишем свой интерпретатор языка BASIC20.06.2009, 20:03. Показов 253358. Ответов 464
Метки нет (Все метки)
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой. Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz Если кто-то пользуется Subversion,скачать исходники можно так:
Технический приём для формирования согласованных данных 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: Представление выражения в двоичном дереве ***************** Первое сообщение: ***************** Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
LexicalAnalyzer.h
LexicalAnalyzer.cpp
main.cpp
Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
Добавлено через 2 часа 5 минут 30 секунд Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ) Вот в этом куске кода в функции get_token():
Добавлено через 16 минут 19 секунд И ещё опечатка была
31
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
| 20.06.2009, 20:03 | |
|
Ответы с готовыми решениями:
464
Пишем свой интерпретатор языка BASIC
Пишем свой чекер |
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||
| 17.11.2009, 10:45 [ТС] | ||
|
Непонятно мне,как запускать программу из другой программы.Что,есть какая-то функция для этого (стандартная)? system как-то не очень хвалят,а как ещё можно вызвать стороннюю программу? А сейчас у меня устроено так,что если прописана опция --gui в консоли,то в main всё просто идёт по другой ветке,и запускается конструктор окна,а уже оттуда вызываются функции проверки синтаксиса и интерпретации,которые и передаются в виде указателей экземпляру окна.А сама реализация gui классов лежит в разделяемой библиотеке. Добавлено через 12 минут Я подумал: "зачем создавать два приложения,когда можно обойтись одним?" и вариант с опцией командной строки показался мне наиболее простым.Потому и сделал так.
0
|
||
|
|
|
| 17.11.2009, 12:04 | |
|
> Я подумал: "зачем создавать два приложения,когда можно обойтись одним?" и вариант с опцией командной строки показался мне наиболее простым.Потому и сделал так.
Можно и одним. Но у людей принято делать так, как я тебе пояснил. Если человеку не нужна IDE, он ставит просто компилятор (интерпретатор). Когда имеется две программы, то компилятор разрабатывает одна команда разработчиков, а IDE - другая, т.е. технически такой вариант удобнее. По большому счёту разбитие большого проекта на несколько отдельных программ - это то же самое, что разбивать одну программу на несколько файлов. Только в качестве интерфейса служит запуск с разными параметрами и обработка текстовой выдачи > Я просто подумал,что можно разбить интерпретацию файла на фрагменты: 1.проверка синтаксиса 2.собственно запуск. 3.а также общая кнопочка(проверка +запуск). А если функции нужно вызывать по желанию (они же в программе basin) то IDE должна как-то знать о них.Но в принципе это не критично и можно сделать только одну кнопку. Решается просто. В интерпретатор заводишь опцию типа --syntax-only и при включенной опции после завершения разбора синтаксиса выходишь. В IDE при нажатии на кнопку "Компилирровать, но не запускать" запускаешь интерпретатор с дополнительной опцией --syntax-only. Пункты 2 и 3 для интерпретатора разделить нельзя, это есть только в компиляторах, поскольку на стадии компиляции формируется исполняемый файл, а на стадии запуска он исполняется, а у интерпретатора нет выходного файла. ПОэтому в твоём случае остайтся только два варианта: "Проверить синтаксис" и "Исполнить" > Непонятно мне,как запускать программу из другой программы.Что,есть какая-то функция для этого (стандартная)? system как-то не очень хвалят,а как ещё можно вызвать стороннюю программу? Если не забуду, на работе пример покажу готовый. А так ищи в сторону fork, exec - это строго для запуска, pipe, dup2 - это чтобы перезватывать вывод программы Как вариант ты можешь оставить то, что сделано у тебя сейчас, но это я бы крайне не рекомендовал, т.к. закопаешься довольно глубоко. Либо опять стОит попробовать по тем же причинам: чтобы понять, что так делать не стОит.
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 17.11.2009, 13:01 [ТС] | |
|
То есть получается,что идея создания динамической разделяемой библиотеки отпадает за недадобностью.Ведь у нас будет две отдельные программы,и одна запускает другую.В этом варианте библиотека .so (или .dll) не нужна.
0
|
|
|
|
|
| 17.11.2009, 15:00 | |
|
Идея динамесечкой библиотеки с точки зрения IDE - отпадает. Но в самом интерпретаторе это сделать можно. Но для порядку надо найти ещё одну графическую библиотеку помимо SDL и уже экспериментировать с двумя собственными динамическими библиотеками, работающие по одному интерфейсу
По поводу запуска программы - я уже выкладывал исходник Трубопровод на линукс Грубо говоря, можно его запустить как "./a.out ls -l" и в этом случае весь ввод-вывод запускаемой программы (в нашем случае ls) пройдёт через процедуру listener
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||||||
| 26.11.2009, 02:21 [ТС] | ||||||
|
Я вспомнил,что есть класс QProcess,и попробовал сделать с помощью него,(раз уж Qt использую).Наверное,твой пример с pipes намного более транспортабелен между unix-системами?
Вот как я делаю
Прочитал,что вроде как xterm есть на большинстве unix-систем,но точно не уверен.Ведь xterm может быть в другой папке.Просто немного сложновато в твоём примере,хотя общий смысл я понял,но там есть всякие define-ы специфические,немного усложняет понимание. Да,я всё таки вернул флаги компиляции в интерпретаторе,это стало возможным благодаря тому,что gui теперь-отдельное приложение.Makefile у меня один,просто теперь он автоматом запускает компиляцию второй программы,заходит в папку,и копирует туда скомпиленный интерпретатор,чтобы лежал рядом с gui программой.
0
|
||||||
|
|
|||
| 26.11.2009, 10:18 | |||
|
1
|
|||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 27.11.2009, 01:56 [ТС] | |
|
>Обычно путь до терминала выносят в настройки IDE. Если программа предварительно работает через configure, то по результату работы выставляется дефолтное значение пути до терминала.
Ты про тот configure скрипт,который запускается до сборки проекта? Сделать что-то навроде test -e /usr/bin/xterm? Ну на на винде,я так понимаю,будет использоваться стандартная переменная %ComSpec% ? Или имелось в виду создание некой отдельной функции configure,или что-то ещё?
0
|
|
|
|
|||
| 27.11.2009, 11:34 | |||
|
1
|
|||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||||||
| 28.11.2009, 02:34 [ТС] | ||||||
|
Я сейчас читаю доку по autoconf,пока нашёл это http://www.gnu.org/software/li... c-Programs и это http://www.gnu.org/software/li... r-Programs. Мне нужен какой-то макрос,навроде AC_PROG_XTERM,но его там нет,и веть нужно ещё,чтобы в зависимости от проверки на существование писался define в config.h или в похожий файл.
Т.е. например,так
Я помню,ты писал,что не работал с autotools,так что это,скорее вопрос риторический.Придётся наверное отдать всё во власть пользователя и как-то создавать .ini или что-то в этом духе.
0
|
||||||
|
|
|
| 28.11.2009, 10:56 | |
|
Ну до реальных пользователей пока далеко, так что с autoconf'ом точно можно не спешить и отложить на потому. Потому как в процессе отладки ты все настройки сам можешь сделать.
Просто "пользователь" в данном случае можно рассматривать в двух контекстах: - тот, кто программой будет пользоваться. Все возможные фичи в интерфейсе (опции командной строки в интерпретаторе и опции в gui и всевозможные кнопочки) надо закладывать сразу и всегда об этом помнить - тот, кто программу будет собирать из исходников. Грубо говоря, в этом случае все настройки технически решаются через файл config.h. Как вариант ты его создаёшь руками и тестируешь в разной комбинации опций конфигурации системы, а уже под конец пишешь configure, который в автоматическом режиме создаст файл config.h Получается так, что по второму пункту проблема локализована, и технически решается в узком месте, где вообще не нужно затрагивать исходники программы. А первая проблема - это то, что по большому счёту сильно влияет на работу всего комплекса и удобство пользования. И в сторонке не всегда это получается сделать, поэтому надо как можно раньше в процессе программирования/проектирования закладываться на эти свойства
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
| 30.11.2009, 08:06 [ТС] | |||||||||||
|
Подглядел,как делают define-ы с помощью configure: написал в configure.in
configure.in
Там я временно сделал вариант с ошибкой,так как не знаю,где лежит xterm на других системах по умолчанию. А программу всё-таки вызываю непосредственно,так чтобы она была под контролем IDE,а не внешнего терминала.Поэтому,скорее всего,придётся делать окошко для варианта успешного вывода (печать результатов программы),например по некому сигналу открывается окошко с текстовым полем.Меня только смущает то,что IDE по сути,толжна быть только обёрткой для программы,а тут получится вмешательство в стандартный вывод.Обычно же IDE вызывает внешнюю программу (cmd или xterm). Вызываю интерпретатор так: mainwindow.cpp
И в errorsList печатаются сообщения красным цветом.
0
|
|||||||||||
|
|
||
| 30.11.2009, 08:43 | ||
|
1
|
||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 30.11.2009, 10:19 [ТС] | |
|
Просто я не представляю,как потом считать данные из потоков ошибок и вывода,ведь если я буду запускать консоль как дочерний процесс IDE,то считываться будут только данные,которые пишет этот процесс,а не запускаемый в консоли? Или в Unix-системах не существует разграничений для процессов,и все данные идут в один общий поток? Вот это мне не понятно. Постараюсь уточнить свой вопрос: допустим,есть файл - поток вывода stdout,запускается программа-терминал,у неё есть свой вывод (свои ошибки или ещё что-то),а программа,запускаемая внутри терминала имеет свой вывод(в данном случае это интерпретатор,и выводится результат программы на QBASIC). Пишутся ли все данные в один поток вывода? С этим и было связано моё затруднение,ведь если я создаю процесс для консоли,и передаю ей в качестве параметра имя программы,то как потом считать вывод этой программы?
0
|
|
|
|
||
| 30.11.2009, 10:34 | ||
|
1
|
||
|
|
||
| 30.11.2009, 17:34 | ||
|
В общем, знатоки утверждают, что при запуске черз нормальный терминал подобная операция перехвата ввода-вывода будет слишком геморройной. Не говоря уж о том, что кроссплатформенно сделать в принципе не получится, а потому их предложение так же сводилось к тому, что проще будет использовать самодельную эмуляцию терминала. Причём говорили, что в Qt вроде бы есть какая-то стандартная компонентя для консоли
1
|
||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||||||
| 20.12.2009, 02:45 [ТС] | ||||||
|
Пытаюсь сделать конструкцию
А как быть с самой интерпретацией run-time? По идее нужно тоже передавать нужный стек параметром,только вот как метка вызова функции будет знать,какой стек нужно выбрать? Придётся делать общую переменную для всех stmt's,содержащую указатель на текущий стек? Или только для меток делать указатель на нужную функцию в списке..
0
|
||||||
|
|
||||||||||||||||
| 20.12.2009, 11:35 | ||||||||||||||||
|
Как интерпретировать процедуры через промежуточное представление - я вот так с ходу и не скажу. Проблема именно в рекурсивных вызовах. Видимо надо уже над переменными строить надствройку в виде некоторой страницы (которая по сути пул памяти, хранилище). Т.е. при создании переменной ты ещё и указываешь и страницу, в которой эта переменная живёт. Страница для глобальных переменных будет одна. Для локалов и формальных параметров каждой процедуры заводится своя страница и все переменные ссылаются на эту страницу. При наличии рекурсивного вызова процедуры всю страницу можно куда-нибудь в сторону скопировать. Таким образом с точки зрения нашего представления вроде бы остаётся всё как есть: внутреннее представление каждой переменной всегда находится в одном и том же месте памяти интерпретатора. Но это - некий технический бубен, потому как наше представление было рассчитано на случай без функций.
Как вариант можно строить наше же представление. С незначительными отличиями: - вместо одной цепочки операторов будет несколько цепочек (на каждую функцию отдельная цепочка) - каким-то образом нужно отличать глобальные переменные от локальной переменной функции. Способов миллион от страниц, про которые говорил выше, до списков переменных, привязанных к каждой процедуре Оба отличия с технической точки зрения НЕ являются сложными и НЕ являются бубнами/подпорками/костылями. Получится так называемое представление высокого уровня, которое попросту отражает исходник программы в удобный вид для обработки в интерпретаторе (ну и плюс отсеиваем пользовательские ошибки). Представление верхнего уровня будет использоваться только для хранения "образа программы". Далее нужно построить ещё одно промежуточное представление, которое удобно для интерпретирования. Это будет представление низкого уровня, которое внутри себя будет читывать динамические стеки и прочую лабуду, возникающую при исполнении. Компиляторы, как правило строятся на двух промежуточных представлениях с тем же назначением: высокоуровневое представление, чтобы иметь образ программы, и низкоуровневое, чтобы с него генерировать код. Высокоуровневое представление оперирует понятиями "объект" ("переменная"). Низкоуровневое - понятиями "память" и "регистр". Для исходника
Адрес глобальных переменных в run-time всегда будет одним и тем же. Адреса локальных переменных будут плавать (в зависимости от глубины стека). В этом случае понадобятся страницы (фрэймы) памяти. Все глобальные переменные будут распределены в одну страницу для глобалов. При входе (на исполнении) в каждую процедуру будет заводиться страница для локалов процедуры и туда помещаться все локалы. Адрес локальной переменной будет вычисляться на основании адреса текущей страницы локалов. Да, всё это на первый взгляд слишком непонятно. Непонятно так же, как это будет выглядеть технически. Но для начала надо хотя бы в общем виде понять концепцию двух представлений. Причём пока писал, уже понял, что низкоуровневое представление можно значительно сократить. А так же построить его на базе высокоуровневого, т.к. на первый взгляд раличие будет только при работе с переменными. Но это мысли "на потом", для начала понять концепцию. Прежде, чем это делать, тебе всё-таки нужно навести порядок во внутренностях интерпретатора, потому что закопаешься. И ещё сделать нормальную печать промежуточного представления, чтоб "глазами" можно было увидеть всё, что в нём есть и как оно друг с другом связано (как это смотреть в моей версии, я вроде бы уже писал). В gcc эти печати даже не стали прятать от пользователя (хотя во всех коммерческих компиляторах в пользовательских версиях) она отключена. Запусти "gcc t.c -da" и ты увидишь файлы "gcc t.c.*", в которых расписано представление после каждого прохода или оптимизации. Без подобной НОРМАЛЬНОЙ печати компилятор реализовать просто невозможно
1
|
||||||||||||||||
|
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
|
|
| 20.12.2009, 12:06 | |
|
Evg, #pragma, я тут прочитал, что вы хотели бы иметь графический интерфейс к программе. Могу помочь. Предлагайте свои идеи, я попробую реализовать. От вас мне будет нужна только программа в скомпилированном виде. И некоторые нюансы можно будет обсудить потом.
1
|
|
|
|
||
| 20.12.2009, 13:23 | ||
|
Как вариант можешь делать сам, но параллельно "заказать" работу. Потому как одна программа низкого уровня (интерпретатор) и несколько программ высокого уровня (графическая оболочка) - это совершенно нормальное явление. А заодно и в чужом коде посмотришь, как делается что-то. Ещё прочувствуешь, чем принципиально отличается работа в команде от работы в одиночку: когда есть много мыслей в голове это одно, а когда эти мысли надо объяснить людям - совсем другое.
1
|
||
|
591 / 357 / 16
Регистрация: 06.02.2009
Сообщений: 1,386
|
|
| 20.12.2009, 13:41 | |
|
Значит ждем решения #pragma.
Добавлено через 1 минуту Evg, ты не мог бы дать мне список ключевых слов и саму программку. Я пока поэкспериментирую.
1
|
|
| 20.12.2009, 13:41 | |
|
Помогаю со студенческими работами здесь
260
пишем свой троян с нуля Пишем свой класс, спецификатор доступа protected Интерпретатор небольшого языка программирования на С++ Не удается откомпилировать интерпретатор М-языка
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Первый деплой
lagorue 16.01.2026
Не спеша развернул своё 1ое приложение в kubernetes.
А дальше мне интересно создать 1фронтэнд приложения и 2 бэкэнд приложения
развернуть 2 деплоя в кубере получится 2 сервиса и что-бы они. . .
|
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ *
Дана цепь постоянного тока с R, L, C, k(ключ), U, E, J. Программа составляет систему уравнений по 1 и 2 законам
Кирхгофа, решает её и находит токи на L и напряжения на C в установ. режимах до и. . .
|
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым.
Но восстановить их можно так.
Для этого понадобится консольная утилита. . .
|
Изучаю kubernetes
lagorue 13.01.2026
А пригодятся-ли мне знания kubernetes в России?
|
|
Сукцессия микоризы: основная теория в виде двух уравнений.
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
В современном мире, где конкуренция за внимание потребителя достигла пика, дизайн становится мощным инструментом для успеха бренда. Это не просто красивый внешний вид продукта или сайта — это. . .
|