|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Пишем свой интерпретатор языка BASIC20.06.2009, 20:03. Показов 257085. Ответов 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
|
|
| 26.10.2009, 22:34 [ТС] | |
|
Да,вот интересно,под виндой работает намного быстрее,причём только в полноэкранном режиме,хотя и не дотягивает до натурального QBASIC-а.
Возможно,тут уже ничего не сделаешь,это уже библиотека так работает видимо,но всё же со временем надо будет попытаться ускорить хоть чуть-чуть. Небольшое напутствие,если делать линию через цикл от края до края,то почему-то нельзя указывать размер границы,видимо происходит выход запределы экрана и программа падает(скорее всего это в самой SDL)
0
|
|
|
|
|
| 26.10.2009, 23:29 | |
|
Со скоростью сделать можно, надо только разобраться. На SDL'е написан FreeCraft - по сути переделка 2-го warcraft'а под линух. Всё там шустро бегало. Надо только разобраться, как эта бодяга работает
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||||||
| 28.10.2009, 06:55 [ТС] | ||||||
|
Попробовал улучшить немного со скоростью,так,по мелочи поменял,но вроде эффект есть.Вот можешь проверить таким вот тестом.Алгоритм аппроксимации(так вроде?) линии содрал прямо с вики,там используется битовая арифметика,я пока не очень понимаю,зачем там сдвиги на 12 позиций и прочее,надеюсь потом пойму.
0
|
||||||
|
|
|
| 28.10.2009, 09:56 | |
|
Ты заметил, что когда рисуешь по точкам через PRESET, то тормозит, а когда через LINE - то практически мгновенно. Т.е. проблему я вижу в концепции SDL. Насколько я понимаю, подобные библиотеки работают через некий виртуальный монитор. Т.е. все точки ты сначала наносишь в этот монитор (который попросту лежит в обычной памяти), и эти операции являются быстрыми. Затем ты этот монитор отображаешь в реальную картинку. Делается это путём ПОЛНОГО обновления виртуального монитора на реальную картинку. Этот процесс уже "медленный" (по сравнению с помещением точки в виртуальный монитор)
В случае, когда ты рисуешь по точкам, получается, что для происовки линии из 100 точек тебе нужно 100 раз обновить экран. Когда ты рисуешь линию, то сначала все 100 точек линии отображаются в виртуальный монитор, и затем один раз обновляются. Т.е. в теории нарисовать линию из 100 точек работает в 100 раз быстрее, чем рисовать 100 точек Библиотека видно написана всё-таки для игрушек. Поскольку игрушки как правило отображают экран по тикам. Т.е. (к примеру) 60 раз в секунду рассчитывается картинка, при этом она сначала рисуется по точкам в виртуальный монитор (т.к. эти операции быстрые), а затем картинка отрисовывается на экран (медленная операция, но 60 раз в секунду успевает). Для интерпретатора такое поведение неудобно, потому что у тебя нет точек привязки, по которым можно отображать картинку из виртуального монитора на реальный. В качестве эксперимента можешь ввести дополнительный оператор в бэйсике, который перенесёт виртуальный монитор на реальную картинку, а все точки ставить строго в виртуальном мониторе. Этот эксперимент нужен лишь для того, чтобы проверить догадку. Если она оправдается, то надо придумать механизм, как это работало бы нормально. Т.е. видимо всегда всё будет рисоваться в виртуальный монитор, при этом асинхронно по таймеру виртуальный монитор будет отображаться в картинку Добавлено через 5 минут Ещё надо какую-нить операцию для паузы (опять-таки можно врЕменную), чтобы картинка не удалялась. А то если вставить бесконечный цикл, то программу только по kill -9 смог убить. INPUT так и не понял, как правильно писать
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 28.10.2009, 18:40 [ТС] | |
|
Насчёт обновления картинки ты прав на все 100.Прямо в точку.Подозрение пало как раз на функцию SDL_UpdateRect(x,y,w,h) и я прочитал в интернете как многие жаловались на медленную работу графики с этой функцией.
В качестве средства предлагалось добавить флаг SDL_DOUBLEBUF при выставлении режима видео,а также создавать поверхность не в системной памяти,а в видеопамяти.После чего просто использовать функцию SDL_Flip,которая делает замену между первым и вторым буфером,происходит это довольно быстро.Но всё же она ждёт вертикальной синхронизации,и в некоторых случаях SDL_UpdateRect может работать быстрее. Но самое правильное-это таймер. В общем пока для пикселей используется SDL_UpdateRect и обновляет только один пиксель,который рисуется,а для линий тоже SDL_UpdateRect ,только обновляется только четырёхугольник,диагональю которого является рисуемая линия. Но ты всё правильно сказал-нужен таймер,чтобы обновлял всю картинку с помощью SDL_Flip с постоянной частотой,например 30-35 кадров в секунду,и сделать это следует безусловно,иначе графика попиксельно(да и вообще)будет относительно тормознутой.Благо таймер в SDL существует как отдельная подсистема,и его можно просто подключить. Насчёт паузы после рисования-в самом QBASIC-е после рисования картинки появляется надпись "Нажмите любую клавишу для продолжения",поэтому надо будет как-то писать текст внизу поверх картинки или что-то такое. Добавлено через 19 минут А ещё забыл сказать:дело ещё не только в этом - как оказалось,у меня почему-то режим с глубиной цвета 16бит(слабо представляю,что это вообще) жутко тормозит,а когда делаешь 32бит,то всё намного быстрее.Так вот я добавил флаг SDL_ANYFORMAT,так что теперь есть предпочтение на 16бит,но если в силу каких-либо причин этот режим не очень подходит,библиотека сама подберёт лучший режим.
0
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 30.10.2009, 23:30 [ТС] | |
|
Что-то пока никак не соображу,как же работают таймеры.Вот есть программа,с каким-то списком инструкций.А где-то есть функция,запускающая таймер и следящая за временными отрезками.Но ведь программа не состоит из одной этой функции,как тогда обновляется таймер вовремя? Или сам таймер должен работать как отдельный процесс,или я не знаю.Какая там концепция?
0
|
|
|
|
|
| 30.10.2009, 23:45 | |
|
Вообще концепция по идее такая, что процесс вызывает ядро и говорит "разбуди через 10 миллисекунд", через 10 миллисекунд выдаётся сигнал, программа прерывается и вызывается пользовательский обработчик сигнала (см. sigaction). Но я не знаю, насколько такое быстро работает, к тому же это линух-зависимое
Что касается встроенной возможности в SDL, то я как-то не понял (правда особо и не разбирался). Но там они пишут, что это замедляет работу, но в SMP этого замедления не будет. SMP, насколько я понимаю, это многопроцессорная машина, а потому вполне возможно, что запускают ещё один процесс
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||||||||||||
| 31.10.2009, 08:02 [ТС] | |||||||||||||||||||||
|
Как раберусь,сделаю таймер.
Пока делал опции для LINE столкнулся с проблемкой: Синтаксис LINE описывается так (Источник,которым пользуюсь):
Поэтому временно синтаксис LINE:
Пока нет проверки на рисование за границы экрана,поэтому сразу говорю,неправильные данные рушат SDL.Пока не решил,где и как именно сделать проверку,но это мелочи. Небольшой тест
P.S. >Ещё надо разбираться с тем, что если программа зациклилась на интерпретации в то время, как работает графический режим, то кроме как по kill -9 она не убивается А что вообще можно с этим сделать? Какие есть выходы из ситуации? Делать интерпретатор работающий с threads?
0
|
|||||||||||||||||||||
|
|
||||
| 31.10.2009, 11:51 | ||||
|
Добавлено через 3 минуты
1
|
||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 02.11.2009, 12:23 [ТС] | |
|
Помнишь,ты писал,что отдельный графический интерфейс делается в виде библиотеки .so или .dll? А что должно быть внутри библиотеки? Как именно она должна взаимодействовать с консольным приложением? Есть ли там функция main,всмысле это тоже отдельная программа? Я поискал,некоторые советуют делать общение GUI с программой через сокеты.Но в тоже время есть класс в Qt,называется QProcess,и он предназначен для запуска внешних программ.Значит,если в таком варианте,нужно разработать ещё одно приложение с окнами,которое будет обрабатывать события и запускать что нужно с необходимыми опциями командной строки.Но тогда это уже нельзя сделать в виде .so?
0
|
|
|
|
|
| 02.11.2009, 15:38 | |
|
Динамическая библиоткеа - это по большому счёту часть кода, вынесенная отдельно. Это экономит дисковое пространство, т.к. динамическая библиотека есть в единственном экземпляре и нет необходимости статически линковать к каждому бинарнику
Второй бонус динамической библиотеки - это возможность её подключения прямо во время работы программы О чём говорил я "тогда" - толком уже и не помню. Но смысл скорее всего сводится к тому, что ты заводишь некий абстрактный интерфейс для работы с графикой. Грубо говоря, это процедуры типа "инициализировать графику", "нарисовать точку в виртуальное окно", "отобразить виртуальное окно на физическое" и т.п. - т.е. набор низкоуровневых примитивов. Далее ты можешь создать динамическую библиотеку, которая реализовывает этот интерфейс через SDL, потом другую библиотеку, которая реализовывает этот интерфейс через что-то другое. Т.е. для твоего интерпретатора получается до фонаря, что там делается на низком уровне и какая реально графическая библиотека используется, он работает с предоставленным интерфейсом В какое-то время, глядя на твои заслуги по части графики у меня зачесалась ж..а и я тоже что-то там сделал, но в итоге опять забил. Т.е. сейчас всё находится в некотором устаканившемся состоянии, можешь попробовать посмотреть. 1. Сейчас FOR сделан несколько через ж...у (там вроде бы только целочисленный положительный STEP поддерживается) 2. В SCREEN можно подать любое число (пока оно игнорируется, реально должно отрабатываться в __rt_graph_SCREEN. Выхода обратно в текстовый режим пока нет 3. Обрати внимание на то, как реализованы PRINT, синусы-косинусы, графика с точки зрения реализации в виде процедур - для движка промежуточного представления всё это выглядит в виде одной и той же конструкции. При этом в операции вызова я список аргументов печатаю в квадратных скобках (чтобы не мельтешило в глазах с круглыми скобками от выражений) - запускай "./interp -s" 4. Обрати внимание, как у меня на нижнем уровне (runtime) реализована графика: разбор непосредственно бэйсиковской реализации отдельно, работа с графической библиотекой отдельо, алгоритмы прорисовки отдельно 5. Всё то, что находится в graph_sdl.c по большому счёту и есть та динамическая библиотека, о которой я писал выше. Если заменить префикс sdl_ на что-нибудь другое, то мы как раз и получим тот абстрактный интерфейс нижнего уровня. Всё, что находится за пределами модуля sdl_graph "не знает" о том, что мы работаем с библиотекой SDL 6. Пока по прежнему на вход читаем файл a.txt. Опции, которые на данный момент могут тебе показаться интересными Пользовательские: -w трассировка записей -e трассировка исполнения -u по умолчанию все переменные прописываются undef'ами (для отладки неинициализированных значений) Внутренние: -s печать промежуточного представления Остальные опции увидишь в main.c но они тебе особенно не интересны
1
|
|
|
|
|
| 13.11.2009, 14:14 | |
|
Оказывается, я тебе наврал про реализацию двухаргументных арифметических операций. Я почему-то всю жизнь считал, что в Си второй аргумент приводится к типу первого. Оказывается это не так. Из двух аргументов выбирается "более широкий тип" и оба аргумента приводятся к этому типу (а точнее, приводится только один из аргументов, ибо второй имеет этит тип) и результат имеет этот самый более широкий тип. Считается, что плавающий тип шире целого
Т.е. я утверждал, что INT + FLOAT эквивалентно (int) (INT + (int)FLOAT), на самом деле это (float) ((float)INT + FLOAT). Т.е. поведение в этом месте бэйсика и Си совпадают. Собственно из-за неправильной реализации у меня коряво работала картинка с синусами и косинусами - мне приходилось заводить плавающие константы
1
|
|
|
|
||
| 14.11.2009, 12:43 | ||
|
1
|
||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 16.11.2009, 11:45 [ТС] | |
|
А я не осваивал.Там в документации есть примеры (с исходниками),я просто взял за основу исходники окошка с подсветкой кода,немного поменял его (там понятный код,правда шаблоны знаков ("регекспы") пришлось методом тыка делать).Ещё там рядом есть пример,но с ToolBar-ом с кнопочками-иконками,я оттуда перенёс этот тулбар.
Сначала-то я вообще не знал,с чего начинать,то ли .ui файл делать с дизайнером,то ли ещё как-то.Тыкался,тыкался,пока не содрал из документации.В-общем,хотел как лучше,а получилось как всегда
0
|
|
|
|
|
| 16.11.2009, 12:05 | |
|
Понятно. Тогда придётся всё-таки осваивать. Ибо для полного счастья надо ещё и отладчик встроенный сделать. Ну а потом остаётся тупое развитие и добавление новых инструкций языка
Добавлено через 55 секунд Кстати, у тебя как сечас сделано? И gui, и интерпретатор всё в одном флаконе? По идее нормально должно быть так, что интерпретатор отдельно, а гуй отдельно и из гуя вызывается (запускается) интерпретатор
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 16.11.2009, 23:31 [ТС] | |
|
Ой,а у меня наоборот )). Я просто подумал,что консольный вариант главный,gui только как опция.Ну ещё от незнания,что-то я сразу не представил вариант,когда gui вызывает консольное приложение.Просто тогда получается,что нужно все исходники интерпретатора вкладывать в проект GUI (это мне так видится).Или как иначе? В Qt же по нажатию на кнопку нужно вызывать функцию из интерпретатора,а как её туда "приделать"?
0
|
|
|
|
||
| 16.11.2009, 23:57 | ||
|
Нормально должно быть так. Отдельно пишется интерпретатор (т.е. то, что у тебя было до гуя). Отдельно пишется графическая оболочка с редактором. Далее в этой графической оболочке при нажатии на клавишу "Run" у тебя записывается редактируемый файл с исходником (чтобы все правки подцепились), после чего запускается "basin source.bas". По завершении исполнения программы анализируем код возврата: если у нас отработало нормально, значит передаём управление обратно на редактор. Если завершилось с ошибкой, то анализируем выдачу от интерпретатора в stdout: парсим то, что он напечатал (вырезаем имя файла и номер строки), позиционируем курсор на той строке исходника и где-то отображаём полную выдачу ошибки от интерпретатора
В нормальном случае делается так, что отдельной поставкой выдаётся интерпретатор (как логически законченная программа), а дополнительной поставкой ставится гуй, в качестве настройки которому надо указать, где лежит интерпретатор. И как вариант делается некоторая полная поставка, включающая в себя оба компонента. Технически удобнее держать исходники в разных каталогах: интерпретатор отдельно, гуй отдельно. Делать это в одном репозитории или в двух разных - хз как удобнее. Для начала делай так, как удобнее, а там будет видно, как надо правильно
1
|
||
| 16.11.2009, 23:57 | |
|
пишем свой троян с нуля Пишем свой класс, спецификатор доступа protected Интерпретатор небольшого языка программирования на С++ Не удается откомпилировать интерпретатор М-языка
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS
Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
|
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи.
Через несколько переработок от PHP кода к C89 (надеюсь, 89).
Но довольно запутанно получилось. Код для Linux.
Но если убрать time и то, что с ним. . .
|
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки
Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
|
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы
Всем привет! Хочу поделиться свежим (и довольно. . .
|
|
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
|
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения:
- добавлена многоязычность
- добавлено снятие скриншотов
- добавлено поддержание бафов хождения по воде (для жреца, дк и шамана)
- и так, по. . .
|
Алиса нашла кучу ошибок компиляции и запуска в проекте, который без проблем компилировался и запускался)))
anaschu 30.06.2026
Я пока посмеюся, но завтра проверю. А вообще интерсно. Дал алисе файл, в котором точно нет ошибок компиляции и запуска, и попросил их найти. Нашла кучу)))
Критические ошибки, мешающие компиляции и. . .
|
сукцессия 16. Общий обзор, в основном что бы другие ии поняли
anaschu 29.06.2026
# Передаточный документ: модель микоризной сукцессии (для нового чата)
Этот документ предназначен для того, чтобы новый чат Claude мог продолжить
работу без необходимости заново разбираться в. . .
|