Copyright (C) 1998-2007 MKTMK
http://www.mktmk.narod.ru.
e-mail: mktmk<at>narod.ru
This document write in WIN1251 code (Russian).
Пакет Open Basic.
Описание
применения.
Версия
1.80.
Open Basic (OB) представляет собой реализацию
интерпретатора языка Basic.
OB разработан для встраивания в приложения
пользователя в качестве скриптового
языка.
OB имеет возможность расширения системы команд
путем подключения
пользовательских
функций к исполняющей системе Open Basic.
Пользовательские функции могут быть написаны
на C/C++, ассемблере или других
языках.
Пользовательские функции могут вызываться из Basic-программы, получать
параметры
разных типов из Basic-программы и возвращать результаты своей работы
в
Basic-программу.
Специально разработанный интерфейс вызова
пользовательских функций позволяет
на
этапе исполнения определить тип и порядок следования параметров в вызове.
OB реализует подмножество команд языка Basic.
OB написан полностью на C++ и
реализован
в виде класса с именем ob_obasic.
OB поддерживает данные трех типов: с плавающей
точкой, целые со знаком, строковые и массивы этих типов.
В документе описывается:
- порядок работы с интерпретатором Open Basic
- синтаксис операторов Open Basic
- интерфейс к данным Open Basic из
пользовательских функций
- правила подключения пользовательских функций
- типы данных Open Basic
- возможности отладки
OB не использует никаких графических
библиотек.
OB не использует никаких системных вызовов ОС.
Copyright (C) 1998-2007 MKTMK
http://www.mktmk.narod.ru.
e-mail: mktmk<at>narod.ru
MKTMK software company.
Если Вы собираетесь применять
интерпретатор, и хотите знать об выходе новых
версий
и о возможных изменениях почтового и WWW адреса, то сообщите об этом
по e-mail.
MKTMK software company заинтересована в опыте
применения интерпретатора:
- для чего Вы применяете интерпретатор
- Ваш транслятор и номер его версии
- найденные в программе ошибки
- полнота документации и ошибки в ней
- подключали ли Вы пользовательские функции
- какие замечания к интерфейсу пользовательских
функций
- с какой ОС Вы работаете
- откуда Вы узнали об интерпретаторе
Эти сведения помогут нам при сопровождении
программы.
Интерпретатор и документация поставляются на
условиях "как есть". Фирма MKTMK
не
несет ответственности за возможные убытки, понесенные из-за использования
интерпретатора.
Мы будем признательны за все найденные в
программе ошибки.
Все упомянутые в тексте торговые марки
являются собственностью их владельцев.
18.feb.2007 – версия 1.80 для Windows и Linux
1. Исправлена ошибка в индексации
массива элементом массива
2. Теперь имя файла в операторе OPEN может задаваться не только
строковой константой, но и строковой переменной.
3. Начиная с версии 1.80 в *.bas программе кроме меток в виде чисел
(номеров строк) поддерживаются строковые метки с двоеточием в конце
4. Из класса ob_obasic исключены методы getstarttime() и getstoptime() как не относящиеся к основному
назначению интерпретатора. Пользователь легко может
самостоятельно проконтролировать время выполнения любого метода интерпретатора.
28.aug.2005 – версия 1.71 для Windows и Linux
Исправлена
ошибка в функции возвращения номера версии
21.aug.2005 – версия 1.70 для Windows и Linux
Исправлена
ошибка при работе с шестнадцатеричными числами
Созданы
multithread
библиотеки для MSVC7
23.feb.2005 – версия 1.50 для Windows и Linux
1998 – первая версия для DOS
Файлы примеров *.bas программ
.\bas
test1.bas
test2.bas
test3.bas
test4.bas
test5.bas
test6.bas
test7.bas
test8.bas
test9.bas
test10.bas
test11.bas
test12.bas
test13.bas
test14.bas
test15.bas
test16.bas
test17.bas
test18.bas
test19.bas
test20.bas
test21.bas
test22.bas -
файлы примеров, которые могут выполняться в консольном
приложении ob180_*.exe
Файлы исходных текстов
консольного приложения
.\example
ob.cpp -
main() тестового примера ob180_*.exe, пользовательские
функции, примеры их подключения. Использует библиотеку ob180_bcb60.lib
comline.cpp -
функции для разбора командной строки
comline.h -
функции для разбора командной строки
.\example_dll
ob.c -
main() тестового примера ob180_*.exe, пользовательские
функции, примеры их подключения. Использует ob180_bcb60_single_thread.dll
comline.c -
функции для разбора командной строки
comline.h -
функции для разбора командной строки
Пример
использования Open Basic
в виде консольного приложения
.\exe
ob180_bcb60.exe
- консольное приложение
Open Basic Borland C++ Builder v6.0
Принимает в
качестве параметра имя текстового файла с *.bas
программой и выполняет его.
При запуске с ключем -? печатает
список своих ключей.
ob180_msvc.exe -
консольное приложение Open Basic MSVS v7.0
ob180_linux -
консольное приложение Open Basic GCC v3.2.2 для Linux i386
.\exe_dll
ob180_bcb60_with_dll.exe - консольное приложение Open Basic
Borland C++ Builder v6.0
Принимает в качестве параметра имя
текстового файла с *.bas
программой и выполняет
его. При запуске с ключем -? печатает
список своих
ключей. Использует ob180_bcb60_single_thread.dll
.\dll
ob180_bcb60_single_thread.dll
ob180_bcb60_single_thread.lib
ob180_bcb60_single_thread.def – DLL, библиотека импорта и таблица экспортируемых функций для
однопотоковой версии DLL
ob180_bcb60_multi_thread.dll
ob180_bcb60_multi_thread.lib
ob180_bcb60_multi_thread.def – DLL, библиотека импорта и таблица экспортируемых функций для
многопотоковой версии DLL
Файлы описаний
.\htm
read_rus.htm
- файл с текстом данного
описания на русском языке
read_eng.htm
- файл с текстом данного
описания на английском языке
shortrus.htm
- файл с текстом краткого
справочника по методам и
перечислениям класса
ob_obasic на русском языке
shorteng.htm
- файл с текстом краткого
справочника по методам и
перечислениям класса
ob_obasic на английском языке
.\htm_dll
read_rus_dll.htm
- файл с текстом описания
применения Open Basic в виде DLL на русском
языке
Заголовочные файлы
.\include
mstore.h -
стратегии хранения данных
mvect.h -
вектор
mlist.h -
список
mstack.h -
стек
mhash.h -
хеш-таблица
ob.h -
основной заголовочный файл Open Basic
Файлы библиотек
.\lib
ob180_bcb60.lib - библиотека Open Basic для Borland C++ Builder v6.0
ob180_msvc_single_thread.lib - библиотека Open Basic
для
MSVC v7.0
ob180_msvc_multi_thread.lib - библиотека Open Basic
для
MSVC v7.0
libob180.a - библиотека Open Basic для GCC v3.2.2 для Linux i386
.\source_dll
obd.cpp
- реализация DLL
obd.h -
реализация DLL
Содержание
Список версий и исправленных ошибок
1. Описание задачи и назначение программы
3.1. Общие сведения. Как использовать интерпретатор. Как загрузить и запустить *.bas программу.
3.2. Обзор технических решений
3.4.4. Функция ob_loadbreakstr
3.4.5. Перечисление ob_operator::flbreak
3.4.7. Метод getcurrentoperatorname
3.4.9. Перечисление ob_lex::typelex
3.4.10. Методы gettypenextlex и restoreinputpointer
3.5. Синтаксис языка Open Basic. Общие сведения
3.6. Типы данных, имена и метки Open Basic
3.7. Пользовательские функции в Open Basic.
3.7.1. Тип возвращаемого значения для пользовательской функции
3.7.2. Прототипы для пользовательской функции
3.7.3. Выбор Basic-имени пользовательской функции
3.7.4. Подключение пользовательской функции к исполняющей системе OB
3.8. Методы и перечисления класса ob_obasic для подключения и отключения пользовательских функций
3.8.1. Перечисление ob_type_del
3.9. Назначение параметров пользовательских функций
3.9.2. Параметры пользовательских функций
3.10. Доступ из пользовательской функции к данным *.bas программы.
3.11.1. Методы и перечисления класса ob_obasic для определения типа переменных и массивов Open Basic
3.11.1.1. Перечисление ob_type_ident
3.11.3. Методы класса ob_obasic для определения размеров массивов Open Basic
3.11.4. Методы класса ob_obasic для записи переменных Open Basic
3.11.5. Методы класса ob_obasic для чтения переменных Open Basic
3.11.6. Методы класса ob_obasic для создания и удаления переменных и массивов Open Basic
3.11.6.1. Методы класса ob_obasic для создания переменных Open Basic
3.11.6.2. Методы класса ob_obasic для создания массивов Open Basic
3.11.6.3. Методы класса ob_obasic для удаления переменных и массивов Open Basic
3.12. Описание других методов класса ob_obasic
3.13.5. Операторы GOSUB и RETURN
3.13.10. Операторы OPEN и CLOSE
3.13.12. Операторы READ, DATA и RESTORE
3.14.4. Функции SIN, COS, ATN, SQR, EXP, LOG и LOG10
3.14.8. Функции D2STR$, D2HEXSTR$, STR2FLOAT и STR2INT%
3.16. Таблица диагностических сообщений
Часто в пользовательских приложениях возникает
необходимость в применении
простого
скриптового языка. Такая задача возникает, если приложение оперирует
некоторым
количеством примитивов, которые должны вызываться в разной
последовательности
для разных режимов работы.
Например:
- запросы к базе данных с разными условиями
выборки данных
- тестирование оборудования и/или программного
обеспечения
- организация связи с нестандартным
оборудованием по различным каналам
- построение графических интерфейсов и
манипуляции с объектами GUI
- входной язык в программах-терминалах для разбора командной строки
- входной язык оператора-технолога в задачах
АСУТП
- входной язык сложных конфигурационных файлов
- и многое другое
Графический интерфейс пользователя затрудняет
возможность автоматизации
задач.
Поэтому часто необходимо дополнить графический интерфейс возможностями,
которые
предоставляет скриптовой язык.
Интерпретатор Open Basic разработан для
встраивания в приложения пользователя
в
качестве скриптового языка.
Open Basic поставляется в виде библиотеки или
исходных текстов.
OB имеет возможность расширения системы команд
путем подключения
пользовательских
функций к исполняющей системе Open Basic.
Пользовательские функции могут быть написаны
на C/C++, ассемблере или других
языках.
Пользовательские функции могут вызываться из Basic-программы, получать
параметры
разных типов из Basic-программы и возвращать результаты своей работы
в
Basic-программу.
Также пользовательские функции имеют доступ ко
всем переменным и массивам
Basic-программы,
а не только передаваемым через параметры. Этот доступ
осуществляется
по именам переменных и массивов.
Пакет Open Basic написан полностью на C++ и не
использует системные вызовы
какой-либо
ОС. Пакет Open Basic может использоваться совместно с любой
графической
библиотекой.
Интерпретатор Open Basic реализован в виде
класса с именем ob_obasic.
Работа интерпретатора состоит в выполнении
программы на языке Basic.
В данном
описании эта программа называется *.bas-программой. Программа *.bas
является
текстовым файлом или буфером в памяти, открытом как поток istream.
Далее в описании:
1. "оператор" - означает оператор
языка Basic. Например PRINT, FOR и т.д.
2. "пользовательская функция" - означает пользовательскую функцию,
присоединенную к исполняющей системе Open
Basic
3. "функция" - означает функцию С++
4. "метод" - означает метод класса ob_obasic.
5. "*.bas-программа" - программа на
языке Basic
Чтобы использовать интерпретатор нужно:
1. скачать со страницы
http://www.mktmk.narod.ru архив, содержащий:
- библиотеку интерпретатора для Вашего
транслятора
- заголовочный файл ob.h
- заголовочные файлы с реализацией
шаблонных контейнеров
(mstore.h,mvect.h,mlist.h,mstack.h,mhash.h)
2. включить в проект библиотеку интерпретатора
3. указать путь для подключения заголовочного
файла интерпретатора ob.h
4. указать путь для подключения заголовочных файлов
шаблонных контейнеров
(mstore.h,mvect.h,mlist.h,mstack.h,mhash.h)
5. включить в свои C++ файлы директивой
#include заголовочный файл
интерпретатора ob.h
6. создать экземпляр класса ob_obasic в своей
C++ программе
7. передать ему программу для выполнения
(загрузить *.bas программу)
в конструкторе класса или с помощью метода
load
8. запустить программу на выполнение с помощью
метода run
Пример:
//Создание
интерпретатора и запуск программы. Программа *.bas хранится
//в
файле prog.bas
//перед
началом работы файл prog.bas открывается для чтения
//как
поток inp
ifstream
inp("prog.bas",ios::binary); //открытие входного потока
ob_obasic
basic_interpreter(&inp);//загрузка *.bas программы в конструкторе
basic_interpreter.run();//запуск *.bas-программы
ВНИМАНИЕ!
Входной поток должен быть открыт в ios::binary режиме.
ПОЯСНЕНИЕ:
Несмотря на то, что *.bas-программа является
текстовым файлом, открываться как
поток она
должна в ios::binary режиме. Это связано с особенностями обработки
символов
возврата каретки и перевода строки в ios::text режиме.
Пример:
//после
окончания программы prog.bas загрузка и запуск программы
//prog1.bas
ifstream
inp1("prog1.bas",ios::binary);//открытие входного потока
basic_interpreter.load(&inp1);//загрузка
*.bas программы с помощью метода load
basic_interpreter.run();//запуск *.bas-программы
ВНИМАНИЕ!
Входной поток должен быть открыт в ios::binary режиме.
Пример:
//после
окончания программы prog1.bas загрузка и запуск программы
//prog2.bas
ifstream
inp2("prog2.bas",ios::binary);//открытие входного потока
basic_interpreter.load(&inp2,ob_obasic::OVERLAY);//загрузка *.bas программы
//с
помощью метода load в режиме OVERLAY
basic_interpreter.run();//запуск *.bas-программы
ВНИМАНИЕ!
Входной поток должен быть открыт в ios::binary режиме.
При
проектировании интерпретатора решались следующие основные проблемы:
1. Возможность хранения Basic-программы в файле на диске или в
буфере памяти. Для обеспечения этой возможности интерпретатор принимает входную
программу в виде указателя на поток ввода istream*. Конкретный вид потока (файл или
буфер) определяется пользователем. Аналогично входной поток оператора INPUT и выходной поток оператора PRINT тоже могут быть буферами или
файлами.
2. Для обеспечения гибкости
функционирования применяется разделение выполнения программы на два этапа.
Первый этап это загрузка программы методом load. Второй этап это выполнение
программы методом run.
В процессе загрузки происходит создание таблицы меток переходов и подпрограмм и
настройка внутренних переменных. В процессе выполнения производится чтение
текста программы и выполнение действий (создание переменных, массивов,
вычисление и присвоение значений переменным, выполнение операторов и функций и
т.д.). Окончание метода run происходит по нескольким причинам:
-
Исчерпание
входного потока
-
Синтаксическая
ошибка в программе
-
Символ
точки останова
-
Символ
конца строки при установленном флаге пошагового режима работы
При окончании метод run возвращает код окончания. Анализируя этот код пользователь может
узнать причину окончания метода.
Разделение выполнения программы на два этапа позволяет продолжить
метод run
после окончания без повторной загрузки программы.
3. Один экземпляр интерпретатора может
выполнять одну программу в данный момент времени. В программе может быть
несколько экземпляров интерпретатора. Интерпретатор не имеет статических членов
данных (кроме доступных по чтению констант). Поэтому несколько экземпляров
интерпретатора могут работать одновременно в разных нитях программы.
4. Вследствии того, что язык C++ не позволяет передавать
информацию с этапа трансляции на этап выполнения программы, пользовательские функции
в Open Basic
имеют унифицированный интерфейс. Этот интерфейс позволяет проанализировать типы
и порядок следования параметров в вызове пользовательской функции на этапе
выполнения программы. Этот подход требует от программиста аккуратности, но зато
не ограничивает возможности создания пользовательских функций с разными
параметрами.
ob_obasic(istream* i=OB_NULL,ostream*
o=&cout,istream* read=&cin);
создает
экземпляр интерпретатора Open Basic.
Параметры
конструктора:
1. Параметр i - указатель на входной поток, из
которого считывается
*.bas-программа.
Указатель потока должен указывать на начало программы.
После окончании работы
интерпретатора
указатель потока указывает на конец программы. Чтобы повторно
запустить
ту же программу, нужно переставить указатель потока на начало и
перезагрузить
программу методом load.
ВНИМАНИЕ!
Входной поток должен быть открыт в ios::binary режиме.
ПОЯСНЕНИЕ:
Несмотря на то, что *.bas-программа является
текстовым файлом, открываться как
поток
она должна в ios::binary режиме. Это связано с особенностями обработки
символов
возврата каретки и перевода строки в ios::text режиме.
2. Параметр o - указатель на выходной поток, в
который выводятся данные
оператором
PRINT.
ВНИМАНИЕ!
Выходной поток должен быть открыт в ios::text режиме.
ПОЯСНЕНИЕ:
Выходной поток является обычным текстовым
потоком в который выводятся
текстовые
данные.
3. Параметр read - указатель на входной поток,
из которого считываются
данные
оператором INPUT.
ВНИМАНИЕ!
Этот поток должен быть открыт в ios::binary режиме.
Перечисление enum typeload{OVERLAY,NOOVERLAY};
- определяет режим загрузки
*.bas
программы. Используется в методе load.
ПОЯСНЕНИЕ:
В процессе работы интерпретатор создает
таблицы:
1. таблица переменных
2. таблица массивов
3. таблица пользовательских функций
4. таблица (поток) данных оператора DATA
5. таблица меток
6. таблица циклов операторов FOR
7. таблица открытых файлов
8. таблица (стек) подпрограмм GOSUB
При typeload=OVERLAY происходит очистка:
1. таблиц меток
2. таблицы циклов операторов FOR
3. таблицы (стека) подпрограмм GOSUB
Остальные таблицы:
1. таблица переменных
2. таблица массивов
3. таблица пользовательских функций
4. таблица (поток) данных оператора DATA
5. таблица открытых файлов
не очищаются и могут использоваться вновь
загруженной программой.
При typeload=NOOVERLAY происходит очистка всех
таблиц, кроме таблицы
пользовательских
функций.
Таблица пользовательских функций очищается
только при вызове метода
void clrtablfun();
Метод void
load(istream* i,typeload a=ob_obasic::NOOVERLAY);
загружает
*.bas-программу.
Параметры
метода:
1. Первый параметр метода это указатель на
поток, в котором содержится
*.bas-программа.
ВНИМАНИЕ!
Этот поток должен быть открыт в ios::binary режиме.
Внутренний
указатель на данные в потоке должен указывать на начало программы.
После
окончания работы интерпретатора внутренний указатель указывает на
конец
программы. Чтобы повторно запустить ту же программу, нужно переставить
внутренний
указатель методом seekg и перезагрузить программу методом load.
Перечисление
enum typeend{
DUMMYEND,ENDFILEEND,ENDOPERATORDETECT,EOLEND,BREAKPOINTEND,NOLOADEND,
BREAKBEFOREOPERATOR,BREAKAFTEROPERATOR
};
определяет код завершения метода
run.
Коды завершения:
1. typeend=DUMMYEND - при нормальной работе
никогда не возвращается методом
run. Используется для внутренних переходов.
2. typeend=ENDFILEEND метод run окончился
из-за исчерпания входного потока.
Это нормальное завершение *.bas-программы
3. typeend=ENDOPERATORDETECT метод run
окончился при обнаружении оператора
END. Это нормальное завершение
*.bas-программы
4. typeend=EOLEND метод run окончился после
исполнения очередной строки, т.к.
был установлен флаг step=STEP методом
setstep
5. typeend=BREAKPOINTEND метод run окончился
после считывания символа '@',
который является символом точки останова
для Open Basic
6. typeend=NOLOADEND метод run окончился т.к. не
был выполнен метод load и
входной поток не открыт
7. typeend=BREAKBEFOREOPERATOR - метод run
окончился перед выполнением
какого-то оператора OB
Пояснение:
В OB для каждого оператора (PRINT, FOR и т.д.)
имеется возможность установить
режим
завершения метода run до или после выполнения этого оператора. Режим
завершения
устанавливается с помощью метода:
bool setoperatorbreak(char* name,ob_operator::flbreak b,ob_operator::flbreak a);
Такая возможность сделана для облегчения
реализации операторов ввода и вывода
PRINT и
INPUT в конкретной ОС. Если перед выводом в поток необходимо выполнить
некоторые
действия (например очистить выходной поток), нужно установить режим
завершения
метода run до выполнения оператора PRINT.
Подробнее см. описание метода
setoperatorbreak.
8. typeend=BREAKAFTEROPERATOR - метод run
окончился после выполнения какого-то
оператора OB
Пояснение:
Если после вывода в поток необходимо выполнить
некоторые действия (например
передать
выведенные оператором PRINT данные оконной системе), нужно установить
режим
завершения метода run после выполнения оператора PRINT.
По умолчанию режим завершения до и после
выполнения всех операторов запрещен.
Метод typeend run(); - запускает загруженную программу.
Или продолжает
выполнение
после останова с кодом завершения.
В OB есть два режима отладки: пошаговое
выполнение *.bas-программ и назначение
точек
останова.
Возможность пошагового выполнения
*.bas-программ реализована с помощью метода
setstep.
Символ '@' отдельной строке в тексте
*.bas-программы реализует точку останова.
Точек
останова в *.bas-программе может быть несколько. После внесения точек
останова
*.bas-программу нужно перезагрузить методом load.
При передаче управления на строку с символом
'@' произойдет останов программы.
Код
завершения метода run будет BREAKPOINTEND. Для продолжения программы нужно
снова
запустить метод run();
Перечисление enum step{NOSTEP,STEP}; -
определяет режим пошагового выполнения
программы.
Используется в методах setstep и getstep. По умолчанию step=NOSTEP.
При step=NOSTEP программа выполняется
непрерывно.
При step=STEP программа завершается с кодом
typeend=EOLEND после выполнения
каждой
строки программы.
Метод
void
setstep(step ts) - устанавливает или снимает режим пошагового выполнения
программы.
Этот метод можно использовать в любой момент работы интерпретатора.
При
установки пошагового режима метод run(); будет завершаться после выполнения
каждой
строки *.bas программы. Для продолжения программы нужно снова запустить
метод
run();
Метод
step
getstep() - возвращает текущий режим режим пошагового выполнения
программы.
Функция
void ob_loadbreakstr(
istream* in,
ob_type_stringsize lengthbuffers,
ob_type_char* ptrbefore,
ob_type_char* ptrcurrent,
ob_type_char* ptrafter
);
где:
istream*
in - текущий входной исполняемый
*.bas-файл
lengthbuffers - длина буферов
ptrbefore - буфер для строки, предшествующей
текущей исполняемой
ptrcurrent - буфер для текущей исполняемой строки
ptrafter - буфер для строки, следующей за текущей
исполняемой
Функция ob_loadbreakstr загружает в указанные
буфера соответствующие строки
выполняемой
программы.
Функция ob_loadbreakstr не является методом
класса ob_obasic.
Пример:
//Создание
интерпретатора и запуск программы в пошаговом режиме.
//с
печатью выполняемых строк
ob_type_char strcurrent[ob_maxlengthstring];//буфер
ob_obasic
basic_interpreter;//Создание интерпретатора
//загрузка
и запуск программы
//prog2.bas
//в
режиме OVERLAY с пошаговым выполнением программы
//и с
печатью выполняемых строк
ifstream
inp2("prog2.bas",ios::binary);//открытие входного потока
basic_interpreter.load(&inp2);//загрузка *.bas-программы
basic_interpreter.setstep(ob_obasic::STEP);//установка пошагового режима
while(1){
if(basic_interpreter.run()!=ob_obasic::EOLEND)
break;//запуск
*.bas-программы
ob_loadbreakstr(&inp2,ob_maxlengthstring,OB_NULL,strcurrent,OB_NULL);
cout<<endl<<"String current:
"<<strcurrent;
}
Функция
ob_loadbreakstr не является методом класса ob_obasic.
Перечисление
enum flbreak{NOBREAK,BREAK};
используется
в методе setoperatorbreak для установки и снятия режима завершения
до или
после выполнения указанного оператора.
В OB для каждого оператора (PRINT, FOR и т.д.)
имеется возможность установить
режим
завершения метода run до или после выполнения этого оператора. Режим
завершения
устанавливается с помощью метода:
bool setoperatorbreak(char* name,ob_operator::flbreak b,ob_operator::flbreak a);
Параметры:
1. name - имя оператора
2. flbreak b - флаг завершения метода run до
выполнения этого оператора
3. flbreak a - флаг завершения метода run
после выполнения этого оператора
возвращаемое
значение:
true - успешное завершение
false -
если ошибка задания имени оператора
Такая возможность сделана для облегчения
реализации операторов ввода и вывода
PRINT и
INPUT в конкретной ОС.
Если перед выводом в поток необходимо
выполнить некоторые действия (например
очистить
выходной поток), нужно установить режим завершения метода run до
выполнения
оператора PRINT.
Если после вывода в поток необходимо выполнить
некоторые действия (например
передать
выведенные оператором PRINT данные оконной системе), нужно установить
режим
завершения метода run после выполнения оператора PRINT.
По умолчанию режим завершения до и после
выполнения всех операторов запрещен.
Метод
позволяет узнать, какой именно оператор вызвал завершение при завершении
с кодами:
BREAKBEFOREOPERATOR или
BREAKAFTEROPERATOR.
ob_type_char* getcurrentoperatorname();
Метод возвращает имя оператора.
Методы позволяют переопределить входной и
выходной потоки, ранее определенные
в конструкторе.
void setin(istream* i);
void setout(ostream* o);
ВНИМАНИЕ!
Входной поток должен
быть открыт в ios::binary режиме.
ВНИМАНИЕ!
Выходной поток должен быть открыт в ios::text режиме.
Метод setin переопределяет поток “read” конструктора.
Метод setout переопределяет поток “o” конструктора.
Перечисление определяет текущую лексему.
enum typelex{
PLUS,MINUS,MUL,DIV,POWER,ASSIGN,LP,RP,STRING,SEMICOLON,COMMA,ENDPROGRAMM,EOL,
LESS,GREAT,SHARP,BREAKPOINT,
DECINTNUMBER,HEXINTNUMBER,FLOATNUMBER,
FUNC,OPERATOR,
OLDVARIABLE,OLDARRAY,NEWNAME,
BAD
};
Методы
предназначены для облегчения реализации операторов ввода и вывода.
- ob_lex::typelex gettypenextlex();
- void
restoreinputpointer();
Метод
ob_lex::typelex gettypenextlex();
Возвращает
следующую лексему из входного потока. Некоторые операторы (например
оператор
INPUT) имеют одинаковый синтаксис для ввода из файла и с консоли.
Текущее
направление ввода определяется следующей лексемой #. С помощью метода
gettypenextlex()
можно выяснить тип следующей лексемы после останова с кодом
завершения
BREAKBEFOREOPERATOR. И таким образом можно выяснить, откуда
ожидается ввод.
Метод
void
restoreinputpointer();
Предназначен
для восстановления состояния входного потока после применения
метода
gettypenextlex().
ВНИМАНИЕ!
Все объекты в *.bas-программе: переменные, массивы, и
пользовательские функции должны иметь
различные имена.
Интерпретатор Open Basic поддерживает
подмножество операторов языка Basic.
Эти
операторы описаны ниже. Имеется возможность работать с тремя типами данных:
с
плавающей точкой, целыми и строками. Имеется возможность работать с массивами
из этих
трех типов.
Переменные в Open Basic не нужно описывать
перед первым использованием.
Первое
появление переменной в программе должно быть слева от оператора
присвоения.
Массивы в Open Basic нужно описывать до
первого использования оператором DIM.
Массивы
могут быть многомерными. Данные для массивов и переменных располагаются
в
свободной памяти оператором new. Общий размер массива зависит от ограничений
на
оператор new в конкретной ОС.
В Open Basic индекс массива начинается с
единицы.
В отличие от стандартного языка Basic оператор
DIM в Open Basic является
исполняемым.
Он выполняется каждый раз, когда на него передается управление.
Допускается повторное описание массива с тем
же именем в операторе DIM.
Новый
массив может иметь другие размерности. Старые данные при этом теряются.
Этот
механизм можно применять для освобождения памяти. После захвата большого
массива
оператором DIM можно освободить память, описав массив с тем же именем
и
размерностью в один элемент.
При описании массива в операторе DIM в
качестве размерностей могут
использоваться
целые переменные.
При создании числовые массивы инициализируются
нулем. Строковые массивы
инициализируются
пустой строкой ("").
Диапазон представления данных с плавающей
точкой и целых зависит от того, как
транслируется
пакет. Обычно целые это int, а плавающие это float.
Максимальная длина строковых переменных
определяется константой
ob_maxlengthstring
в файле ob.h. Для версии OB v1.80 ob_maxlengthstring=4096.
В *.bas-программе могут быть пустые строки.
Интерпретатор Open Basic поддерживает
следующие операции над целыми данными и
данными
с плавающей точкой:
+ - сложение
- - вычитание
* - умножение
/ - деление
^ - возведение в степень
- - унарный минус
+ - унарный плюс
= - присвоение
<, >, =, <>, <=, >= - выражения
отношения 'меньше', "больше", "равно",
"не равно", "меньше или
равно", "больше или равно". Выражения отношения
используются в операторе IF.
Как и в стандартном языке Basic тип переменной
или массива в Open Basic
определяется
по имени. А именно:
- если в имени последним символом является
символ '%', то это переменная
или массив целого типа.
- если в имени последним символом является
символ '$', то это переменная
или массив строкового типа.
- если в имени последним символом является
любой другой символ, то это
переменная или массив с плавающей точкой
Многие типы Open Basic описаны в ob.h с
помощью typedef.
Тип
ob_type_flo отображается в тип float с помощью typedef.
Тип
ob_type_int отображается в тип int с
помощью typedef.
В
пользовательских функциях рекомендуется использовать типы ob_type_flo и
ob_type_int. При смене, например, ob_type_flo
с float на double будет
обеспечена
совместимость типов.
В качестве имен переменных, массивов и пользовательских
функций можно
использовать
любые последовательности букв и цифр. Имена должны начинаться с
буквы.
Буквы в имени могут быть прописные или
строчные. Символы подчеркивания и
символы
'$' и '%' считаются буквами.
Приведения букв к одному регистру не
производится. Имена MASS, mass и Mass
являются
разными именами.
Максимальная длина имени определяется
константой ob_maxlengthstring в файле
ob.h. Для версии
Пример:
Объявление массива и инициализация двух переменных
- целой и с плавающей
точкой.
Последнее измерение массива задано переменной. Тип элементов массива
mass -
с плавающей точкой. Переменная counter% имеет целый тип. Переменная data
имеет
тип с плавающей точкой.
counter%=7
DIM
mass(2,3,10,counter%)
data=counter%+37.77
Пример:
Объявление
массива и использование его. Повторное объявление
массива
с тем же именем, но другой размерностью и использование его.
DIM mass(10)
FOR i%=1
TO 10 STEP 1
mass(i%)=i%+37.77
NEXT i%
counter%=7
DIM
mass(counter%,3)
FOR i%=1
TO counter% STEP 1
mass(i%,2)=i%+37.77
NEXT i%
Для строковых данных поддерживаются
только операции сложения строк, их
сравнения
и присвоения.
Если в выражении используются данные разных
типов, то производится
приведение
типов.
Если в выражении используется целые данные и
данные с плавающей точкой,
результирующий
тип будет с плавающей точкой.
При присвоении тип правого выражения
приводится к типу выражения слева от
знака
присвоения =.
Если слева от знака присвоения целая
переменная, а справа с плавающей точкой,
то
дробная часть отбрасывается.
Интерпретатор Open Basic поддерживает метки в
виде номеров строк. Эти номера
не
обязательно должны идти подряд. Не каждая строка программы должна быть
пронумерована.
Осуществить переход операторами GOTO и GOSUB можно только на
пронумерованную
строку. Можно поставить метку и у пустой строки.
Пример:
IF ii%=6 THEN
GOTO 10
PRINT
"ii%=";ii%;
10 PRINT "ii%!=6"
IF ik%=7 THEN
GOSUB 11
PRINT
"ik%=";ik%;
GOTO 12
11
PRINT
"ik%!=7"
RETURN
12
STOP
END
Начиная с версии 1.80 в *.bas программе кроме меток в виде чисел
(номеров строк) поддерживаются строковые метки с финальным двоеточием.
Двоеточие является частью идентификатора метки и должно следовать за
идентификатором метки без разделителя. В операторах GOTO и GOSUB идентификатор
строковой метки пишется без финального двоеточия. В программе могут
одновременно применяться метки в виде чисел (номеров строк) и строковые метки.
Пример:
REM Test
string label
PRINT
PRINT
"Start--------------------------------"
loop_counter%=10
FOR i%=1 TO
loop_counter%
PRINT
"-------------------------------- ";"pass=";i%
GOSUB
gosub_label_1
GOSUB
gosub_label_2
GOSUB
gosub_label_3
GOSUB
gosub_label_4
NEXT i%
PRINT
"End program OK"
10
STOP
END
gosub_label_1:
PRINT
"gosub_label_1"
a%=i%/2*2
IF a%=i% THEN
GOTO goto_label_1
PRINT "do
not goto detect"
ENDIF
goto_label_1:
RETURN
gosub_label_2:
PRINT "gosub_label_2"
a%=i%/2*2
IF a%=i% THEN GOTO goto_label_2
PRINT "do not goto detect"
ENDIF
goto_label_2:RETURN
gosub_label_3:
PRINT
"gosub_label_3"
RETURN
gosub_label_4:
PRINT
"gosub_label_4"
RETURN
OB имеет возможность расширения системы команд
путем подключения
пользовательских
функций к исполняющей системе Open Basic.
Параметры пользовательских функций позволяют
определить тип и порядок
следования
аргументов в вызове во время исполнения программы.
Пользовательские функции подключаются к
исполняющей системе Open Basic под
некоторыми
именами (Basic-именами). Каждая пользовательская функция
подключается
под своим Basic-именем. После подключения их можно вызывать в
тексте
*.bas-программы по этим именам. Можно передавать им параметры и получать
от них
результаты. Можно вызывать пользовательские функции без параметров.
Пользовательские функции могут быть написаны
на C/C++, ассемблере или других
языках.
Все пользовательские функции имеют 2 имени:
1. С++ имя функции в составе проекта по
которому пользовательскую функцию
можно вызывать из С++ программы.
2. Basic-имя функции, по которому
пользовательскую функцию можно вызывать из
*.bas-программы.
Первое имя пользовательские функции получают
при их написании. Второе имя
пользовательские
функции получают на этапе подключения к исполняющей системе
Open
Basic с помощью метода setfun.
Чтобы создать пользовательскую функцию и
подключить ее к исполняющей системе
Open
Basic необходимо:
1. Выбрать тип возвращаемого значения для
пользовательской функции
2. Выбрать C++ имя пользовательской функции и
написать пользовательскую
функцию по одному из трех прототипов
3. Выбрать Basic-имя пользовательской функции
4. Подключить пользовательскую функцию к
исполняющей системе OB с помощью
метода setfun используя Basic-имя и C++ имя
в качестве параметров
После этого можно использовать Basic-имя пользовательской
функции в *.bas
программе.
Пользовательская функция может возвращать
значения трех типов:
- с плавающей точкой ob_type_flo
- целое ob_type_int
- строковое
ob_type_char*
Пользовательская функция может иметь один из
трех прототипов:
1. Функции, возвращающие значение с плавающей
точкой
ob_type_flo name_flo(
ob_obasic* basic_ptr,
const ob_type_char* parstring,
const ob_type_parnum *descrf,
const ob_type_parnum *descri,
const ob_type_parnum *descrc,
const ob_type_flo* parf,
const ob_type_int* pari,
const ob_type_char* parc
);
2. Функции, возвращающие целое
значение
ob_type_int name_int(
ob_obasic* basic_ptr,
const ob_type_char* parstring,
const ob_type_parnum *descrf,
const ob_type_parnum *descri,
const ob_type_parnum *descrc,
const ob_type_flo* parf,
const ob_type_int* pari,
const ob_type_char* parc
);
3. Функции, возвращающие строку
ob_type_char* name_char(
ob_obasic* basic_ptr,
const ob_type_char* parstring,
const ob_type_parnum *descrf,
const ob_type_parnum *descri,
const ob_type_parnum *descrc,
const ob_type_flo* parf,
const ob_type_int* pari,
const ob_type_char* parc
);
Эти прототипы различаются только
типом возвращаемого значения.
В файле ob.h содержится макрос
OB_DECLARE_USER_FUNCTION(name,typeret), который можно
использовать
для объявления пользовательских функций. Параметр name - это имя
функции
в C++, параметр typeret - это тип возвращаемого значения.
Пример:
Объявление
пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.
C++ имя
пользовательской функции "myfun1".
Тип
возвращаемого значения - ob_type_flo.
OB_DECLARE_USER_FUNCTION(myfun1,ob_type_flo);
Пример:
Определение
пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.
C++ имя
пользовательской функции "myfun2".
Тип
возвращаемого значения - ob_type_int.
OB_DECLARE_USER_FUNCTION(myfun2,ob_type_int){
return
365;
}
Пример:
Определение
пользовательской функции с помощью макроса OB_DECLARE_USER_FUNCTION.
C++ имя
пользовательской функции "myfun3".
Тип
возвращаемого значения - ob_type_char*.
OB_DECLARE_USER_FUNCTION(myfun3,ob_type_char*){
return "Hello world";
}
Basic-имя пользовательской функции должно
отличаться от имен переменных,
массивов
и других пользовательских функций *.bas-программы.
Подключение пользовательской функции к
исполняющей системе OB производится с
помощью методов setfun.
bool setfun(ob_type_char* name,ob_type_flofun f);
bool setfun(ob_type_char* name,ob_type_intfun f);
bool setfun(ob_type_char* name,ob_type_charfun f,ob_type_del
dt);
Параметры:
1. name - Basic-имя пользовательской функции
2. f
- указатель на пользовательскую функцию
3. dt
- тип размещения размещения в памяти возвращаемого значения (только
для функций, возвращающих строку)
Пример:
//подключается
функция userfun1
//эта
функция возвращает значение с плавающей точкой
//эта
функция печатает сообщение "hello world" и возвращает значение 3.1416
//при
подключении она получает Basic-имя "TEST_FUN1"
//то
есть в *.bas-программах ее можно вызывать по имени "TEST_FUN1"
OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){
cout<<endl<<"hello world";
return 3.1416;
}
main(){
ob_obasic onebasic;//создается экземпляр интерпретатора
ifstream
inonebasicf("EXAMPLE.BAS",ios::binary);//открывается файл
EXAMPLE.BAS
onebasic.load(&inonebasicf);//файл
EXAMPLE.BAS загружается в интерпретатор
onebasic.setfun("TEST_FUN1",userfun1);//подключается функция TEST_FUN1
onebasic.run();//запуск *.bas-программы
}
Для
функции, возвращающей строковый тип есть отличие в порядке подключения.
Возможно
два варианта размещения в памяти возвращаемого значения:
- в куче оператором new[]
- в статической памяти
В первом случае пользовательская функция
подключается с параметром
dt=OB_DELETE.
После
окончания работы такой функции Open Basic освободит память оператором
delete[].
Пример:
В примере создается экземпляр интерпретатора,
открывается файл с именем
EXAMPLE.BAS
и загружается в интерпретатор. После этого к исполняющей системе
подключаются
четыре функции TEST_FUN1-TEST_FUN4.
Функция TEST_FUN1 печатает список своих
параметров с плавающей точкой и
возвращает
значение с плавающей точкой, равное сумме своих параметров с
плавающей
точкой.
Функция TEST_FUN2 печатает список своих целых
параметров и возвращает целое
значение
равное сумме своих целых параметров.
Функции TEST_FUN3 и TEST_FUN4 печатают свой
первый строковый параметр и
возвращают строку "This
is string".
При этом функция TEST_FUN4
располагает возвращаемое значение в статической
памяти,
а функция TEST_FUN3 в свободной памяти.
Все функции контролируют правильность типов
своих параметров. В случае
отсутствия
параметров нужного типа печатают сообщения.
#include <ob.h>
char* s="This is string";
OB_DECLARE_USER_FUNCTION(userfun1,ob_type_flo){
ob_type_flo summ=0;
ob_type_parnum i;
if(descrf[0]==0) cout<<endl<<"Not
float parameters";
for(i=0;i!=descrf[0];i++){
summ+=parf[i];
cout<<endl<<"parameters["<<i<<"]="<<parf[i];
}
return summ;
}
OB_DECLARE_USER_FUNCTION(userfun2,ob_type_int){
ob_type_int summ=0;
ob_type_parnum i;
if(descri[0]==0) cout<<endl<<"Not int
parameters";
for(i=0;i!=descri[0];i++){
summ+=pari[i];
cout<<endl<<"parameters["<<i<<"]="<<pari[i];
}
return summ;
}
OB_DECLARE_USER_FUNCTION(userfun3,char*){
if(descrc[0]==0) cout<<endl<<"Not
string parameters";
cout<<endl<<parc;
char* p=new char[strlen(s)+1];
strcpy(p,s);
return p;
}
OB_DECLARE_USER_FUNCTION(userfun4,char*){
if(descrc[0]==0) cout<<endl<<"Not
string parameters";
cout<<endl<<parc;
return s;
}
main(){
ob_obasic onebasic;//создается экземпляр интерпретатора
ifstream
inonebasicf("EXAMPLE.BAS",ios::binary);//открывается файл
EXAMPLE.BAS
onebasic.load(&inonebasicf);//файл
EXAMPLE.BAS загружается в интерпретатор
onebasic.setfun("TEST_FUN1",userfun1);//подключается функция TEST_FUN1
onebasic.setfun("TEST_FUN2",userfun2);//подключается функция TEST_FUN2
onebasic.setfun("TEST_FUN3",userfun3,OB_DELETE);//подключается
TEST_FUN3
onebasic.setfun("TEST_FUN4",userfun4,OB_NODELETE);//подключается
TEST_FUN4
onebasic.run();//запуск *.bas-программы
}
При обнаружении в тексте
*.bas-программы имени подключенной функции
исполняющая
система Open Basic производит следующие действия:
1. вычисляет все аргументы в текущем вызове
*.bas-программы
2. заполняет массивы descr*
3. заполняет массивы par*
4. заполняет указатель ob_obasic* basic_ptr
адресом текущего объекта Open Basic
5. заполняет строку parstring
6. передает управление пользовательской
функции
Пользовательская функция должна контролировать
типы, количество и порядок
следования
параметров в текущем вызове.
Перечисление enum ob_type_del{OB_DELETE,OB_NODELETE};
- определяет тип
размещения
в памяти возвращаемого пользовательской функцией значения.
Используется
в методе setfun чтобы подключить пользовательские функции,
возвращающие
тип ob_type_char*.
При dt=OB_DELETE возвращаемое значение
располагается в свободной памяти
оператором
new. После окончания пользовательской функции оно будет удалено
оператором
delete[].
При dt=OB_NODELETE возвращаемое значение не
будет удалено оператором delete[].
Методы
bool setfun(ob_type_char* name,ob_type_flofun f);
bool setfun(ob_type_char* name,ob_type_intfun f);
bool setfun(ob_type_char* name,ob_type_charfun
f,ob_type_del dt);
подключают
пользовательскую функцию к исполняющей системе Open Basic.
Параметры:
1. name - Basic-имя пользовательской функции
2. f
- указатель на пользовательскую функцию
3. dt
- тип размещения размещения в памяти возвращаемого значения (только
для функций, возвращающих строку)
Если
функция с именем name еще не
подключена к исполняющей системе Open Basic, метод подключает ее возвращает false.
Если
функция с именем name уже
подключена к исполняющей системе Open Basic, метод заменяет ее на новую и возвращает true.
Типы
ob_type_flofun, ob_type_intfun, ob_type_charfun это указатели на функции,
описанные
в ob.h. Они отличаются типом возвращаемого значения.
Метод
bool delfun(ob_type_char* name);
отключает
пользовательскую функцию от Open Basic.
Параметры:
1. name - Basic-имя пользовательской функции
Метод delfun возвращает значение true, если
функция успешно отключена и false
в
случае, если такой функции не существует.
Интерфейс пользовательских функций Open Basic
разработан для того, чтобы
обеспечить
возможность контроля фактических параметров в вызове на этапе
исполнения
программы.
Для этого набор параметров пользовательских
функций содержит две группы
массивов.
Первая группа это три массива описаний параметров
descrf, descri, descrc.
Эти
массивы содержат информацию о количестве и порядке следования фактических
параметров
в вызове пользовательской функции.
Вторая группа это три массива значений
параметров parf, pari, parc. Эти
массивы
содержат значения фактических параметров в вызове пользовательской
функции.
Назначение и структура массивов descr* и par*
подробнее описана в следующем
разделе.
Существуют три типа пользовательских функций.
Все они имеют одинаковые
параметры
и разный тип возвращаемого результата.
Рассмотрим параметры пользовательских функций
на примере Функции, возвращающей
значение
с плавающей точкой.
ob_type_flo name_flo(
ob_obasic* basic_ptr,
const ob_type_char* parstring,
const ob_type_parnum *descrf,
const ob_type_parnum *descri,
const ob_type_parnum *descrc,
const ob_type_flo* parf,
const ob_type_int* pari,
const ob_type_char* parc
);
Параметры:
1.
ob_obasic* basic_ptr - указатель на экземпляр интерпретатора ob_obasic, к
которому
подключена функция. Используется для доступа
к переменным программы с
помощью методов ob_obasic.
2.
const char* parstring - строковые представления параметров.
Пример:
если в качестве параметров функции USER_FUN1
в ее вызове указано
USER_FUN1(1.123,a_a%,1+2), то в массиве
parstring будут находиться следующие
строки: "1.123","a_a%","1+2".
Эти строки будут лежать подряд, каждая
строка будет заканчиваться нулевым
байтом.
3.
массивы описания параметров descr*:
const ob_type_parnum *descrf - для
параметров с плавающей точкой
const ob_type_parnum *descri - для целых
параметров
const ob_type_parnum *descrc - для строковых
параметров
это массивы, описывающие количество, типы и
местоположение всех параметров,
переданных пользовательской функции из
*.bas-программы. Используются для
контроля количества, типа и порядка
следования параметров в вызове
пользовательской функции.
Структура массива descrf(остальные -
аналогично):
descrf[0] - общее число параметров с
плавающей точкой в текущем вызове
Остальные элементы массива descrf(их количество равно descrf[0])
это порядковые номера параметров с плавающей
точкой в текущем вызове.
Порядковые номера считаются с 1.
Пример:
если в качестве параметров функции USER_FUN1
в ее
вызове указано USER_FUN1(1.123,a_a%,1+2), то
в массиве descrf будут находиться следующие
числа:
1,1
в массиве descri будут находиться следующие
числа:
2,2,3
в массиве descrc будут находиться следующие
числа:
0
Пример:
если в качестве параметров функции USER_FUN1
в ее
вызове указано
USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4),
то в массиве descrf будут
находиться следующие числа:
4,3,4,5,6
в массиве descri будут находиться следующие
числа:
0
в массиве descrc будут находиться следующие
числа:
2,1,2
4.
массивы значений параметров par*:
const ob_type_flo* parf - для параметров с плавающей точкой
const ob_type_int* pari - для целых параметров
const ob_type_char* parc - для строковых
параметров
это массивы, описывающие значения всех
параметров соответствующих типов,
переданных пользовательской функции в
текущем вызове из *.bas-программы.
Параметры лежат подряд, в массиве parc строки, как и в массиве parstring,
отделяются нулевыми байтами.
Пример:
([a_a%] - значение переменной с именем a_a%)
если в качестве параметров функции USER_FUN1
в ее
вызове указано USER_FUN1(1.123,a_a%,1+2), то
в массиве parf будут находиться следующие
числа:
1.123
в массиве pari будут находиться следующие
числа:
[a_a%],3
в массиве parc не будет значений
Пример:
если в качестве параметров функции USER_FUN1
в ее
вызове указано
USER_FUN1("str1","srt2"+"str3",1.1,1.2,1.3,1.4),
то в массиве parf будут находиться
следующие числа:
1.1,1.2,1.3,1.4
в массиве pari не будет значений
в массиве parc будут находиться следующие
строки:
"str1","srt2str3"
В файле ob.h содержится макрос OB_DECLARE_USER_FUNCTION(name,typeret),
который можно
использовать
для объявления пользовательских функций. Параметр name - это имя
функции
в C++, параметр typeret - это тип возвращаемого значения.
Максимальное число параметров определяется
константой ob_maxnumpar в файле
ob.h.
Для версии OB v1.80 ob_maxnumpar=64;.
Используя массивы описания порядка следования
параметров descr* и массивы
значений
параметров par* пользователь может организовать контроль типов и
порядка
следования параметров в текущем вызове пользовательской функции на
этапе
выполнения программы.
Анализ массивов descr* дает полную информацию
о типах, количестве и порядке
следования
параметров в текущем вызове пользовательской функции.
Пример:
В пользовательскую функцию, вычисляющую синус
передана в качестве параметра
строковая
переменная.
При этом массивы descrf, descri и descrc будут
содержать значения:
descrf[0]=0
descri[0]=0
descrc[0]=1
Анализируя
эту информацию, пользователь может совершить нужные ему действия,
например:
1. генерировать пользовательское исключение
2. подставить аргумент по умолчанию, например
0.
3. выполнить останов программы с печатью
предупреждения
4. попытаться преобразовать строку в число с
помощью atof
Для облегчения доступа к строковым данным Open
Basic предоставляет функцию
const ob_type_char*
ob_getstringparam(
const ob_type_parnum *descrc,
const ob_type_char* parc,
const ob_type_parnum i);
Параметры:
1. descrc - массив описания строковых
параметров
2. parc
- массив значений строковых параметров
3. i
- номер строки, переданной в параметрах (нумерация с нуля)
С помощью этой функции можно получить доступ к
i-й строке, записанной в
строковые
параметры или в имена пользовательской функции.
Если i больше, чем descrc[0], то функция
возвращает 0.
Если descrc[0] равно нулю, то функция
возвращает 0.
Функция
ob_getstringparam не является методом класса ob_obasic.
Кроме необходимости принять параметры из *.bas
программы и передать в нее
выходное
значение, пользовательская функция имеет доступ к переменным
*.bas-программы.
Если в *.bas-программе используется переменная
или массив, то пользовательская
функция
может считывать и записывать эту переменную и элементы массива.
Пользовательская
функция имеет средства проверки наличия переменной с заданным
именем
в программе. Пользовательская функция имеет средства создания переменных
с
заданным именем в таблице переменных *.bas-программы.
Эти возможности реализованы в Open Basic с
помощью методов, описанных в
следующем
разделе.
Методы этого раздела запускаются обычно в
пользовательских функциях, поэтому
в
примерах они запускаются с помощью указателя ob_obasic* basic_ptr. Такое имя во
всех
пользовательских
функциях имеет первый параметр пользовательской функции, если определять
пользовательские функции с помощью макроса OB_DECLARE_USER_FUNCTION.
В общем случае методы этого раздела могут
запускаются в любом месте C++
программы,
в которой используется интерпретатор. Например, после останова
*.bas-программы
с помощью точки останова, можно распечатать значения переменных
и
массивов. Можно перед началом работы программы создавать и инициализировать
некоторые
переменные.
Перечисление
enum ob_type_ident {OB_IDENTFLO,OB_IDENTINT,OB_IDENTSTR,OB_NOIDENT};
определяет
тип переменной или массива. Используется в методах
typevar
и typearray чтобы определить тип переменной и массива.
Если
ob_type_ident=OB_IDENTFLO переменная имеет тип с плавающей точкой.
Если ob_type_ident=OB_IDENTINT
переменная имеет целый тип.
Если
ob_type_ident=OB_IDENTSTR переменная имеет строковый тип.
Если
ob_type_ident=OB_NOIDENT переменная не обнаружена.
Метод
ob_type_ident typevar(ob_type_char* name); - возвращает тип переменной с
именем
name.
Параметры:
1. name - имя Basic-переменной
Метод
ob_type_ident typearray(ob_type_char* name); - возвращает тип массива с
именем
name.
Параметры:
1. name - имя Basic-массива (без скобок и индексов)
Пример:
Если есть *.bas программа
DIM array1%(10,10), array2$(10,10), array3(10,10)
a%=10
b$="string example"
c=101.4
после
выполнения этого участка кода в пользовательских функциях, подключенных
к
интерпретатору, применение этих методов даст следующие результаты:
ob_type_ident ident;
ident=basic_ptr->typevar("a%");//
ident имеет значение
OB_IDENTINT
ident=basic_ptr->typevar("b$");//
ident имеет значение
OB_IDENTSTR
ident=basic_ptr->typevar("c"); //
ident имеет значение
OB_IDENTFLO
ident=basic_ptr->typearray("array1%");//
ident имеет значение
OB_IDENTINT
ident=basic_ptr->typearray("array2$");//
ident имеет значение
OB_IDENTSTR
ident=basic_ptr->typearray("array3");
// ident имеет значение
OB_IDENTFLO
Где basic_ptr-первый параметр в
пользовательских функциях, указатель на экземпляр
интерпретатора.
В
примере *.bas-программы нет переменной с именем VAR и массива с именем ARR.
Поэтому
применение этих методов даст следующие результаты:
ident=basic_ptr->typevar("VAR");//
ident имеет значение OB_NOIDENT
ident=basic_ptr->typearray("ARR");//
ident имеет значение OB_NOIDENT
Метод
ob_type_ident
strlenvar(
ob_type_char* name,
ob_type_stringsize* len,
ob_type_arraysize* as=OB_NULL);
определяет
тип переменной и длину переменной или элемента массива с именем
name.
Параметры:
1. name - имя Basic-переменной или
Basic-массива
2. *len - для строковых переменных содержит
длину строки без завершающего
нуля. Для переменных с плавающей
точкой и целых содержит
sizeof(ob_type_float)
и
sizeof(ob_type_int) соответственно.
3. *as - индексы массива в случае если name имя
массива
Метод strlenvar можно вызывать для
Basic-переменных или элементов
Basic-массивов.
Для Basic-массивов есть 2 способа вызова
метода strlenvar.
1. С указанием текущих индексов в имени
(параметр as=OB_NULL)
2. С указанием текущих индексов в параметре
*as (параметр as!=OB_NULL)
Метод возвращает OB_NOIDENT в случае ошибки
задания имени, например если оно
начинается
не с буквы или является именем не описанного на момент использования
массива
или переменная не существует. При нормальном завершении метод
возвращает
тип переменной.
Параметр *len для строковых переменных
содержит длину строки без завершающего
нуля.
Параметр *len для переменных с плавающей точкой и целых содержит
sizeof(ob_type_float) и sizeof(ob_type_int) соответственно.
Пример:
Вызов метода strlenvar для элемента массива с указанием текущих
индексов
в имени
Если
есть *.bas программа:
DIM
array2$(10,10)
array2$(5,5)="array string example"
после
выполнения этого участка кода в пользовательских функциях, подключенных
к
интерпретатору, применение метода strlenvar даст следующие результаты:
ob_type_stringsize len;
ob_type_ident
ident;
ident=basic_ptr->strlenvar("array2$(5,5)",&len);//
ident==OB_IDENTSTR len==20
Пример:
Вызов метода strlenvar для элемента массива с указанием текущих
индексов
в параметре *as
Если
есть *.bas программа:
DIM
array2$(10,10)
array2$(5,5)="array string example"
после
выполнения этого участка кода в пользовательских функциях, подключенных
к
интерпретатору, применение метода strlenvar даст следующие результаты:
ob_type_stringsize len;
ob_type_ident
ident;
ob_type_arraysize as[]={5,5};
ident=basic_ptr->strlenvar("array2$",&len,as);//
ident==OB_IDENTSTR len==20
Пример:
Вызов метода strlenvar для переменных
Если
есть *.bas программа:
DIM array1%(10,10), array3(10,10)
a%=10
b$="string example"
c=101.4
после
выполнения этого участка кода в пользовательских функциях, подключенных
к
интерпретатору применение метода strlenvar даст следующие результаты:
ob_type_ident ident;
ob_type_stringsize len;
ident=basic_ptr->strlenvar("a%",&len);//
ident==OB_IDENTINT len==4
ident=basic_ptr->strlenvar("b$",&len);//
ident==OB_IDENTSTR len==14
ident=basic_ptr->strlenvar("c",&len);
// ident==OB_IDENTFLO len==4
Метод
const ob_type_arraysize* getarraysize(
ob_type_char* name,ob_type_arraydimension* kr); - возвращает
количество
измерений массива и размер каждого измерения.
Параметры:
1. name - имя массива.
2. *kr
- количество измерений массива. Он заполняется методом getarraysize.
Возвращаемый параметр - массив размеров каждого
измерения. Он создается при
описании
массива оператором DIM. Этот параметр представляет собой внутренний
буфер
Open Basic и должен только читаться.
Пример:
Массив описан оператором DIM
Array_1(10,11,12).
Применение метода
getarraysize.
const ob_type_arraysize *sr;
ob_type_arraydimension kr;
sr=basic_ptr->getarraysize("Array_1",&kr);
После
применения getarraysize kr=3, а указатель sr указывает на
массив
{10,11,12}.
Методы
bool
writevar(ob_type_char* name,ob_type_flo
val,ob_type_arraysize* as=OB_NULL);
bool
writevar(ob_type_char* name,ob_type_int
val,ob_type_arraysize* as=OB_NULL);
bool
writevar(ob_type_char* name,ob_type_char*
val,ob_type_arraysize* as=OB_NULL);
Параметры:
1. name - имя Basic-переменной или
Basic-массива
2. val - значения, записываемые в
переменные или элементы массива
3. *as
- индексы массива в случае если name имя массива
Методы writevar можно вызывать для
Basic-переменных или элементов
Basic-массивов.
Для Basic-массивов есть 2 способа вызова
методов writevar.
1. С указанием текущих индексов в имени
(параметр as=OB_NULL)
2. С указанием текущих индексов в параметре
*as (параметр as!=OB_NULL)
Методы записывают переменную с именем name в
таблицу переменных и присваивают
ей
значение val.
Если переменная не существует, то она
создается.
Производится проверка на тип имени, т.е.
создается переменная соответствующая
имени.
Если тип присваиваемого значения не
соответствует типу имени (например при
попытке
создать переменную целого типа со вторым аргументом ob_type_char* val),
то
метод генерирует исключение.
Имя name может быть именем элемента массива.
Тогда оно должно содержать
индексы
конкретного элемента по правилам Basic.
Методы возвращают false в случае ошибки
задания имени, например если оно
начинается
не с буквы или является именем не описанного на момент использования
массива.
При нормальном завершении методы возвращают true.
Пример:
Чтобы в пользовательской функции присвоить переменной VAR
значение 10.4, нужно написать следующий
код:
if(basic_ptr->writevar("VAR",10.4)==false)
cout<<endl<<"error in writevar";
Пример:
Чтобы в пользовательской функции присвоить третьему элементу
массива array_string$(10) значение "Hello world",
нужно написать следующий код:
if(basic_ptr->writevar("array_string$(3)","Hello
world")==false)
cout<<endl<<"error in writevar";
Методы
bool
readvar(ob_type_char* name,ob_type_flo*
val,ob_type_arraysize* as=OB_NULL);
bool
readvar(ob_type_char* name,ob_type_int*
val,ob_type_arraysize* as=OB_NULL);
bool
readvar(ob_type_char* name,ob_type_char*
val,ob_type_arraysize* as=OB_NULL);
Параметры:
1. name - имя Basic-переменной или
Basic-массива
2. *val - значение, прочитанное из переменной или элемента массива
3. *as
- индексы массива в случае если name имя массива
Методы readvar можно вызывать для
Basic-переменных или элементов
Basic-массивов.
Для Basic-массивов есть 2 способа вызова
методов readvar.
1. С указанием текущих индексов в имени
(параметр as=OB_NULL)
2. С указанием текущих индексов в параметре
*as (параметр as!=OB_NULL)
Методы считывают переменную с именем name из
таблицы переменных в указатель
val.
Если переменная не существует, то она не
создается.
Имя name может быть именем элемента массива.
Тогда оно должно содержать
индексы
конкретного элемента по правилам Basic.
Методы возвращают false в случае ошибки
задания имени, например если оно
начинается
не с буквы или является именем не описанного на момент использования
массива
или переменная не существует. При нормальном завершении методы
возвращают
true.
Если тип переменной и параметра val не
совпадают (например при попытке
присвоить
строковой переменной значение целого числа), метод генерирует
исключение.
Пример:
Чтобы в пользовательской функции считать значение переменной
VAR1 в C++ переменную с именем val1,
нужно написать следующий
код:
ob_type_flo val1;
if(basic_ptr->readvar("VAR1",&val1)==false)
cout<<endl<<"error name var in readvar";
Пример:
Чтобы в пользовательской функции считать значение четвертого
элемента массива array_string$(10),
нужно написать следующий
код:
ob_type_char buf[256];
ob_type_char* pchar=buf;
if(basic_ptr->readvar("array_string$(4)",pchar)==false)
cout<<endl<<"error name var in
readvar";
Метод
void createvar(ob_type_char* name);
Параметры:
1. name - имя Basic-переменной или
Basic-массива
Создает переменную с именем name в таблице переменных
интерпретатора.
Тип переменной определяется по наличию в имени
символов '%' и '$'.
void createarray(
ob_type_char* name,ob_type_arraydimension
kr,ob_type_arraysize* as);
Параметры:
1. name - имя Basic-переменной или
Basic-массива
2. kr
- количество измерений массива.
3. *as
- массив размеров каждого измерения.
Создает массив с именем name в таблице
массивов интерпретатора. Если массив с
таким
именем уже существует, он удаляется и создается заново с указанными
параметрами.
Тип элементов создаваемого массива
определяется по наличию в имени массива
символов
'%' и '$'. Метод эквивалентен оператору DIM.
Параметры аналогичны параметрам метода
getarraysize.
Пример:
Чтобы из пользовательской функции создать массив целых
ARRAY1%(5,10,20), нужно написать
следующий код:
ob_type_arraysize as[]={5,10,20};
basic_ptr->createarray("ARRAY1%",3,as);
Методы
void clrtabl(typeload a=NOOVERLAY);
void
clrtablfun();
Очищают таблицы интерпретатора.
Метод clrtabl имеет параметр typeload a,
аналогичный параметру метода load.
Метод
clrtabl не очищает таблицу пользовательских функций ни при каких
значениях
параметра typeload a.
Метод clrtablfun очищает таблицу
пользовательских функций.
~ob_obasic(); - деструктор.
Метод static const ob_type_char* about()-
возвращает строку информации о
программе.
Строка может содержать символы новой строки.
Пример:
cout<<ob_obasic::about();//печать
информации о программе
Метод static const ob_type_serialnum
serial_number() - возвращает номер
экземпляра программы.
Метод static const
ob_type_int version() - возвращает номер текущей версии
программы,
умноженный на 100. Для версии 1.80 метод возвращает 180.
Операторы могут располагаться в одной строке и
отделяться друг от друга
пробелами.
Некоторые операторы, например DATA и PRINT
должны быть единственными
операторами
в строке, т.к. нужно явно ограничить список аргументов этих
операторов.
При описании операторов символы в квадратных
скобках означают необязательные
символы.
Open Basic поддерживает следующие операторы:
Выводит в выводной поток, указанный при
создании ob_obasic, список переменных.
Формат оператора:
[N] PRINT [#EXP,][LIST]
где
N -
номер строки
LIST - список элементов, представленных в виде
констант, переменных, строковых
или числовых выражений.
EXP -
выражение, определяющее номер канала вывода, открытого оператором OPEN
Оператор PRINT без списка элементов выводит
символ новой строки.
Если элементом списка является выражение, Open
Basic вычисляет его и печатает
результат.
Пример:
10 TT%=40
TTT=101.3
20 PRINT "TT%=";TT,"TTT=";TTT+0.3
Результат работы оператора
TT%=40
TTT=101.6
Элементы списка отделяются друг от друга
запятыми или точкой с запятой.
Там, где элементы списка отделены запятыми,
производится вывод символа
табуляции
между элементами.
Если в конце списка элементов стоит запятая
или точка с запятой, то после
оператора
PRINT не производится перевод строки.
Оператор PRINT со списком элементов должен
быть единственным оператором
в
строке.
Вводит из вводного потока, указанного при
создании ob_obasic, данные.
Формат оператора:
[N] INPUT [#EXP,]VAR1,[VAR2,VAR3,...]
где
N -
номер строки
VAR1,[VAR2,VAR3,...] - список переменных
EXP - выражение, определяющее номер канала
ввода, открытого оператором OPEN
Встретив оператор INPUT Open Basic вводит из
потока данные, представленные в
числовой
форме и присваивает их переменным из списка. Строковые данные в
потоке
должны быть заключены в кавычки.
Пример:
10 TT%=40
TTT=101.3
20 INPUT TT%,TTT
Позволяют организовать цикл так, что Open
Basic автоматически проверяет
условие
при каждом проходе.
Формат оператора FOR:
[N] FOR VAR=EXP1 TO EXP2 [STEP EXP3]
где
N -
номер строки
VAR -
управляющая переменная (индекс цикла)
EXP1 - начальное значение индекса. Любое
числовое выражение.
EXP2 - конечное значение индекса. Любое
числовое выражение.
EXP3 - приращение величины индекса. Любое
числовое выражение.
может быть положительным или
отрицательным. По
умолчанию равен 1.
Управляющая
переменная (индекс цикла) может быть элементом массива.
Операторы FOR и NEXT используются только в
паре. Оператор FOR определяет
начало
цикла, оператор NEXT - конец цикла.
Формат оператора NEXT:
[N] NEXT VAR1
где
N -
номер строки
VAR1 -
управляющая переменная, использованные в операторе FOR
Если начальное значение переменной цикла больше
конечного значения, то цикл
не
выполняется.
Передавать управление внутрь цикла
недопустимо.
Рекомендуется в качестве переменных цикла
использовать целые переменные, во
избежании
ошибок округления.
Циклы можно вкладывать друг в друга,
внутренний цикл должен заканчиваться до
внешнего.
Оператор FOR имеет некоторые особенности
выполнения. Они связаны с тем, что
Open
Basic это интерпретатор. При входе в цикл производится проверка условия
цикла.
Если условие цикла не выполняется, цикл не будет выполнен ни разу.
В этом
случае производится поиск соответствующего оператора NEXT и передача
управления
ему. При этом не учитываются возможные ветвления алгоритма
операторами
GOTO.
Пример:
GOTO 30
10
NEXT i%
GOTO 20
30 FOR i%=10 TO k% STEP 1
GOTO 10
20
STOP
END
Этот
пример будет работать, если k% больше 10. Но если это не так, то
произойдет
аварийный останов.
Пример:
FOR i%=1 TO 3
FOR ii%=4 TO 1 STEP -2
PRINT
"Work FOR operator","ii%=";ii%,"i%=";i%
NEXT ii%
NEXT i%
Результат работы оператора
Work FOR operator
ii%=4 i%=1
Work FOR operator
ii%=2 i%=1
Work FOR operator
ii%=4 i%=2
Work FOR operator
ii%=2 i%=2
Work FOR operator
ii%=4 i%=3
Work FOR operator
ii%=2 i%=3
Пример:
FOR i%=1 TO 3
FOR ii%=4 TO 1
STEP -2
PRINT
"Work FOR operator","ii%=";ii%,"i%=";i%
NEXT ii%
NEXT i%
Результат работы оператора
Work FOR operator
ii%=4 i%=1
Work FOR operator
ii%=2 i%=1
Work FOR operator
ii%=4 i%=2
Work FOR operator
ii%=2 i%=2
Work FOR operator
ii%=4 i%=3
Work FOR operator
ii%=2 i%=3
Вызывает непосредственный переход к указанной
строке с нарушением
естественного
порядка выполнения операторов программы.
Формат оператора:
[N] GOTO line_number
или
[N] GOTO label_string
где
N
- номер строки
line_number
- номер строки, к которой осуществляется переход
label_string - метка
Пример:
20 GOTO 50
PRINT
"This operator do not work in example"
50 PRINT "Work GOTO operator"
Результат работы оператора
Work GOTO operator
Пример:
20 GOTO
label_1
PRINT
"This operator do not work in example"
label_1: PRINT "Work GOTO operator"
Результат
работы оператора
Work GOTO operator
Осуществляют связь программы с подпрограммой.
Формат оператора:
[N] GOSUB line_number
или
[N] GOSUB label_string
где
N - номер строки
line_number - номер строки, к которой осуществляется
переход
label_string - метка
Встретив в программе оператор GOSUB, Open
Basic передает управление строке,
заданной
в операторе GOSUB. Программа продолжает выполняться с этой строки.
Когда
встретится оператор RETURN управление передается строке, следующей за
строкой
с оператором GOSUB.
Операторы GOSUB и RETURN используются только в
паре.
Формат оператора RETURN:
[N] RETURN
где
N -
номер строки
Подпрограммы можно вкладывать друг в друга.
Пример:
GOSUB 10
GOTO 100
10
PRINT
"Work GOSUB operator 1"
GOSUB 20
PRINT
"Work GOSUB operator 2"
RETURN
20
PRINT
"Work GOSUB operator 3"
PRINT
"Work GOSUB operator 4"
RETURN
100
STOP
END
Результат
работы оператора
Work GOSUB operator 1
Work GOSUB operator 3
Work GOSUB operator 4
Work GOSUB operator 2
Пример:
GOSUB
label_gosub_1
GOTO label_goto_1
label_gosub_1:
PRINT
"Work GOSUB operator 1"
GOSUB
label_gosub_2
PRINT
"Work GOSUB operator 2"
RETURN
label_gosub_2:
PRINT
"Work GOSUB operator 3"
PRINT
"Work GOSUB operator 4"
RETURN
label_goto_1:
STOP
END
Результат
работы оператора
Work GOSUB operator 1
Work GOSUB operator 3
Work GOSUB operator 4
Work GOSUB operator 2
Оператор присваивает значение переменной.
Формат оператора:
[N] [LET] VAR=EXP
где
N -
номер строки
LET -
необязательное имя оператора
VAR -
переменная, принимающая новое значение
EXP -
выражение, определяющее новое значение
Пример:
20 LET a=100.1
PRINT
"Work LET operator","a=";a
Результат
работы оператора
Work LET operator
a=100.1
Оператор резервирует место для числового или
строкового массива.
Формат оператора:
[N] DIM LIST
где
N -
номер строки
LIST - список имен массивов, разделенный
запятыми
Массивы в Open Basic могут быть любой
размерности и объема. В связи с тем, что
место
под них резервируется оператором C++ 'new', ограничения на размер связаны
с
особенностями реализации этого оператора на конкретной платформе. Например в
MS DOS
'new' не запрашивает более 64К байт. Поэтому в MS DOS Open Basic общий
размер
массива не может быть больше 64К байт, при этом количество измерений
также
не может превышать 64К байт.
Массивы в Open Basic могут менять размерность.
При повторном описании уже
описанного
массива, он уничтожается и создается вновь, возможно уже с новыми
размерностями
и размером.
При создании числовые массивы инициализируются
нулем. Строковые массивы
инициализируются
пустой строкой.
Тип создаваемого массива определяется по
правилам определения типа переменной,
по
наличию в имени символов % и $.
Пример:
DIM
a%(2,2,3),b(3,2,4)
DIM a$(2,2,3,2)
a$="variable string"
a$(1,1,3,2)="array string"
a%(2,2,3)=10
b(1,1,1)=101.1
PRINT
a$(1,1,3,2)
PRINT a$
PRINT
"a%=";a%
PRINT
"b=";b
Результат работы оператора
array string
variable string
a%=10
b=101.1
Операторы используются для завершения работы
программы.
Оператор STOP вызывает очистку всех таблиц
Open Basic - переменных, массивов
и т.д.
Оператор END также вызывает очистку всех
таблиц Open Basic и дополнительно
выставляет
внутренний флаг останова. Сброс этого флага производится в методе
ob_obasic::load.
Операторы не вызывают очистку таблицы
пользовательских функций.
Если программа имеет оверлейную структуру и
последующие ее части загружаются
методом
load с параметром OVERLAY и используют таблицы переменных предыдущих
частей,
то операторы STOP и END должны стоять только в конце последней части
программы.
Формат операторов:
[N] STOP
[N] END
где
N -
номер строки
Пример:
PRINT "example STOP and REM
operator"
10 STOP
20 END
Вводит комментарии в программу.
Формат
оператора:
[N] REM COMMENT
где
N -
номер строки
COMMENT - текст комментария
Операторы REM и пустые строки увеличивают
время выполнения программы и
занимают
место в памяти.
Пример:
10 REM this text is comment
Оператор OPEN открывает файл. Оператор CLOSE
закрывает файл.
Формат оператора OPEN:
[N] OPEN filename FOR INPUT AS FILE #EXP
[N] OPEN filename FOR OUTPUT AS FILE #EXP
где
N -
номер строки
filename - имя файла
EXP - выражение, которое вычисляется и
приводится к целому типу. Обычно
используют константы.
AS FILE - ключевые слова
Оператор OPEN FOR INPUT открывает файл для
чтения.
Оператор OPEN FOR OUTPUT открывает файл для
записи.
Формат оператора CLOSE:
[N] CLOSE #EXP1,[#EXP1,#EXP2,...]
где
N -
номер строки
EXP - выражение, которое вычисляется и
приводится к целому типу. Обычно
используют константы.
Пример:
k%=10
OPEN "F000.TXT"
FOR OUTPUT AS FILE #k%+1
OPEN "F001.TXT" FOR OUTPUT AS
FILE #k%+2
FOR i%=1 TO
KOL% STEP 1
PRINT
"i%=",i%
PRINT
#k%+1,i%
f=i%+0.1
PRINT
#k%+2,f
NEXT i%
CLOSE #k%+1
CLOSE #k%+2
OPEN
"F000.TXT" FOR INPUT AS FILE #k%+2
OPEN
"F001.TXT" FOR INPUT AS FILE #k%+3
FOR i%=1 TO
KOL% STEP 1
INPUT
#k%+2,ii%
INPUT
#k%+3,ff
PRINT
"ii%=",ii%
f=i%+0.1
IF
ii%<>i% THEN PRINT " Error test OPEN-CLOSE command" GOTO 10
IF
ff<>f THEN PRINT " Error test OPEN-CLOSE command" GOTO 10
NEXT i%
CLOSE #k%+2
CLOSE #k%+3
10 STOP
END
Удаляет файл.
Формат оператора:
[N] KILL
STR1[,STR2,STR3,...]
где
N -
номер строки
STR1, STR2 ,STR3 - имена файлов
Пример:
10 KILL
"F000.TXT","F001.TXT"
Операторы READ и DATA используются для организации блока данных,
который
считывается
интерпретатором Open Basic во время выполнения программы.
Формат оператора READ:
[N] READ
VAR1[,VAR2,VAR3,...]
где
N -
номер строки
VAR1,VAR2,VAR3 - переменные, которым
присваиваются значения из списка
оператора DATA
Формат оператора DATA:
[N] DATA EXP1,[EXP1,EXP2,...]
где
N -
номер строки
EXP1,EXP2,EXP3, - выражение, которое
вычисляется и
присваивается переменной из списка READ. Могут
быть числовыми
или строковыми. Обычно используют константы.
Формат оператора RESTORE:
[N] RESTORE
где
N -
номер строки
Перед выполнением программы Open Basic
просматривает все операторы DATA в
порядке
их появления и создает блок данных. Каждый раз, когда в программе
встречается
оператор READ, блок данных выдает последовательно соответствующее
значение
для переменных этого оператора в том порядке, в котором они заданы
в блоке
данных.
После выполнения оператора READ положение
последних считанных данных
запоминается.
Следующий оператор READ начинает выбирать данные с той позиции,
которая
была установлена предыдущим оператором READ.
Open Basic осуществляет повторное чтение одних
и тех же данных с помощью
оператора
RESTORE.
Оператор DATA должен быть единственным
оператором в строке.
Пример:
DATA
1.1,2,3,4,"1 string for data"
DATA
5.1,6,7,4+4,"2 string for data"
DIM z%(3)
READ
a2,z%(1),z%(2),z%(3),e2$
READ
a,b%,c%,d%,e$
PRINT
"a=";a;" b%=";b%;" c%=";c%;"
d%=";d%;" e$=";e$
READ
a1,b1%,c1%,d1%,e1$
PRINT
"a1=";a1;" b1%=";b1%;" c1%=";c1%;"
d1%=";d1%;" e1$=";e1$
RESTORE
READ
a1,z%(1),z%(2),z%(3),e1$
PRINT
"a1=";a1;" z%(1)=";z%(1);" z%(2)=";z%(2);"
z%(3)=";z%(3);
PRINT " e1$=";e1$
Результат работы оператора
a=1.1 b%=2 c%=3 d%=4 e$=1 string for data
a1=5.1 b1%=6
c1%=7 d1%=8 e1$=2 string for data
a1=1.1 z%(1)=2
z%(2)=3 z%(3)=4 e1$=1 string for data
Инициализирует случайный генератор новым
значением. В качестве нового значения
используется
текущее системное время в секундах. Поэтому повторно оператор
RANDOMIZE
нужно применять не раньше, чем через 1 секунду после его предыдущего
применения.
Формат оператора:
[N] RANDOMIZE
где
N -
номер строки
Оператор RANDOMIZE помещается перед первым
использованием функции случайных
чисел
(функция RND). При выполнении функции RND оператор RANDOMIZE изменяет
начальное
значение случайного числа таким образом, что при последующем проходе
функция
RND дает другие числа.
Пример:
10 RANDOMIZE
Служит для организации условных переходов.
Имеет три формата: строковый,
блочный
и блочный укороченный.
Строковый формат оператора IF:
[N] IF REL-EXP
THEN operators
где
N -
номер строки
THEN - ключевое слово
REL-EXP - проверяемое условие. Выражение
отношения может быть арифметическим
или
строковым.
operators
- оператор или группа операторов
Если условие REL-EXP истинно, то выполняются
операторы в строке за ключевым
словом
THEN, если условие ложно, то выполняется оператор в следующей за
оператором
IF строке.
Пример:
TT%=40
20 IF TT%=40 THEN GOTO 50
PRINT
"This operator do not work in example"
50 PRINT "Work IF
operator","TT%=";TT%
Результат работы оператора
Work IF operator TT%=40
Пример:
TT%=40
IF TT%=40
THEN PRINT "Work IF operator","TT%=";TT% GOTO 10
PRINT
"This operator do not work in example"
10 PRINT "Work IF
operator","TT%=";TT%
Результат работы оператора
Work IF operator TT%=40
Work IF operator TT%=40
Пример:
TT%=40
IF TT%=40
THEN a=101.1 b=102.1 c=103.1 GOTO 10
a=1101.1
b=1102.1 c=1103.1
PRINT
"This operator do not work in example"
10 PRINT
"a=";a,"b=";b,"c=";c
Результат работы оператора
a=101.1 b=102.1 c=103.1
Блочный формат оператора IF:
[N] IF REL-EXP
THEN
operators1
ELSE
operators2
ENDIF
где
N - номер строки
THEN - ключевое слово
REL-EXP - проверяемое условие. Выражение
отношения может быть арифметическим
или строковым.
operators
- оператор или группа операторов
Если условие REL-EXP истинно, то выполняются
операторы в блоке между ключевыми
словами
THEN и ELSE. Если условие REL-EXP ложно, то выполняются операторы в
блоке
между ключевыми словами ELSE и ENDIF.
Блочный
укороченный формат оператора IF:
[N] IF REL-EXP THEN
operators1
ENDIF
где
N - номер строки
THEN - ключевое слово
REL-EXP - проверяемое условие. Выражение
отношения может быть арифметическим
или
строковым.
operators
- оператор или группа операторов
Если условие REL-EXP истинно, то выполняются
операторы в блоке между ключевыми
словами
THEN и ENDIF. Если условие REL-EXP ложно, то выполняется оператор в
следующей
за ключевым словом ENDIF строке.
Функция SGN% - функция знака.
Формат:
SGN%(EXP)
где EXP
- целое или выражение с плавающей точкой.
Функция
возвращает +1 если EXP>0, -1 если EXP<0 и 0 если EXP=0.
Если
аргумент задан неверно(строковый), то генерируется ошибка.
Пример:
PRINT
"This is example SGN function"
PRINT
"<0";SGN%(-1-2);" >0";SGN%(2*3);"
=0";SGN%(9+1-10)
Функция ABS - определяет абсолютное значение
аргумента.
Формат:
ABS(EXP)
где EXP
- целое или выражение с плавающей точкой.
Функция
возвращает результат с плавающей точкой, даже при целом аргументе.
Если
аргумент задан неверно(строковый), то генерируется ошибка.
Пример:
PRINT
"This is example ABS function"
PRINT
"abs(-20.5)=";ABS(-20.5);" abs(20.5)=";ABS(20.5)
Функция INT% - определяет целую часть
аргумента.
Формат:
INT%(EXP)
где EXP
- целое выражение с плавающей точкой.
Функция
возвращает целый результат.
Если
аргумент задан неверно(строковый), то генерируется ошибка.
Пример:
PRINT "This
is example INT% function"
PRINT
"int(-20.3)=";INT%(-20.3);" int(20.3)=";INT%(20.3)
Функции вычисляют синус, косинус,
арктангенс, квадратный корень, экспоненту,
логарифм,
и десятичный логарифм соответственно.
Форматы:
SIN(EXP),
COS(EXP),
ATN(EXP),
SQR(EXP),
EXP(EXP),
LOG(EXP),
LOG10(EXP)
где EXP
- целое или выражение с плавающей точкой.
Функции
возвращают результат с плавающей точкой.
Если
аргумент задан неверно(строковый), то генерируется ошибка.
Пример:
PRINT
"This is example trigonometric function"
a=SIN(3.14/2)
b=COS(0)
c=ATN(1)
d=SQR(4.0)
e=EXP(1)
f=LOG(EXP(1))
g=LOG10(10)
PRINT
"a=";a;" b=";b;" c=";c;" d=";d;"
e=";e;" f=";f;" g=";g
Функция RND - генерирует псевдослучайное число
в интервале 0-1.
Формат:
RND().
Функция
возвращает результат с плавающей точкой.
Аргументы игнорируются.
Пример:
PRINT
"This is example RND function"
PRINT
RND(),RND(),RND(),RND();
RANDOMIZE
PRINT RND(),RND(),RND(),RND();
Функция LEN% - определяет длину строки.
Формат:
LEN%(EXP)
где EXP
- строковое выражение.
Функция
возвращает целый результат.
Если
аргумент задан неверно(целый или с плавающей точкой), то генерируется
ошибка.
Пример:
PRINT
"This is example LEN function"
STRing_this$="aaa bbb ccc ddd"
PRINT
"len=";LEN%(STRing_this$)
Функции возвращают дату и время
соответственно.
Форматы:
DAT$(),
CLK$()
Функции
возвращает строковый результат.
Аргументы
игнорируются.
Формат
даты: day-month-year
Формат
времени: hour:min:sec
Пример:
PRINT "This is example DAT$ &
CLK$."
PRINT
"data=";DAT$;" time=";CLK$
Функция D2STR$ - конвертирует число
в строку с его десятичным представлением
Формат:
D2STR$(EXP)
где EXP
- целое число или число с плавающай точкой
Функция
возвращает строковый результат.
Функция D2HEXSTR$ - конвертирует целое число в
строку с его шестнадцатеричным
представлением
Формат:
D2HEXSTR$(EXP)
где EXP
- целое число
Функция
возвращает строковый результат.
Функция STR2FLOAT - конвертирует строку в
число
Формат:
STR2FLOAT(EXP)
где EXP
- строка
Функция
возвращает число с плавающай точкой. Если строка не может быть
конвертирована
в число, возвращается ноль.
Функция STR2INT% - конвертирует строку в целое
число
Формат:
STR2INT%(EXP)
где EXP
- строка
Функция
возвращает целое число. Если строка не может быть конвертирована в
целое
число, возвращается ноль.
Пример:
PRINT "converter from digit to string
=";D2STR$(123)
PRINT
"converter from string to float =";STR2FLOAT("1.234")
PRINT
"converter from string to int =";STR2INT%("1234")
PRINT
"converter from digit to hex string =";D2HEXSTR$(4660)
При обнаружении ошибки Open Basic генерирует
исключение типа ob_err с кодом
ошибки.
Пользователь должен перехватывать это исключение и обрабатывать его.
Для
этого класс ob_err имеет специальные методы. Типовая схема работы с
исключениями
ob_err:
int main(int argc, char * argv[]){
int
ret=0;//код возврата main
ifstream
fi;//входной поток
try{
ob_obasic
basic_interpreter(OB_NULL);//Создание интерпретатора
fi.open("test1.bas",ios::binary);//открытие
входного потока в бинарном режиме
basic_interpreter.load(&fi);//загрузка *.bas-программы
ob_obasic::typeend te=basic_interpreter.run();//запуск *.bas-программы
cout<<endl<<"Stop by stop code";//печать кода останова
cout<<endl<<"Stop
code=";
switch(te){
case
ob_obasic::ENDOPERATORDETECT
:cout<<"ENDOPERATORDETECT";break;
case
ob_obasic::ENDFILEEND
:cout<<"ENDFILEEND";break;
case
ob_obasic::BREAKPOINTEND
:cout<<"BREAKPOINTEND";break;
case ob_obasic::NOLOADEND
:cout<<"NOLOADEND";break;
case
ob_obasic::BREAKBEFOREOPERATOR:cout<<"BREAKBEFOREOPERATOR";break;
case
ob_obasic::BREAKAFTEROPERATOR
:cout<<"BREAKAFTEROPERATOR";break;
case
ob_obasic::EOLEND
:cout<<"EOLEND";break;
default:cout<<"Unknown stop code";break;
}//switch
}//try
catch(ob_err& e){
cout<<endl<<"Stop by
ret=e.getcode(); //получение кода
ошибки
e.release(&cout,&ob_englmessage); //печать текстового сообщения в cout
}//OB catch
return ret;
}
Класс ob_err имеет методы getcode и release.
virtual ob_type_codeerror getcode();
virtual void release(ostream* os,ob_message*
currentmessage);
Метод
getcode не имеет аргументов и возвращает код ошибки.
Метод
release имеет два аргумента: указатель на поток и таблицу диагностических
сообщений.
Метод release записывает в указанный поток текстовое сообщение из
таблицы
диагностических сообщений, соответствующее коду ошибки.
Open Basic предоставляет таблицу
диагностических сообщений на английском языке
ob_englmessage.
Пользователь может создать собственную таблицу диагностических
сообщений
на другом языке и использовать ее в качестве второго аргумента метода
release.
Чтобы получить строку, в которой произошла
ошибка, надо воспользоваться
функцией
ob_loadbreakstr.
Более
подробно обработку исключений можно посмотреть в файле .\example\ob.cpp.
Ниже приведен список диагностических
сообщений:
"End
programm OK",//0 - нормальное завершение программы
"Divide
by zero", //1 - деление на ноль
"Incompatible operand for this
operation",//2 - несовместимые операнды
(например
строковые и числовые в арифметической операции)
"Sintax
error",//3 - синтаксическая ошибка
"Missing
')'",//4 - пропущена правая скобка (возможно слишком много
аргументов
в функции или размерностей в массиве)
"Missing
primary",//5 - ожидается в этом месте программы примитив.
"Too
long name or string",//6 - слишком длинная строка или имя переменной
"Use variable before definition",//7 - использование переменной
в
правой части оператора присвоения до использования ее в левой части.
"Missing
'='",//8 - ожидается в этом месте
программы знак присвоения.
"Error
read input stream",//9 - ошибка чтения из входного потока.
"Duplicate
label in program",//10 - метка описана в программе дважды.
"System error. Please contact your
dealer",//11 - не используется
"Label not present in GOTO or GOSUB",//12 - в таблице меток не найдена
метка,
на которую ссылается оператор GOTO.
"Missing compare operator in operator
IF",//13- в операторе IF
ожидается
символ выражения отношения (<,>,<=, и.т.д.).
"Missing keyword THEN in operator IF",//14 -
в операторе IF
ожидается
ключевое слово THEN.
"System error. Please
contact your dealer",//15 - не используется
" System error. Please contact your dealer
",//16 - не используется
"Not GOSUB operator for this RETURN
operator",//17 - при работе
программы
найден оператор RETURN, однако стек входов в подпрограммы пуст.
"Counter parameter of FOR operator must be
variable or array element",//18
- в операторе FOR ожидается имя
переменной или элемента массива в качестве
счетчика цикла.
"Missing keyword TO in operator FOR",//19 - в операторе FOR
ожидается
ключевое слово TO.
"System error. Please
contact your dealer",//20 - не используется
"System error. Please contact your
dealer",//21 - не используется
"System error. Please contact your
dealer",//22 - не используется
"Error in parameters built-in
function",//23 - ошибка при разборе параметров
функции.
"Missing name array in DIM operator",//24 - в операторе DIM
ожидается
имя массива с размерностями.
"System error. Please contact your
dealer",//25 - не используется
"Too
many array dimension",//26 - у массива слишком много измерений.
"Missing ',' in DIM operator to separate
value",//27 - в операторе
DIM
ожидается запятая при разделении имен массивов.
"System error. Please contact your
dealer",//28 - не используется
"Size of array is negative or zero",//29 - нулевой или
отрицательный
размер массива.
"System error. Please
contact your dealer",//30 - не используется
"Size of array is zero",//31 - нулевой размер массива.
"Current index of array too big",//32 - дополнительный контроль к ошибке 59
"Missing keyword FOR in operator OPEN",//33
- в операторе OPEN
ожидается ключевое слово FOR.
"Missing mode opened file in operator
OPEN",//34 - в операторе OPEN
ожидаются
ключевые слова режима открытия файла.
"Missing keyword 'AS' or 'FILE' or '#' in
operator OPEN",//35 - в
операторе
OPEN ожидаются ключевые слова AS FILE.
"System error. Please contact your
dealer",//36 - не используется
"System error. Please contact your
dealer",//37 - не используется
"File not open",//38 - файл не открыт.
"System error. Please contact your
dealer",//39 - не используется
"System error. Please contact your
dealer",//40 - не используется
"Too many parameters in call function",//41
- слишком много
параметров
в вызове функции.
"System error. Please
contact your dealer",//42 - не используется
"System error. Please contact your
dealer",//43 - не используется
"System error. Please contact your
dealer",//44 - не используется
"System error. Please contact your
dealer",//45 - не используется
"System error. Please contact your
dealer",//46 - не используется
"System error. Please contact your
dealer",//47 - не используется
"System error. Please contact your dealer",//48
- не используется
"System error. Please contact your
dealer",//49 - не используется
"Unary minus can not use for string
type",//50 - попытка применить операцию
унарного
минуса к строковой переменной
"Compare with zero can not use for string type",//51 - попытка применить
операцию
сравнения с нулем к строковой переменной
"Arithmetic operator can not use for string
type",//52 - попытка применить
арифметическую
операцию к строковой переменной
"Can not compare string and digital type",//53 - попытка применить
операцию
сравнения с числом к строковой переменной
"Error format of float number (is two point in
float number)",//54 - ошибка
формата
константы с плавающей точкой
"Error
format of hex number",//55 - ошибка формата шестнадцатеричной константы
"Error format of number (is point and 'x' letter
in hex number)",//56
- ошибка формата шестнадцатеричной
константы
"String
do not have right quote",//57 - не найдена правая кавычка в строковой
константе
"Current count dimension of array is not equal
that DIM operator",//58 -
количество
размерностей в текущем обращении к массиву не равно количеству
размерностей в операторе DIM
"One or many current dimension of array is too
big",//59 - попытка обратится к
элементу
массива с номером большим, чем он описан в операторе DIM.
Например,
DIM a%(10,20) а обращение a%(5,21).
"System error. Please contact your
dealer",//60 - не используется
"System error. Please contact your
dealer",//61 - не используется
"System error. Please contact your
dealer",//62 - не используется
"System error. Please contact your
dealer",//63 - не используется
"Do not clear left in primary (debug
error)",//64 - отладочная информация.
Не
должна появляться при нормальной работе
"Do not clear left in run user function (debug
error)",//65 - отладочная
информация.
Не должна появляться при нормальной работе
"Do not found NEXT operator for FOR
operator",//66 - не найден оператор NEXT
для
текущего оператора FOR
"System error. Please
contact your dealer",//67 - не используется
"System error. Please contact your
dealer",//68 - не используется
"Parameter of NEXT operator must be variable or
array element",//69
- в операторе NEXT ожидается имя
переменной или элемента массива в качестве
счетчика цикла.
"Do not found ELSE or ENDIF operator for IF
operator",//70 - не найдены ключевые
слова
ELSE или ENDIF для текущего оператора IF
"Do not found FOR operator for this NEXT
operator",//71 - не найден оператор FOR
для
текущего оператора NEXT
"Need '(' in DIM operator or array use"//72
- не найдена левая скобка после
имени
массива в операторе DIM
"Can
not cast float to string"//73 - попытка приведения числа к строке
"Can
not cast int to string"//74 - попытка приведения числа к строке
"Can
not cast string to float"//75 - попытка приведения строки к числу
"Can
not cast string to int"//76 - попытка приведения строки к числу
"Index of array must not be zero"//77 - текущий индекс массива
равен нулю
"Do not clear ptr in setptr for savewrapper
(debug error)",//78 - отладочная
информация.
Не должна появляться при нормальной работе
"Array
dimention less than zero",//79 - текущий индекс массива меньше нуля
"Error file name format in OPEN operator",//80
- ошибка имени файла
(возможно
пустая строка)
"Error
write
to output stream",//81 - ошибка записи в выходной файл в
операторе
PRINT