Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
||||||||||||||||||||||||||||||||||||||||||||||
1 | ||||||||||||||||||||||||||||||||||||||||||||||
Пишем свой интерпретатор языка BASIC20.06.2009, 20:03. Показов 242508. Ответов 464
Метки нет (Все метки)
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC.
Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой. Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz Если кто-то пользуется Subversion,скачать исходники можно так: Код
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: Представление выражения в двоичном дереве ***************** Первое сообщение: ***************** Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
LexicalAnalyzer.h
LexicalAnalyzer.cpp
main.cpp
Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
Добавлено через 2 часа 5 минут 30 секунд Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ) Вот в этом куске кода в функции get_token():
Добавлено через 16 минут 19 секунд И ещё опечатка была
31
|
20.06.2009, 20:03 | |
Ответы с готовыми решениями:
464
Пишем свой интерпретатор языка BASIC Пишем свой strlen Пишем свой чекер пишем свой троян с нуля |
09.10.2009, 17:07 | 181 | |||||||||||||||
Всё равно проблему не понял
Мой нынешний вариант
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
10.10.2009, 00:29 [ТС] | 182 | ||||||||||
Добавил ещё две опции командной строки:
Добавил
Насчет генератора кода: думаю,лучше пока отложить,а то проект становится громоздким,и добавление новых опций превращается просто в кодинг,это конечно,тоже интересно,но хочется узнать что-то новое,а не топтаться на месте.В любом случае,это можно будет добавить позже.Нужно решить какие конструкции ещё необходимы (ну INPUT я сделаю),имею в виду те,которые нужны будут чтобы двигаться дальше(где-то ты писал,что можно попробовать работу с графикой).Тут понятно,нужны встроенные функции как RND,SIN,COS и т.д.Я вижу это примерно так: на уровне представления это statement,содержащий указатель на элемент класса,у которого свои свойства и т.д.На момент интерпретации все действия выполняются реализацией класса.Ну,не знаю,насколько это правильно,может,предложишь другой вариант. Также очень интересует вопрос кроссплатформенности,и написание графического интерфейса.
0
|
10.10.2009, 00:53 | 183 |
По поводу синусов, косинусов и прочего идея такая. Заводится тип выражения - процедурный вызов. Только вызывается не пользовательский код, а встроенные функции. Функции передаётся список value'ов - параметры. И возвращается value - результат
Единственный геморрой - в бэйсике есть долбанная конструкция MID$, которая может стоять в том числе и в левой части присваивания. Но не думаю, что она очень уж часто используется По поводу графики и прочего - тогда я думал, что ты под виндами живешь, хотя ничто тебе не мешает реализовать графику под линухом. Правда надо разобраться, что за библиотеки для этого нужны и прочее - я с графикой никогда не работал По поводу кроссплатформенности - понятное дело, что текстовый режим он и в африке текстовый режим. А графика - надо сначала понимать, как на разных системах она работает, а потом думать, как это реализовать. Т.е. если делать в лоб и использовать "обычные" библиотеки, то скорее всего под каждую ветку придётся писать отдельные коды. Можно попробовать и поработать через Qt, тогда по идее с переносом на другие платформы проблем не будет Как вариант можно попробовать написать примитивный IDE. Ещё как вариант - встроенный командный отладчик. По типу gdb, но поскольку у нас интерпретатор, то должно быть всё в одном флаконе
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
10.10.2009, 01:13 [ТС] | 184 |
Да,хороший вариант с функциями.То есть функции (встроенные) будут разрешены только внутри выражений,чтобы не путаться в statements.
Qt по вкусу,надо будет попробовать.Интересует вариант создания отдельного пакета к программе,то есть чтобы были возможны оба варианта-консольный и графический.Есть же программы,к которым можно просто доустановить пакет с графическим интерфейсом,и это никак не мешает использовать прогу в консоли.Правда как это делается,сейчас пока загадка,надеюсь в своё время узнаю.
0
|
10.10.2009, 11:11 | 185 | |||||
Ну... в твоём случае под линухом, например, это можно было бы сделать в виде отдельной динамической библиотеки *.so. Под виндами это будет *.dll. Но для начала сделай, чтобы хотябы на одной платформе заработало. Или как вариант, сначала попробуй без графики под винду пернести. И ещё как вариант постоянно проверять под линухом и виндой
Добавлено через 37 минут По поводу трассировки. Возьмём, например, программу (WHILE я по-человечески ещё не переделал, а потому он в дебильном синтаксисе)
Код
$ ./interp -w TRACE: a.txt:2 WRITE I = 1 TRACE: a.txt:5 WRITE A(1) = 1 TRACE: a.txt:9 WRITE I = 2 TRACE: a.txt:7 WRITE A(2) = 2 TRACE: a.txt:9 WRITE I = 3 TRACE: a.txt:7 WRITE A(3) = 2 TRACE: a.txt:9 WRITE I = 4 Трассировка исполнения Код
$ ./interp -e TRACE: a.txt:11 EXEC LET TRACE: a.txt:2 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:4 EXEC LET TRACE: a.txt:5 EXEC BRANCH TRACE: a.txt:6 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:6 EXEC LET TRACE: a.txt:7 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:6 EXEC LET TRACE: a.txt:7 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL Ну и как вариант комбинация этих двух трассировок Код
$ ./interp -w -e TRACE: a.txt:11 EXEC LET TRACE: a.txt:2 WRITE I = 1 TRACE: a.txt:2 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:4 EXEC LET TRACE: a.txt:5 WRITE A(1) = 1 TRACE: a.txt:5 EXEC BRANCH TRACE: a.txt:6 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 WRITE I = 2 TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:6 EXEC LET TRACE: a.txt:7 WRITE A(2) = 2 TRACE: a.txt:7 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 WRITE I = 3 TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:4 EXEC LABEL TRACE: a.txt:6 EXEC LET TRACE: a.txt:7 WRITE A(3) = 2 TRACE: a.txt:7 EXEC LABEL TRACE: a.txt:8 EXEC LET TRACE: a.txt:9 WRITE I = 4 TRACE: a.txt:9 EXEC BRANCH TRACE: a.txt:10 EXEC LABEL TRACE: a.txt:3 EXEC CBRANCH TRACE: a.txt:3 EXEC LABEL
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
17.10.2009, 15:07 [ТС] | 186 |
Вчера попробовал скомпилировать исходники на 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 | 187 |
Про строки - перевод строки под виндами (и dos'ом) занимает 2 символа: '\n' и '\r'. Лечится двумя способами:
1. Файл открывать в текстовом режиме. В Си это fopen (..., "r") в отличие от "rb" для бинарного режима. Как в Си++ - не знаю, но там наверняка есть что-то подобное 2. Если файл всё же открывается в бинарном виде, то символ '\r' просто игнорировать (т.е. он трактуется как пробел и знак табуляции) Про функции посмотрю, правда копаться в исходниках неохота. В двух словах расскажи, как оно сделано Добавлено через 30 секунд > Значит,пока программа кроссплатформенная Она ж консольная, а консольные практически везде одинаково работают
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
17.10.2009, 15:18 [ТС] | 188 |
Сделал функции возможными только в выражениях.Добавил тип выражения procedure,как ты и предложил,содержит тип функции из enum и expression-параметр для передачи.На интерпретации вызывается функция по типу,вычисляется параметр,и подставляется в функцию sin cos и т.д. При этом параметр приводится к типу double,пока только эта версия существует.
0
|
17.10.2009, 16:07 | 189 |
А у тебя есть какая-нибудь возможность распечатать промежуточное представление по типу того, как делалось в моём примере. ЧТобы глазами "увидеть", как оно устроено
Добавлено через 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 [ТС] | 190 | |||||
Это как раз делается опцией в исходнике OPTION TRACE TREE <val> (то есть трассировка дерева при выполнении) или из командной строки(см.ниже опции)
А OPTION TRACE ACTION <val> выполняет роль трассировки действий,производимых с данными.Пока это только для LET,но задумано так,что для каждой инструкции можно добавить свою трассировку(например для графических функций это может быть успешная отрисовка чего-то,для циклов это может быть переход по метке или ещё что-то. Возможные опции командной строки на данный момент
Насчёт остального,это очень интересно.В принципе,для графики я так и задумывал,что будет некая "обёртка" в виде класса graphics.h +.cpp которая уже непосредственно общается с SDL,чтобы в случае чего можно было сменить графическую библиотеку по надобности,даже пусть она и кроссплатформенная.Правда насчёт PRINT я немного не понял,зачем делать для него CALL,в смысле что его реализация может зависеть от платформы?Вроде же всё работает..Как бы это стандартная конструкция. Или ты уже метишь в создание вообще какой-то глобальной обёртки для языков?
0
|
17.10.2009, 18:19 | 191 | |||||
Смысл этих действий в том, чтобы из промежуточного представления исключить "лишние" операторы и оставить минимально необходимый набор. С минимальным набором ты уже сталкивался - это построение операций управления. При этом получалось так, что добавляя новые конструкции языка ты вообще никак не затрагивал интерпретатор и промежуточное представление. С остальными операторами по большому счёту то же самое: промежуточное представление и интерпретацию не меняем, а меняем лишь "крайние" компоненты. Технически такая схема всегда более оправдана, т.к. при добавлении новой функциональности ограничиваешься минимально необходимыми правками, не меняющими логику работы интерпретации.
Да и в случае 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 [ТС] | 192 |
Странно,у меня всё нормально.В ревизии 40 уже всё сделано и я проверял-работает.. Попробуй не с командной строки,а в исходнике через OPTION,а с проблемой разберёмся,думаю.Может,ревизия не та?Я 40-вую только вчера скомиттил
0
|
17.10.2009, 23:15 | 193 | |||||
Я свежую смотрел, может я не так запускаю?
Добавлено через 3 минуты
Добавлено через 2 минуты Блин... перепутал арктангенс и котангенс
0
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|||||||||||
18.10.2009, 04:13 [ТС] | 194 | ||||||||||
Это очень странно,потому что я сейчас проверил,вот выдача с этого исходника(правда нумерация строк немного попутана,но это поправимо).
Меню я забыл обновить,оно должно вылазить на ошибках в опциях командной строки.Должно быть так:
0
|
18.10.2009, 12:01 | 195 | |||||
Ну и как я об этом мог догадаться? Правда для пользовательской опции такое поведение несколько нелогично, ну да фиг с ним пока
Код
$ ./basin a.bas 0.0001 file: a.bas line: 5 error: Cannot convert type Собственно, опять вернусь к прежнему вопросу. А просто печать представления у тебя есть? Как ты вообще просекаешь, что в итоге у тебя построилось? Тут показано то, что печатается у меня. В большинстве случаев при ошибках мне достаточно посмотреть на эту печать, чтобы увидеть, что там внутри не так построилось. А что-то подобное у тебя есть?
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
19.10.2009, 01:17 [ТС] | 196 |
Есть только печать дерева при исполнении,то есть видишь не всё построение,а только ветки,по которым идёт программа.Делается или OPTION TRACE TREE 1 в начале исходника,или --trace-tree из консоли.Печатать всё дерево не вижу смысла,если только для себя.То есть конечно для пользователя удобнее смотреть печать только тех инструкций,которые исполняются,навроде отладочного средства,но всё дерево печатать наверное не нужно?
>Ну и как я об этом мог догадаться? Правда для пользовательской опции такое поведение несколько нелогично, ну да фиг с ним пока А мне,наоборот кажется это весьма логичным:представь,что пользователь рисует что нибудь-такая печать будет мешать процессу отладки,ломая изображение.Или данные печатаются в виде таблицы,да мало ли чего.Другое дело,надо это где-то явно указать,куда пишется отладка.Например,перед началом запуска программы пользователь получает сообщение на экране,о том куда будут записаны данные в случае печати в файл.
0
|
19.10.2009, 12:41 | 197 |
Естественно, это нужно как внутреннее отладочное средство (т.е. НЕ для пользователя). Хороший набор отладочных средств в большинстве случаев позволяет найти ошибку только глядя на отладочные печати и трассы и не прибегать к отладчику
Правильно Не надо за пользователя что-то решать. Это дурной тон в стиле микрософта. Пользователь должен иметь набор инструментов для того, чтобы саму решать что и как делать. В данном случае нужна пользовательская опция, чтобы задать, куда сливается вся трассировочная печать. Нормальным поведением было бы по опции --trace-tree печатать в stdout (т.е. туда же, куда и PRINT) - тогда будет чёткое представление что и как запускается относительно пользовательских PRINT'ов. По дополнительной опции (либо в случае, если задано --trace-tree=<file>) сливать печать в файл, указанный пользователю. Точно так же все имена файлов можно настраивать через OPTION. Т.е. предоставить набор средств, предоставляющий пользователю полную свободу выбора: "хочешь - мороженное, хочешь - пирожное" (c) Добавлено через 13 минут И что немаловажно - выбор настроек по умолчанию. Т.е. при просто поданной опции правильным (на мой взгляд) считается печатать в stdout, ибо увидев эту опцию в help'е и начав проверять"методом тыка", увидев лишнюю печать на экране пользователь хоятбы поймёт, что эта функциональность реально работает и что оно делает
1
|
Временно недоступен
957 / 228 / 14
Регистрация: 12.04.2009
Сообщений: 926
|
|
22.10.2009, 00:02 [ТС] | 198 |
Вот касательно этого созрел вопрос.
Функции ведь возвращают какое-то значение,хотя и не всегда.Так сложилось исторически,что у меня при интерпретации кажая функция,обрабатывающая statement,возвращает указатель на следующую инструкцию в списке.А как ты видишь вариант с функциями? Я так немного прикинул,что будет функция interp_stmtCALL(stmt),и есть некий контейнер,в котором хранятся последние вычисленные значения функций.Но это всё же видится как костыль.Или нет? То есть если функция может выполнять роль инструкции(то есть быть не в выражении,а просто в программе) ,тогда нужно где-то хранить возвращаемое значение? Просто я начал перенос PRINT и в голову пришла такая мысль...
0
|
22.10.2009, 09:46 | 199 |
В моём пониятии вызов функции - это всё-таки 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 [ТС] | 200 | ||||||||||
Сделал инструкцию SCREEN(ревизия 42),пока только в одном варианте,так как там куча всяких режимов,я даже не знаю,получится ли все их сделать,библиотеки разные,выбрал наиболее подходящий.(640 на 480,глубина цвета 16 бит,страница создаётся в системной памяти)
В-общем,если интересно попробовать(в принципе там ничего пока не увидишь,только чёрный экран с курсором),то тогда нужно указать режим возврата(то есть твой режим видео) а то экран так и останется в 640Х480,а мне даже понравилось,некоторые старые игрушки,Homm 3 например,не растягиваются у меня на полный экран,так как у меня widescreen,а это способ,возможно,насильно растянуть картинку как хочешь. Менять нужно в файле graphics.h вот эти два enum'a
И ксатати,если не нужно полный экран,то просто убрать " | SDL_FULLSCREEN" Насчёт линий и прочего я не нашёл специальных функций,но зато обнаружил пример рисования пикселя на экране.Причём функцию нужно писать самому.Но главное нарисовать точку,а там уже "да здравствует математика".
0
|
25.10.2009, 20:00 | |
25.10.2009, 20:00 | |
Помогаю со студенческими работами здесь
200
Пишем свой класс, спецификатор доступа protected Интерпретатор небольшого языка программирования на С++ Не удается откомпилировать интерпретатор М-языка Интерпретатор музыки стандарта BASIC PLAY на С++ Написать интерпретатор программного языка -помощь Интерпретатор/компилятор ассемблер-подобного языка Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |