Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Операционные системы > Софт
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.05.2015, 10:51   #1
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию Free Alisa. ЯВУ, которое я разрабатываю для себя

По просьбам нескольких форумчан выкладываю сюда свой интерпретатор Называется "Alisa" и немного примеров. Поскольку я не специалист писать мануалы, то либо тему буду дополнять по мере необходимости либо просто на словах описывать как решаю те или иные задачи.
Сам интерпретатор уже скомпиленный в архиве. Тут же основное его ядро в сорце. К нему конечно есть еще модули, но они используются и в других проектах, поэтому я их не прикладываю.
Кому захочется поштудировать мой индокод - основная функция TAlisaInterpretter.LetsDo. Это старт синтексического разбора и выполнения.
Интерпретатор многопроходный. Кэширования или прекомпиляци нет, и делать не планирую. Скорость мне не особо важна. Исходник конечно замусорен, писал я его без продумывания определенной схемы, а как получится. Не считаю это препятствием ибо писал для себя.

Даж не знаю чего еще сказать...
Думаю по мере дополнения в этой теме в целом картина вырисуется.
Вложения
Тип файла: rar alisa.rar (51.2 Кб, 20 просмотров)
Тип файла: rar FreeAlisa.part01.rar (488.3 Кб, 9 просмотров)
Тип файла: rar FreeAlisa.part02.rar (488.3 Кб, 10 просмотров)
Тип файла: rar FreeAlisa.part03.rar (211.2 Кб, 10 просмотров)
I'm learning to live...

Последний раз редактировалось Stilet; 26.05.2015 в 17:19.
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 10:52   #2
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию Некоторые основы

Код:
(writeln 'Пример основ')
Все что интерпретатор не понимает - считается коментарием
Поэтому писать текст можно свободно в коде не выделяя его в коментарии
типа
(//
  Это закомментированный блок
)
*********************************************************************
Определение переменной
(a := 123) 
*********************************************************************
Определение метода для переменной
(a := func foo (
	(write 'Значение = ' a)
	(return (a + 100))
))
*********************************************************************
Вызов метода и обработка от него результата
(write 'Метод вернет результат: ' (call a.foo))
*********************************************************************
Условный оператор
Допустимые логические операторы <> = >= <= > < and or not xor
(if (a > 100)
 (writeln 'Больше')
 (writeln 'Меньше')
)

Проверка на вхождение
(b := "ми")
(if (b in 'Привет мир')
 (writeln 'Ога')
 (writeln 'Неа')
)
*********************************************************************
Цикл
(for (i := 0) (i < 10) (i ++) 
 (write i)
)
*********************************************************************
Операторы в выражении
(writeln
 "Сумма чисел " (a + i) \n
 "Разница чисел " (a - i) \n
 "Деление чисел " (a / i) \n
 "Целочисленное деление чисел " (a div i) \n
 "Остаток от деления чисел " (a mod i) \n
 "Инкремент " (a ++) \n
 "Декремент " (a --) \n
 "Самоувеличение " (a += 24) \n
 "То же самое для /= *= -=  ^= %= по аналогу в Си" \n
)
*********************************************************************
Массивы 
(m := (integers 11 34 65 88))
Так же допустимы массивы bytes words doubles strings

Списки
(sp <- 'wawa' 12 (2 + 2))

Проход по массивам и спискам
(write 'массив: ')
(for k in m 
	(write k \t)
) (writeln)
(write 'список: ')
(for k in sp 
	(write k \t)
)
*********************************************************************
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 10:53   #3
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию Примерная схема функций

Код:
(writeln '
   Функции. Являются методами переменок или отдельными функциями
   Результат - всегда последнее выражение
')
(f := func foo1 (
 (f.param1 + f.param2)
))

(write (call f.foo1 param1=2 param2=3))

Рекурсия
(f := func foo2 (
 (write f.param1 ' ')
 (if (f.param1 > 10) 
  (return f.param1)
  (f.param1 + (call f.foo2 param1=(f.param1 * 2)))
 )
))
(writeln \n 'Элементы = ' (call f.foo2 param1=2))
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 11:09   #4
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию 7Z упаковщик.

Имеется возможность работать с архивами посредством 7z.
Для этого нужна 7z.dll из стандартной поставки.


Создание обьекта:
Код:
(z := zip)
zip указывает на тип (класс) архива. Так же можно написать вместо слова zip слово 7z. rar пока не поддерживается.

Внесение в список архивируемого некоего файла.
Внесение происходит посредством формирования списка в переменную-объект архива
Код:
(z <- "d:\1\Какой-то файл.xps")
(z <- "d:\еще файл.xps")
Упакова: to - параметр указывающий куда упаковывать.
Расширение автоматически подставляется
deletesource говорит о том что упакованное нужно удалять
Код:
(call z.pack  to='d:\1\zi' deletesource=yes)
Метод возвращает true или false в случае успеха или неудачи и проверяется в if

Распаковка:
Код:
(call z.unpack from='d:\Блабла')
Где Блабла файл zip или 7z в зависимости от того какой класс у переменной z

Список файлов в архиве:
Код:
            (call z.list from=apo.afile onfound=(func
			  (write 'Файл ' z)
			))
В основное поле (по умолчанию) переменной z помещается имя файла.
Анонимка onfound срабатывает для каждого файла, который перечисляется методом list в архиве.

Код:
(call z.clear)
просто очищает список, подготовленный к архивации.
I'm learning to live...

Последний раз редактировалось Stilet; 01.05.2015 в 12:59.
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 11:26   #5
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию ADO. ODBC.

Для этого тоже есть свой класс.

Создается таким образом:
Код:
(base := ado driver='SQL Server' user='sa' pass='Парольчик' 
  base='Базка' host='123.111.34.56')
При этом желательна настройка ODBC.

Открытие запроса:
Код:
(if  (call base.open sql='
        Select
          полетакое-то
        from
         блабла
....
      ')

  (
    Тут обработка полученного запросом
  )

  (
    Тут обработка ошибка, которая возвращается методом (call base.error)
  )

)
Просто выполнение без возврата:
Код:
 (call base.exec sql='INSERT бла бла....')
Тоже проверяется IF-ом

Проход по набору либо так:
Код:
 (for () (call base.noteof) (call base.next)
 (writeln base['Поле такое то'])  
)
Поле можно указать по номеру или имени.
Или так:
Код:
(call base.scan
  (writeln base['Поле такое то'])
)
Второе быстрее и проще. Поэтому я редко использую цикл.

BLOB поля есть :
Код:
(call base.exec 
				sql=`updateТабличка set Блобик=:frf where ID=Чему-то`
				frf=(load 'c:\Users\Vi\Desktop\Файлик.расширеньеце')
			  )
(call base.commit)
Если параметр (load указан значит идет загрузка из файла или из переменной типа stream (есть и такое)
Этот же пример показывает что есть возможность параметрических запросов. frf - параметр, которому что-то назначается.

Список методов следующий:
(call base.next) - переход на следующую запись
(call base.error) - возврат текста ошибки
(call base.eof ) - проверка на конец набора
(call base.noteof ) - проверка на не конец набора
(call base.isnull field='ИмяПоля') - проверка на NULL
(call base.close ) - Закрытие набора
(call base.commit) - Коммит (Роллбэка нет)

(call base.fieldcount ) - Кол-во полей
(call base.fieldname 3) - Имя поля по номеру. 3 это номер поля
(call base.fieldtype 3) - Тип поля
(call base.fieldsize 3) - размер поля
Поля нумеруются с нуля. Как в Делфи

Небольшой пример:
Код:
(res := ado driver='SQL Server' user='sa' pass='Парольчик' base='Платежи')
(write (call res.open sql='SELECT *  FROM ListPays(2013,8,0,1) order by День desc, ОПС'))
(i := 0)

(res := func foorec (format
          `
           <tr onclick="objRES.SelectPaiInTable(this,[id])">
            <th width="5%" align="right" ondblclick="objRES.DelPay(this,[id])">[num]</th>
            <td width="10%" align="left">[ls]</td>
            <td>[fio]</td>
            <td  width="30%">[addr]</td>
            <td  width="10%" align="right">[sum] грн.</td>
            <td  width="10%" align="middle">[adatpay]</td>
            <td  width="10%" align="middle">[aops]</td>
           </tr>
          ` num=count id=res[id] ls=res[Лицевой] fio=res[ФИО] addr=res[Адрес] sum=(asdouble '%10.2f' res[Сумма]) 
            aops=(if (call res.isnull field='ОПС') (result '') (result res[ОПС]))
			adatpay=res[dpay]
  
))
(t := '')
(call res.scan 
 (t += (call res.foorec)) 
 (i ++)
)
(write i t)
Формируется HTML из набора путем дописывания к переменке t строки. format - функция формирования строки по параметрам. Идея взята из Питона. Есть там такое формирование текста путем вставки в спецтеги типа ВВ
I'm learning to live...

Последний раз редактировалось Stilet; 01.05.2015 в 11:36.
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 11:57   #6
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию Немного о списке

Список назначается обьектом list
Код:
(l := list)
По факту это ассоциативный массив. Ну или справочник.
Добавлять так:
Код:
(call l.add 25 (6 + 4))
Соответственно в ячейку с именем 25 что-то помещается. Имя может быть и строковым
Соответственно вытаскивать либо обращаясь к массиву
Код:
(write l[25])
Либо методом:
Код:
(write (call l.item 25))
Списки использую редко, но бывает.

Так же прикручен аналог StringList
Код:
(st := stringlist)
Добавить в список можно так:

Код:
(call st.add
 'Некая строка'
 "Еще одна строка"
 (2 + 2)
)
Все добавляемое преобразуется в строки автоматом

Сохранение и загрузка соответственно происходят методами:
Код:
(call st.save to="d:\Куда сохранять\Имя файла")
Код:
(call st.load from="d:\Откуда считывать\Имя файла")
Если в метод save передать параметр pack=yes то сохраненное будет упаковано в zip. Делалось для определенных целей. Применяю не часто, но оказалось удобно.

Удаление из списка
Код:
(call st.delete 5 32 7)
Соответственно будут удалены строки 5, потом 32 (согласно списку с уже удаленной 5-й) и 7-я. Такого как транзакции еще не прикрутил, поэтому предидущее удаление обязательно влияет на последующее

Поиск:
Код:
(call st.find 'Что искать')
Возвращает True если найдено и False если нет. Индекс найденного не возвращает.

Кол-во элементов
Код:
(call st.count)
Нумерация как в Делфи - с нуля.

Проход по списку:
Код:
(call st.scan 
 (write 'Элемент: ' st)
)
st в проходе принимает очередной элемент списка. В таких методах имя переменки используется как итератор.

Текст целиком:
Код:
... := (call st.text)
Как и в Делфи. Присвоения текста не предусмотренно (пока)

Очистка
Код:
(call st.clear)
Как и в Делфи.

Есть еще метод addfrom.
Код:
(call st.addfrom file='файлик')
Просто дописывает в конец списка содержимое файла.
Делал под определенную задачу. А так редко использую.

К списку можно обращаться как к массиву:
Код:
... := (st[3] + ' дней ' + st[4])
Соответственно вернет конкатенацию элементов списка с константной строкой.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 12:17   #7
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию CryptoAPI. Шифровалка.

Это делалось чисто из интереса, и применения криптованию пока не найдено.
Класс crypt.
Код:
(c := crypt prov=PROV_RSA_FULL hash=CALG_SHA key=CALG_RC4 pass='123')
prov - провайдер
hash - алгоритм
key - ключ
pass - пароль для хеширования

Еще пример:
Код:
(c := crypt md5 pass='123' salt)
С солькой.

Далее можно криптовать:
Код:
(writeln (call c.encrypt text='Hello World') (call c.error))
Хеловорлд зашифруется согласно указанному прову при создании объекта паролю, алгоритму и сольке.
Если произойдет ошибка метод error вернет текст.

Можно шифровать файлы:
Код:
(writeln (call c.encrypt file='d:\файлик.txt' to='d:\файлик.crypted' pass='123'))
Пароль можно менять по необходимости при вызове прова.

Дешифровка соответственно:
Код:
(writeln (call c.decrypt file='d:\файлик.crypted' to='d:\файлик.txt' pass='123'))
File - источник
To - получатель (во что пойдет шифрование)

Еще прикрутил шифрование по сертификату с указанными параметрами:
Код:
(writeln (call c.encrypt 
    file='d:\файлик.txt' 
    to='d:\файлик.crypted' 
    cert 
    subject='DC=com, DC=microsoft, CN=Microsoft Root Certificate Authority'
) (call c.error))
В данном случае выбирается сертификат от Микрососов для криптования.


Но эта возможность на стадии прототипирования, еще требует марафетика.

Есть возможность получения списка сертификатов из хранилища:
Код:
(c := crypt prov=PROV_RSA_FULL hash=CALG_SHA key=CALG_RC4)
(call c.listcerts
 onfound=(writeln 
            'cbCertEncoded=' c[length] \n 
            'dwCertEncodingType=' c[encodingtype] \n 
            'Version=' c[version] \n 
            'serial=' c[serial] \n 
            'signature=' c[signature] \n 
            'issuer=' c[issuer] \n 
            'datebegin=' c[datebegin] \n 
            'dateend=' c[dateend] \n 
            'IssuerUniqueId=' c[IssuerUniqueId] \n 
            'SubjectUniqueId=' c[SubjectUniqueId] \n 
            'publickey=' c[publickey] \n 
            'Subject=' c[subject] \n
        )
)
Анонимка onfound срабатывает на каждый найденный сертификат, инициализируя итератор соответствующими полями.

Есть возможность сгенерировать открытый или закрытый ключик:
Код:
(call c.genkey prov=PROV_RSA_FULL container='my' PUBLICKEYBLOB to='d:\1\key')
В файл выводится сгенереный ключ. Подробности лучше почитать в MSDN, саму схему генерации описывать долго.
Или же открыть сорц и посмотреть как я там это реализовал.
Собственно можно открыть уже сгенерированное:
Код:
(call c.exportkey PUBLICKEYBLOB to='d:\1\key')
Для высадки в файл.
Высадка делается из контейнера, который обьектом сгенерирован заранее.
Открыть контейнер можно при создании объекта:
Код:
(c := crypt prov=PROV_RSA_FULL container='my')
По имени ессно.

Кроме экспорта можно просто прочитать параметры ключа в открытом контейнере
Код:
(writeln (call c.readkey) (call c.error))
(writeln
 'KEYLEN='   c[KEYLEN] '\n' 
 'PADDING='   c[PADDING] '\n' 
 'ALGID='   c[ALGID] '\n' 
 'BLOCKLEN='   c[BLOCKLEN] '\n' 
 'CERTIFICATE='   c[CERTIFICATE] '\n' 
 'SALT='   c[SALT] '\n' 
 'PERMISSIONS='   c[PERMISSIONS] '\n' 
)
Параметры согласованы с MSDN, так что их имена и что они означают можно подсмотреть там.


Удаление контейнера с ключиками:
Код:
(call c.delkey prov=PROV_RSA_FULL container='my')
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 12:26   #8
Arigato
Высокая репутация
СуперМодератор
 
Аватар для Arigato
 
Регистрация: 27.07.2008
Сообщений: 16,219
По умолчанию

Уже высказывал свое ИМХО по поводу скобок: слишком много их, легко запутаться. Я обычно и в арифметических выражениях стараюсь избегать вложенность скобок более двух уровней, если такое получается, то выражение разбиваю на несколько, например, числитель и знаменатель дроби считаю раздельно, а потом делю. Это существенно повышает читабельность.
Arigato вне форума Ответить с цитированием
Старый 01.05.2015, 12:54   #9
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию DBF. FoxPro

С DBF-никами пригодится работать чрезвычайно плотно.
Причем в разных условиях. Поэтому использую как и Фокспро (основа взаимодействия с ядром описана тут: http://www.programmersclub.ru/%D0%91...visual-foxpro/), так и своеписанный мезанизм (типа TDbf Делфийского). Собсно и сам TDbf был прикручен.

Для начала опишу самописку:
Код:
(d := dbf create='d:\1\q.dbf' fields=(
	(num n 5)
	(str130 c 3)
    (dat d)
))
(call d.append num=1 str130='мир' dat=2013-06-15)
Пояснять особо, думаю, не надо. Создается файл с полями, список и характеристики которых описаны параметром Fields.
После чего дописывается запись в конец. Имена полей перечисляются как параметры.

Пометка на удаление:
Код:
(call d.delete 5 3 7)
Помечаются записи по их номеру в таблице.
Физического удаления не происходит.

Проход по набору или таблице - тот же scan.
Код:
(call d.scan
 (writeln d[Имя поля или номер])
)
Значения полей формируются в массив, к которому можно обратиться через саму переменку.

Есть метод
Код:
(call d.noteof)
который применялся в качестве определителя конца таблицы или набора для цикла for.
Так же есть
Код:
(call d.skip step=5)
который применяется для перехода по записям. Если step не указывается то делается проход на следующую запись. Отрицательное значение соответственно делает проход назад.
Таким образом конструкция
Код:
(for () (call d.noteof) (call d.skip)
 (writeln d[Имя поля или номер])
)
является прототипом scan.

Закрывает файл метод
Код:
(call d.close)
Он же является коммитом де-факто
Есть еще метод
Код:
(call d.save file="Файлик куда сохранить")
Выполняющий действие типа создания копии в стиле SaveAs. Редко его использую, но иногда пригождается

Для открытия существуюшей таблицы применяется метод
Код:
(call d.open file="файлик.dbf" codepage=cp866)
Если codepage не указана, по умолчанию имеется ввиду страница Win-1251. Иначе работа с досовскими файлами.

Такс... Что я еще не описал? Пожалуй только получение номера записи.
Делается это обращением к элементу объекта d['recno']. Так что поля с таким именем лучше в DBF не делать, иначе обрабатываться будет коряво.


Теперь Фокспро.
Для его фунциклирования требуются библы: msvcrХХ.dll VFPxENU.DLL VFPxRENU.DLL vfpxt.dll
Где x - версия фокспрошки и Сишного рантайма

Плюс провайдер, сформированный и зарегистрированный как описано в статье, ссыль которой я привел выше.

Обьект создается так:
Код:
(fox := foxpro)
Создание можно проверить :
Код:
(if (fox := foxpro)
 (write 'Нормально. Фокс доступен')
 (write 'Облом: ' (call fox.error) (quit))
)
Если облом то (quit) завершает работу интерпретатора.

Тут мало методов. Основное все вызывается методами func и proc.
Примерно так:
Код:
(call fox.proc 
 'use file.dbf'
 'repl Field with значение all'
 'close data'
)
Метод скормит фоксу строки одну за другой на выполнение.
Таким образом в Алисе можно писать целые скрипты для Фокспро.
Этим же методом выполняются и SQL:
Код:
(writeln (call f.proc 'select * from c:\R12394.DBF') ' ' (call f.error))
(write (call f.scan
 (writeln f[fam])
 
) ' ' (call f.error))
Или
Код:
(if (call fox.proc 'delete from бла бла...')
 (write 'Удалено удачно')
 (write 'Чет не срослось: ' (call fox.error))
)
В отличии от proc метод func выполняется для возврата результата функции.
Напрмиер
Код:
... := (call fox.func '=RECNO()')
Выполнит функцию recno() и вернет ее результат.

Для foxpro класса так же есть scan для прохода по таблице или набору (см. выше)

Есть еще методы reg и unreg, которые регистрируют провайдера, но это тупо аналоги regsvr32, и их я не использую.
I'm learning to live...
Stilet вне форума Ответить с цитированием
Старый 01.05.2015, 12:56   #10
Stilet
Белик Виталий :)
Старожил
 
Аватар для Stilet
 
Регистрация: 23.07.2007
Сообщений: 57,792
По умолчанию

Цитата:
Уже высказывал свое ИМХО по поводу скобок:
Ага помню. Меня диалект Лиспа не напрягает.
И к тому же так удобнее было для разработки анализатора. Анализировать от скобки до скобки.

Такс, пока перерывчик. Позже продолжу...
I'm learning to live...
Stilet вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Хочу написать программу для себя Marishka.S Помощь студентам 7 02.10.2011 17:23