|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||||||||||||||||||||||||||||||||||||||||||
Пишем свой интерпретатор языка BASIC20.06.2009, 20:03. Показов 251182. Ответов 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
Пишем свой чекер |
|
|
||||||||||||||||
| 09.10.2009, 17:07 | ||||||||||||||||
|
Всё равно проблему не понял
Мой нынешний вариант
1
|
||||||||||||||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
| 10.10.2009, 00:29 [ТС] | |||||||||||
|
Добавил ещё две опции командной строки:
Добавил
Насчет генератора кода: думаю,лучше пока отложить,а то проект становится громоздким,и добавление новых опций превращается просто в кодинг,это конечно,тоже интересно,но хочется узнать что-то новое,а не топтаться на месте.В любом случае,это можно будет добавить позже.Нужно решить какие конструкции ещё необходимы (ну INPUT я сделаю),имею в виду те,которые нужны будут чтобы двигаться дальше(где-то ты писал,что можно попробовать работу с графикой).Тут понятно,нужны встроенные функции как RND,SIN,COS и т.д.Я вижу это примерно так: на уровне представления это statement,содержащий указатель на элемент класса,у которого свои свойства и т.д.На момент интерпретации все действия выполняются реализацией класса.Ну,не знаю,насколько это правильно,может,предложишь другой вариант. Также очень интересует вопрос кроссплатформенности,и написание графического интерфейса.
0
|
|||||||||||
|
|
|
| 10.10.2009, 00:53 | |
|
По поводу синусов, косинусов и прочего идея такая. Заводится тип выражения - процедурный вызов. Только вызывается не пользовательский код, а встроенные функции. Функции передаётся список value'ов - параметры. И возвращается value - результат
Единственный геморрой - в бэйсике есть долбанная конструкция MID$, которая может стоять в том числе и в левой части присваивания. Но не думаю, что она очень уж часто используется По поводу графики и прочего - тогда я думал, что ты под виндами живешь, хотя ничто тебе не мешает реализовать графику под линухом. Правда надо разобраться, что за библиотеки для этого нужны и прочее - я с графикой никогда не работал По поводу кроссплатформенности - понятное дело, что текстовый режим он и в африке текстовый режим. А графика - надо сначала понимать, как на разных системах она работает, а потом думать, как это реализовать. Т.е. если делать в лоб и использовать "обычные" библиотеки, то скорее всего под каждую ветку придётся писать отдельные коды. Можно попробовать и поработать через Qt, тогда по идее с переносом на другие платформы проблем не будет Как вариант можно попробовать написать примитивный IDE. Ещё как вариант - встроенный командный отладчик. По типу gdb, но поскольку у нас интерпретатор, то должно быть всё в одном флаконе
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 10.10.2009, 01:13 [ТС] | |
|
Да,хороший вариант с функциями.То есть функции (встроенные) будут разрешены только внутри выражений,чтобы не путаться в statements.
Qt по вкусу,надо будет попробовать.Интересует вариант создания отдельного пакета к программе,то есть чтобы были возможны оба варианта-консольный и графический.Есть же программы,к которым можно просто доустановить пакет с графическим интерфейсом,и это никак не мешает использовать прогу в консоли.Правда как это делается,сейчас пока загадка,надеюсь в своё время узнаю.
0
|
|
|
|
||||||||||||||||||||||
| 10.10.2009, 11:11 | ||||||||||||||||||||||
|
Добавлено через 37 минут По поводу трассировки. Возьмём, например, программу (WHILE я по-человечески ещё не переделал, а потому он в дебильном синтаксисе)
Трассировка исполнения
Ну и как вариант комбинация этих двух трассировок
1
|
||||||||||||||||||||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 17.10.2009, 15:07 [ТС] | |
|
Вчера попробовал скомпилировать исходники на Widows XP,компилятор g++,всё скомпилировалось гладко.Значит,пока программа кроссплатформенная.Проверил тестовый исходник-работает.
Есть небольшая неувязка из-за того,что винда конец строки по другому делает.Или по другой причине,точно не знаю,особо не засиживался,так,поглядел.В-общем,номера строк при ошибках вычисляются неправильно: число точно в два раза больше,чем надо.Я думаю,это связано с окончанием строк как-то,но точно не знаю.И что мне с этим делать?Делить тупо пополам? Ну ELSEIF вроде сделал,твой тест проходит,также SIN COS TAN ATN,остальные функции постараюсь не затягивать и сделаю. Сейчас начал потихоньку читать про разные графические библиотеки,пришёл к выводу,что xlib лучше не использовать.Остановился на SDL,она вроде и кроссплатформенная даже,так что проблем с переносимостью будет меньше.Ну и хорошего вроде написали про SDL,надо попробовать. Добавлено А да,ещё сделал трассировку ав твоём варианте,теперь OPTION TRACE ACTION <val> и OPTION TRACE TREE <val>,и там по мелочи опции командной строки поменял,всё можно увидеть в option.cpp
0
|
|
|
|
|
| 17.10.2009, 15:13 | |
|
Про строки - перевод строки под виндами (и dos'ом) занимает 2 символа: '\n' и '\r'. Лечится двумя способами:
1. Файл открывать в текстовом режиме. В Си это fopen (..., "r") в отличие от "rb" для бинарного режима. Как в Си++ - не знаю, но там наверняка есть что-то подобное 2. Если файл всё же открывается в бинарном виде, то символ '\r' просто игнорировать (т.е. он трактуется как пробел и знак табуляции) Про функции посмотрю, правда копаться в исходниках неохота. В двух словах расскажи, как оно сделано Добавлено через 30 секунд > Значит,пока программа кроссплатформенная Она ж консольная, а консольные практически везде одинаково работают
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 17.10.2009, 15:18 [ТС] | |
|
Сделал функции возможными только в выражениях.Добавил тип выражения procedure,как ты и предложил,содержит тип функции из enum и expression-параметр для передачи.На интерпретации вызывается функция по типу,вычисляется параметр,и подставляется в функцию sin cos и т.д. При этом параметр приводится к типу double,пока только эта версия существует.
0
|
|
|
|
|
| 17.10.2009, 16:07 | |
|
А у тебя есть какая-нибудь возможность распечатать промежуточное представление по типу того, как делалось в моём примере. ЧТобы глазами "увидеть", как оно устроено
Добавлено через 13 минут
Добавлено через 17 минут А теперь то, к чему я клонил, когда говорил про функции 1. Выносим функцию expr_CalcProcedure в отдельный модуль (который назвать function.cpp или ещё как, потому как к выражению он уже не очень относится). В результате чего имеем следующее: при добавлении новой функции мы делаем исправления только "вверху" (в разборе синтаксиса) и "внизу" (в процессе вычисления этого call'а), а вся серёдка (промежуточное представление, интерпретация) не меняются. 2. Поддерживаем возможность работы, когда у функции несколько входных переменных 3. А теперь самое интересное. Заводим в function.cpp некую внутреннюю функцию "__print". "Внутреннюю" в том смысле, что пользователь напрямую её вызвать не может. Далее в процессе разбора синтаксиса вместо оператора SK_PRINT строим некий фиктивный оператор CALL (который по сути то же самое, что ты сейчас с делал в выражении) и будем строить операцию вызова процедуры "__print" и формировать список параметров к ней. Такое поведение даёт тебе тот же самый бонус, что и в пункте 1: по сути поведение PRINT'а у тебя настраивается только "сверху" и "снизу", а вся "серёдка" остаётся без изменений. Теперь, допустим, ты добавляешь оператор LINE (для нарисования линии). В function.cpp заводим функцию "__line", а в синтаксисе формируем вызов этой функции. Таким образом серединку мы опять-таки не трогали (что крайне важно). Далее функцию, которая реализует "__line" ты можешь писать в двух экземплярах: одну под линух, другую под винду (к примеру, если будешь работать на разных графических библиотеках). Таким образом архитектурно-зависимая часть будет разводиться только в самом низу, а всё остальное высокоуровневое будет работать одинаково на всех архитектурах В результате, то, что я называл "серёдкой" фактически выполняет роль некоторого движка. "Сверху" ему задаётся набор операторов, основная часть которых является фиксированной (LET, Условные переходы), а всё остальное реализуется в виде операции процедурного вызова. "Снизу" задаётся вся логика работы процедурных вызовов. Код движка при этом по большому счёту не модифицируется. При этом "сверху" ты можешь понимать синтаксис какого-то другого языка и посадить его на тот же самый движок, возможно добавив что-то "снизу" По такому принципу работают и всякие игрушки. Например, для стрелялок сначала пишется некий движок, которому "сверху" задаются текстуры для уровней, описание уровня (где какая стена и текстура и т.п.), описание моделей игроков, а сам движок занимается только отрисовкой изображения. В итоге получается так, что совершенно разные по внешнему виду игрушки реально сидят на одном и том же графическом движке, просто уровни и игроки задаются разными текстурами и моделями Хз насколько понятно пояснил, но на мой взгляд пойдя по такому пути можно сделать интерпретатор, в который очень легко добавляется новая функциональность. Тезнически может быть проще будет сначала реализовать несколько графических операторов (POINT, LINE, CIRCLE), а потом будет больше ясности на предмет того, как техничеси организовывать такую схему
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||
| 17.10.2009, 17:06 [ТС] | |||||||
|
А OPTION TRACE ACTION <val> выполняет роль трассировки действий,производимых с данными.Пока это только для LET,но задумано так,что для каждой инструкции можно добавить свою трассировку(например для графических функций это может быть успешная отрисовка чего-то,для циклов это может быть переход по метке или ещё что-то. Возможные опции командной строки на данный момент
Насчёт остального,это очень интересно.В принципе,для графики я так и задумывал,что будет некая "обёртка" в виде класса graphics.h +.cpp которая уже непосредственно общается с SDL,чтобы в случае чего можно было сменить графическую библиотеку по надобности,даже пусть она и кроссплатформенная.Правда насчёт PRINT я немного не понял,зачем делать для него CALL,в смысле что его реализация может зависеть от платформы?Вроде же всё работает..Как бы это стандартная конструкция. Или ты уже метишь в создание вообще какой-то глобальной обёртки для языков?
0
|
|||||||
|
|
||||||||
| 17.10.2009, 18:19 | ||||||||
|
Да и в случае print'а. "Внизу" ты делаешь "тупую" реализацию: на входе получаешь набор Value'ов и тупо его распечатываешь. При этом "вылизывание" семантики PRINT'а в соответствии с тем, как оно должно быть в настоящем бэйсике, делается только "наверху" в момент синтаксического разбора. У тебя сейчас PRINT неправильно работает, но предположим, он работает правильно. Тогда для конструкции
строка "A=" целое (или плвающее) A строка " B=" строка "\t" (табуляция) - т.к. там стоИт запятая, а не точка с запятой целое (или плвающее) B строка "\n" (перевод строки) - т.к. в конце у нас нет символа ";" В итоге всю языковую семантику мы обрабатываем "сверху" в синтаксической части (которая напрямую завязана на язык), а выполняем примитивные действия "внизу" - т.к. там нам нужно лишь напечатать, а всякие форматы и что да как задаётся - пусть это решает та часть, которая отвечает за входной язык То же самое касается всех остальных операторов языка. Например, что касается LINE, то процедура "__line" должна тупо рисовать линию от одной точки до другой с заданным цветом. А вот в случае, если цвет не задан, то пусть "наверху" языковая часть решает, каким цветом надо рисовать в тех случаях, если цвет явно не указан. Это не задача процедуры "__line", это задача языковой части. Или, например, вроде бы возможно написать "LINE - (100, 100)", что означает линию от последней поставленной точки до точки (100,100). Опять-таки, пусть это решается "наверху", и в конечном итоге позовётся "__line" со всеми нужными параметрами Просто обозначил как некую теоретическую возможность, чтобы понятно было, что на каком уровне должно делаться и какая компонента за что должна отвечать. Я понимаю, что понять насколько это важно или нужно можно лишь тогда, когда сначала сделаешь "в лоб", а потом "правильно" и сравнить один и другой подход. Но в качестве некоего аналога такой концепции я тебе уже привёл построение операций управления. Смысл там такой же.Добавлено через 2 минуты Что-то опции нифига не работают. Да и посмотреть хотелось не трассу исполнения, а просто все операторы промежуточного представления
1
|
||||||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 17.10.2009, 18:46 [ТС] | |
|
Странно,у меня всё нормально.В ревизии 40 уже всё сделано и я проверял-работает.. Попробуй не с командной строки,а в исходнике через OPTION,а с проблемой разберёмся,думаю.Может,ревизия не та?Я 40-вую только вчера скомиттил
0
|
|
|
|
|||||||
| 17.10.2009, 23:15 | |||||||
|
Я свежую смотрел, может я не так запускаю?
Добавлено через 3 минуты
Добавлено через 2 минуты
0
|
|||||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
| 18.10.2009, 04:13 [ТС] | |||||||||||
|
Это очень странно,потому что я сейчас проверил,вот выдача с этого исходника(правда нумерация строк немного попутана,но это поправимо).
Меню я забыл обновить,оно должно вылазить на ошибках в опциях командной строки.Должно быть так:
0
|
|||||||||||
|
|
||||||||||||
| 18.10.2009, 12:01 | ||||||||||||
Правда для пользовательской опции такое поведение несколько нелогично, ну да фиг с ним пока
Собственно, опять вернусь к прежнему вопросу. А просто печать представления у тебя есть? Как ты вообще просекаешь, что в итоге у тебя построилось? Тут показано то, что печатается у меня. В большинстве случаев при ошибках мне достаточно посмотреть на эту печать, чтобы увидеть, что там внутри не так построилось. А что-то подобное у тебя есть?
1
|
||||||||||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
| 19.10.2009, 01:17 [ТС] | |
|
Есть только печать дерева при исполнении,то есть видишь не всё построение,а только ветки,по которым идёт программа.Делается или OPTION TRACE TREE 1 в начале исходника,или --trace-tree из консоли.Печатать всё дерево не вижу смысла,если только для себя.То есть конечно для пользователя удобнее смотреть печать только тех инструкций,которые исполняются,навроде отладочного средства,но всё дерево печатать наверное не нужно?
>Ну и как я об этом мог догадаться? Правда для пользовательской опции такое поведение несколько нелогично, ну да фиг с ним пока А мне,наоборот кажется это весьма логичным:представь,что пользователь рисует что нибудь-такая печать будет мешать процессу отладки,ломая изображение.Или данные печатаются в виде таблицы,да мало ли чего.Другое дело,надо это где-то явно указать,куда пишется отладка.Например,перед началом запуска программы пользователь получает сообщение на экране,о том куда будут записаны данные в случае печати в файл.
0
|
|
|
|
||||
| 19.10.2009, 12:41 | ||||
|
Добавлено через 13 минут И что немаловажно - выбор настроек по умолчанию. Т.е. при просто поданной опции правильным (на мой взгляд) считается печатать в stdout, ибо увидев эту опцию в help'е и начав проверять"методом тыка", увидев лишнюю печать на экране пользователь хоятбы поймёт, что эта функциональность реально работает и что оно делает
1
|
||||
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||
| 22.10.2009, 00:02 [ТС] | ||
|
Вот касательно этого созрел вопрос.
0
|
||
|
|
|
| 22.10.2009, 09:46 | |
|
В моём пониятии вызов функции - это всё-таки expr, а не statement. В случае print'а мы имеем statement с именем call, который внутри себя содержит expr с именем call. У себя я буду делать так, что все функции (__print, __line и т.п.) на вход будут понимать список value'ов (или масив - не суть) и возвращать value. Внутри выражений будет всё считаться точно так же, как и, например, для операции сложения - отдаём куда-то значения, а то, что нам возвращается, отдаём наверх.
Только вот с такой позиции пока не совсем понятно, как делать INPUT. Т.е. он содержит имя переменной, которую надо передавать НЕ как value, а наоборот, как адрес. Теоретически это рулится элементарно тем, что заводится value, означающее адрес на переменную. Но в моём варианте интерпретатора нет нигде взятие адреса на переменную, т.к. мне не хотелось выставлять в интерфейс прямой доступ к месту, где хранится value внутри переменной, но по ходу дела придётся Исходя из такой концепции можно и арифметические выражения удалять и реализовывать их в виде функций. Таким образом промежуточное представление будет состоять по большому счёту из одних операций call. Единственное, я пока не уверен, а не будет ли это слишком большим извратом. Добавлено через 22 минуты Хотя с INPUT'ом я что-то торможу. Процедура __input возвращает в виде строкового value то, что введено с клавиатуры. А дальше просто строится операция присваивания с корректным учётом типа
1
|
|
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
| 25.10.2009, 20:00 [ТС] | |||||||||||
|
Сделал инструкцию SCREEN(ревизия 42),пока только в одном варианте,так как там куча всяких режимов,я даже не знаю,получится ли все их сделать,библиотеки разные,выбрал наиболее подходящий.(640 на 480,глубина цвета 16 бит,страница создаётся в системной памяти)
В-общем,если интересно попробовать(в принципе там ничего пока не увидишь,только чёрный экран с курсором),то тогда нужно указать режим возврата(то есть твой режим видео) а то экран так и останется в 640Х480,а мне даже понравилось,некоторые старые игрушки,Homm 3 например,не растягиваются у меня на полный экран,так как у меня widescreen,а это способ,возможно,насильно растянуть картинку как хочешь. Менять нужно в файле graphics.h вот эти два enum'a
И ксатати,если не нужно полный экран,то просто убрать " | SDL_FULLSCREEN" Насчёт линий и прочего я не нашёл специальных функций,но зато обнаружил пример рисования пикселя на экране.Причём функцию нужно писать самому.Но главное нарисовать точку,а там уже "да здравствует математика".
0
|
|||||||||||
| 25.10.2009, 20:00 | |
|
Помогаю со студенческими работами здесь
200
пишем свой троян с нуля Пишем свой класс, спецификатор доступа protected Интерпретатор небольшого языка программирования на С++ Не удается откомпилировать интерпретатор М-языка
Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
||||
|
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта
Симптом:
После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
|
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
|
Новый ноутбук
volvo 07.12.2025
Всем привет.
По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне:
Ryzen 5 7533HS
64 Gb DDR5
1Tb NVMe
16" Full HD Display
Win11 Pro
|
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
|
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
|
|
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов
На странице:
https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/
нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
|
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов.
. . .
|
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
|
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
|
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут.
В век Веб все очень привыкли к дизайну Single-Page-Application .
Быстренько разберем подход "на фреймах".
Мы делаем одну. . .
|