#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
||||||||||||||||||||||||||||||||||||||||||||||
#1 | ||||||||||||||||||||||||||||||||||||||||||||||
Пишем свой интерпретатор языка BASIC - C++20.06.2009, 20:03. Просмотров 195970. Ответов 464
Метки нет Все метки)
(
*****************
Благодаря форуму и Evg в частности интерпретатор развивается, потихоньку превращаясь в простенький интерпретатор QBASIC. Некоторые из самых старых версий сохранились в теме и ссылки на них будут добавлены в это сообщение,а также ссылки на другие темы,связанные с этой. Репозиторий с проектом находится тут, там же есть возможность в браузере посмотреть историю ревизий (английский в логах весьма примитивен,комментарии и рекомендации можете писать в личку),а также скачать самый последний архив репозитория в формате .tar.gz Если кто-то пользуется Subversion,скачать исходники можно так: Код
svn co https://basin.svn.sourceforge.net/svnroot/basin basin Технический приём для формирования согласованных данных Makefile: как с использованием gcc строить автоматические зависимости от .h файлов? Вопрос по svn (Subversion) Создание системы тестирования ПО. Вопрос про разные реализации бэйсиков Можно ли выразить порядковый номер элемента массива через индексы? [C++] Какие флаги указать линкеру для компиляции программы? Как можно определить переменную в файле configure.in,чтобы её можно было использовать в Makefile? Странный SIGSEGV, или что зависит от порядка написания интерфейса класса Можно ли как-то указать в Makefile, чтобы часть файлов компилировал компилятор C? Альтернативная версия интерпретатора от Evg на C Это простая реализация разбора выражений, написанная Evg на C: Представление выражения в двоичном дереве ***************** Первое сообщение: ***************** Задание(Страуструп,из книги,по готовому коду): Введите программу калькулятора и заставьте её работать.Например,при вводе
LexicalAnalyzer.h
LexicalAnalyzer.cpp
main.cpp
Анализатор-то работает,но конечное значение не вычисляется.Более того,если вводим
Добавлено через 2 часа 5 минут 30 секунд Пришлось решать влоб с дебаггером.У Страуструпа опечатка (или намеренная ошибка,что более вероятно ![]()
Добавлено через 16 минут 19 секунд И ещё опечатка была
31
|
|
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
|
20.06.2009, 20:03 |
Я подобрал для вас темы с готовыми решениями и ответами на вопрос Пишем свой интерпретатор языка BASIC (C++):
464
Пишем свой чекер - C++ пишем свой троян с нуля - C++ Пишем свой класс, спецификатор доступа protected - C++ Не удается откомпилировать интерпретатор М-языка - C++ Интерпретатор небольшого языка программирования на С++ - C++
|
Evg
![]() ![]() |
|||||||||||
28.09.2009, 09:31 | #151 | ||||||||||
Да. В правой части должно быть "linear_array[(a-1)*y*z + (b-1)*z + (c-1)]". А в общем случае надо вычитать стартовый индекс (который по умолчанию равен 1, но по синтаксису можно задавать самому)
Любая пользовательская настройка должна быть в виде опции. ТОлько поведение на мой взгляд надо инвертировать. По умолчанию работать так, как принято в бэйсиках, а по опции - ломаться на неинициализированных данных. Эта опция - по сути дела отладочное средство. Технически удобнее всего делать так, что в момент заведения новой переменной ей сразу прописывать нулевую инициализацию Да, нужно сгенерировать правильный набор операций сравнений, условных переходов и т.п. Т.е. при поддержке FOR'а изменения вносятся только в синтаксический разборщик. В промежуточном представлении и интерпретаторе не надо делать ничего. Имено поэтому такой вид промежуточного представления даёт дополнительные бонусы: т.е. многие сложные высокоуровневые конструкции реализуются через один и тот же маленький набор низкоуровневых примитивов Т.е. промежуточное представление для
1
|
#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
|||||||||||||||||||||
29.09.2009, 06:42 [ТС] | #152 | ||||||||||||||||||||
При попытке сделать индексацию с единицы нашёл какой-то странный баг.При печати в данном исходнике печать первого и второго цикла расходятся.
Исходник
Сначала грешил на формулу,но когда вставил печать в первый цикл,вообще попал в тупик,так как она верная.Вообще,если после первого цикла менять значение array(3,1) или array(2,1),то меняются также значения array(2,10) и array(1,10) соответственно.Считал по формуле - получается,что у них в линейном массиве тот же индекс.
0
|
Evg
![]() ![]() |
|||||||||||
29.09.2009, 11:05 | #153 | ||||||||||
Вычитать 1 нужно только из индекса. Размерность массива остаётся прежней
Вместо
Пока не забыл, что на будущее. Чего нужно было бы сделать, но что нужно, а что нет - решай сам. В идеале надо сделать всё 1. Поддержать массивы с произвольного стартового индекса. Типа "DIM A(5 TO 10) 2. По возможности поддержать все синтаксические реализации для IF, WHILE, FOR (ну и какие там ещё есть циклы) 3. Видимо придётся наводить порядок в исходниках программы. Когда много чего работает - наверняка накопилось куча мест, которые неплохо бы переделать 4. Возможно сразу же попытаться реализовать вариант с генерацией исходника на Си++ с целью получения бинарника (о чём я уже рассказывал). Такой вариант уже имеет рассматривать с той точки зрения, что при дальнейшем развитии можно будет поддерживать обе ветки (интерпретация и генерация текста Си++), а потому многие неоптимальности видны будут сразу. Из разряда того, что при нынешней схеме реализация конструкции FOR НЕ затронула бы процесс интерпретации и генерации текста, т.к. в промежуточное представление мы не вносили новых конструкций Ну и дальнейшим пунктом развития будет реализация встроенных функций (SIN, COS, VAL, STR$, ...)
1
|
Evg
![]() ![]() |
|
30.09.2009, 14:25 | #154 |
Если смотрел мои исхожники, там есть конструкция var_DimDescr_t, описывающая размерность массива. Эту же конструкцию я использую и для описания элемента массива (которая по научному называется "декомпозиция"). Это неправильно (мне тогда просто лень было, а потом забыл). Просто должны быть две вещи:
- Описатель размерностей массива (на каждую размерность хранится стартовый индекс и размер). Этот описатель является свойством переменной - Описатель декомпозиции элемента массива (на каждую размерность хранится текущее значение индекса). Этот описатель является свойством операции Номер элемента вычисляется на основании двух этих конструкций.
1
|
Evg
![]() ![]() |
|
30.09.2009, 21:16 | #155 |
Кстати, вот ещё идея. Сделать "OPTION TRACE_CMD <val>", "OPTION TRACE_WRITE <val>". Пользовательские фичи для включения трассировки исполнения операций и трассировки записей. Т.е. если есть блок кода, который предположительно работает неправильно, то командами "OPTION TRACE_WRITE 1" и "OPTION TRACE_WRITE 0" соотвественно включаем и выключаем трассировку
1
|
#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
|
30.09.2009, 21:33 [ТС] | #156 |
В смысле навроде того,что у нас пишется в логи? Только там что будет писаться,что-то недопонимаю? UPD Всмысле будут писаться текущие значения какой-то переменной?
0
|
Evg
![]() ![]() |
|
30.09.2009, 21:41 | #157 |
Ну навроде того, только это то, что для пользователя предназначено. При печати записей печатать что-то типа
Код
a.bas:10 WRITE A = 10 a.bas:11 WRITE B = 11 ... Код
exec a.bas:10 exec a.bas:11 exec a.bas:12 Добавлено через 56 секунд Когда у тебя два заумных вложенных цикла с кучей ветвлений внутри, тяжело "теоретически" разбирать ошибки
1
|
Mozart
39 / 17 / 1
Регистрация: 21.08.2009
Сообщений: 63
|
|
01.10.2009, 14:48 | #158 |
Господа, увидел вашу тему, решил наваять что-то подобное, но у меня возникла проблема:
сначала сделал линейно и у меня выходило что 2+2*2=8, хотя 6; потом немного видоизменил код добавив рекурсию в итоге предыдущее считает правильно а 3-1+2=0 хотя 4. Как вы решали проблему приоритета умножения/деления над сложением/вычитанием? ЗЫ: если брать все в скобки - считает правильно.
0
|
#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
|
01.10.2009, 23:35 [ТС] | #161 |
В смысле негативные? Что-то не понял
![]()
0
|
#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
|
01.10.2009, 23:42 [ТС] | #163 |
А,ну так да,мы давно же обсуждали,что тесты лучше негативные делать,чтобы отлавливать правильно ошибки и если что править диалог с пользователем.
0
|
Evg
![]() ![]() |
|
01.10.2009, 23:47 | #164 |
Так надо иметь две группы тестов: позитивные и негативные. Позитивные должны нормально проходить интерпретацию и выдавать результат (и сравнивать его с эталоном). Вот про это я и говорил, что надо аккуратно эталонную печать править (изменился исходник теста, изменилась работа оператора PRINT, исправлена ошибка и т.п.). В первую очередь важно иметь хороший набор позитивных тестов
С негативными тестами как правило всё сложнее, но в твоём варианте вполне приемлимо. Заметил у тебя, что ошибки исполнения выдаются с неправильной привязкой к исходнику - с той, что соответствовала последнему токену. Поэтому в операторах я так же храню привязку, чтобы при сломе его исполнения выругаться правильно
1
|
#pragma
Временно недоступен
955 / 226 / 6
Регистрация: 12.04.2009
Сообщений: 921
|
||||||||||||||||
02.10.2009, 06:15 [ТС] | #165 | |||||||||||||||
Сделал OPTION BASE <val>, а также теперь общая форма записи для DIM такая:
Пример исходника example
Ну всё,пока делаю for,do и твои опции trace попробую сделать.
0
|
02.10.2009, 06:15 | |
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
|
02.10.2009, 06:15 |
Привет! Вот еще темы с ответами:
165
Написать интерпретатор программного языка -помощь - C++ Интерпретатор/компилятор ассемблер-подобного языка - C++ Интерпретатор музыки стандарта BASIC PLAY на С++ - C++ Задание: разработать "Интерпретатор языка". С чего начать? - C++ Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |