Виртуальная школа начинающего программиста
12 мая 2003
Рубрика: Технологии.
Автор: Данияр Атаджанов.
pic

Мы продолжаем знакомить вас с возможностями различных языков программирования и программных сред разработки. Данный урок посвящен такой популярной среде разработки, как Visual Basic. Этот язык стал очень популярен благодаря своей простоте и универсальности. Наверное, именно поэтому многие компании-разработчики прикладного программного обеспечения сделали его встроенным языком своих программных продуктов, позволяющим пользователю расширять их стандартные возможности своими руками (например, Microsoft Office, CorelDraw, AutoCAD и др.). Сегодня основой для урока послужит статья нашего автора, в которой он продемонстрирует, что с помощью Visual Basic можно создать даже собственный язык программирования. Правда, назвать его действительно новым языком нельзя, но как пример самостоятельного опыта «языкостроения» достаточно интересен.

Урок 2: Создаем свой язык программирования с помощью Visual Basic

Да, действительно, мы сейчас попробуем стандартными средствами создать свой язык программирования! Не удивляетесь, но это не так сложно, как может показаться на первый взгляд. Конечно, до создания настоящего компилятора далеко, но это лишь пример, и дальше все ограничивается лишь вашей фантазией и умением.
Ну что ж, приступим. Для начала как-нибудь назовем наш новый язык. Ну, например, Simple Programming Language, сокращенно — SPL. Любой язык программирования состоит из трех частей:

а) правила синтаксиса;
б) операторы;
в) собственно компилятор.

Начнем, пожалуй, с пункта а. Правила синтаксиса мы может установить любые. Пусть это будут те же правила, что и в Бейсике, но с русским синтаксисом, то есть вместо:

If x = 0 Then MsgBox «Error»
вы напишете достойное:
Если икс = 0, тогда Сообщ «Ошибка»
Не правда ли, здорово?

Пункт б. Ну, если мы выбрали Бейсик, то и операторы будут те же, что в Бейсике, но на русском языке. Это вы уже увидели в описанном выше примере.
И, наконец, самое главное и интересное — реализация языка, то есть создание компилятора.
Открываем Visual Basic и создаем в нем новый проект — Standard EXE.
Перед нами пустая форма. Начнем ее оформлять. Измените некоторые свойства нашей формы (их меняют на панели Properties):

Name = frmMain — так обычно называют основную форму;
Caption = «Simple Programming Language version 1.0.0» — тут вы можете написать все, что вашей программистской душе угодно!
Так же измените длину и ширину основной формы под ваши.
И еще: измените BorderStyle на 1 — Fixed Single, а MinButton — на True. Теперь мы запретили изменение размеров форм.
Из чего будет состоять наша программа? Конечно, в первую очередь нам надо создать поле ввода, куда пользователь будет писать свой код.
Итак, нажимаем кнопку TextBox на панели инструментов.
Затем методом протягивания обозначьте этот компонент на вашей форме. Задайте нужную длину и ширину, а также обязательно измените свойство MultiLine на True. Это позволит писать код в текстовое поле не на одну строку, а на несколько. Также свойство ScrollBars надо установить как 2 — Vertical. При этом во время ввода текста пользователем нашей программы справа появится полоса прокрутки. Кстати, наше поле ввода я назвал txtCode (Name = txtCode).

pic

Теперь, думаю, нужно создать несколько кнопок, которые, собственно, и будут выполнять основные действия программы. Это кнопки «Запуск» и «Выход». Можно также добавить еще несколько кнопок по вашему усмотрению, а я объясню, что будут делать эти две кнопки. Нетрудно догадаться, что первая кнопка запустит код, который впишет пользователь, а вторая — это выход из вашей программы. Поэтому в свойство Caption первой кнопки впишем «Запуск», а в свойство второй — «Выход».

pic

Кнопки я назвал cmdRun и cmdExit.
Ну что же, с оформлением покончено, пора переходить к написанию кода к программе. Код я постарался сделать максимально понятным и коротким. Расскажу о том, как я собираюсь обычный текст, который вводит пользователь, превратить в работающий код. Это делается при помощи функции EbExecuteLine, которая в Visual Basic пятой версии находится в библиотеке vba5.dll, а в шестой версии — в библиотеке vba6.dll (на более низких версиях VB я никогда не работал). Данная функция обрабатывает обычный текст как программный код. Функция EbExecuteLine возвращает значение, которое будет равняться 1 (если код сработал и не имеет синтаксических и других ошибок) или 0 (если при обработке кода произошла ошибка). Это замечательное свойство данной функции мы и используем. В случае, если текст невозможно обработать и он содержит ошибки, мы выведем сообщение об ошибке. Чтобы воспользоваться возможностями функции EbExecuteLine, сначала нужно ее объявить. Если вы используете VB 6.0, то в разделе General впишите следующие объявления:

Option Compare Text
Option Explicit
Private Declare Function EbExecuteLine Lib «vba6.dll» (ByVal pStringToExec As Long, _ ByVal Foo1 As Long, ByVal Foo2 As Long, ByVal fCheckOnly As Long) As Long
Если же вы используете Visual Basic пятой версии, то вместо предыдущих объявлений вы должны написать немного иное:

Option Compare Text
Option Explicit
Declare Function EbExecuteLine Lib «vba5.dll» (ByVal pStringToExec As Long, _ByVal Foo1 As Long, ByVal Foo2 As Long, ByVal fCheckOnly As Long) As Long

То есть заменяем vba6.dll на vba5.dll и убираем Private. Теперь программируем кнопки. Что написать в процедуре, обрабатывающей нажатие (Click) кнопки выхода, мы знаем:

Private Sub cmdExit_Click()
End
End Sub

Как вы уже поняли, после обработки события End программа завершает свою работу, то есть выключается. Теперь переходим к программированию второй и самой главной кнопки. Она, используя функцию, возможности которой я описал выше, переводит обычный текст в исполняемый код. Итак, сначала проверим, действительно ли в поле ввода содержится текст:

If Len(txtCode.Text) <> 0 Then

и если все в порядке, то идем дальше. Объявим переменные, которые будут нам помогать:

Dim Result As Boolean, Code As String

В переменной Result будет находиться значение, возвращаемое функцией EbExecuteLine, а в переменной Code — текст, который отправим на обработку, поэтому сразу присвоим этой переменной текст в поле ввода:

Code = txtCode.Text

Теперь в переменной Code содержится значение поля ввода. У функции EbExecuteLine есть один недостаток — она не может обработать символ новой строки (в Бейсике — это vbCrLf), но зато понимает двоеточие (:), и нужно этим воспользоваться. Значит, заменяем vbCrLf на двоеточие:

Code = Replace(Code, vbCrLf, «:»)

Мы решили, что у нас будет русский синтаксис, но функция EbExecuteLine понимает только английские операторы, поэтому все русские операторы, которые встретятся программе, переведем на английские:

Code = Replace(Code, «Если», «If», , , 2)
Code = Replace(Code, «Тогда», «Then», , , 2)
Code = Replace(Code, «Сообщ», «MsgBox», , , 2)
Code = Replace(Code, «От», «For», , , 2)
Code = Replace(Code, «До», «To», , , 2)
Code = Replace(Code, «Следующ», «Next», , , 2)

Цифра 2 в конце Replace означает, что символы должны заменяться независимо от регистра, в котором находятся. Вы можете добавить и другие операторы. Я использовал лишь самые часто используемые. Осталось последнее — запустить код из текстового поля:

Result = EbExecuteLine(StrPtr(Code), 0&, 0&, False) = 0

и если есть ошибки, сообщаем об этом:

pic

If Result = False Then MsgBox «Ошибка в синтаксисе программы!», _ vbCritical, «SPL by Daniyar Atadjanov»
txtCode.SetFocus

Ну вот и все. Пришло время вставить код, который сработает, если пользователь не ввел текста в поле:

pic

Else
MsgBox «Поле ввода кода не должно быть пустой строкой!», vbCritical, _ «SPL by Daniyar Atadjanov»
End If

Ниже показан весь код программы:

Option Compare Text
Option Explicit
Private Declare Function EbExecuteLine Lib «vba6.dll» (ByVal _ pStringToExec As Long, ByVal Foo1 As Long, ByVal Foo2 As Long, ByVal _ fCheckOnly As Long) As Long
‘ Если вы используете VB 5-й версии, то раскомментируйте следующее:
‘Declare Function EbExecuteLine Lib «vba5.dll» (ByVal pStringToExec As _ Long, ByVal Foo1 As Long, ByVal Foo2 As Long, ByVal fCheckOnly As Long) As _ Long
Private Sub cmdRun_Click()
If Len(txtCode.Text) <> 0 Then
Dim Result As Boolean, Code As String
Code = txtCode.Text
Code = Replace(Code, vbCrLf, «:», , , 2)
Code = Replace(Code, «Если», «If», , , 2)
Code = Replace(Code, «Тогда», «Then», , , 2)
Code = Replace(Code, «Сообщ», «MsgBox», , , 2)
Code = Replace(Code, «От», «For», , , 2)
Code = Replace(Code, «До», «To», , , 2)
Code = Replace(Code, «Следующ», «Next», , , 2)
Result = EbExecuteLine(StrPtr(Code), 0&, 0&, False) = 0
If Result = False Then MsgBox «Ошибка в синтаксисе программы!», _ vbCritical, «SPL by Daniyar Atadjanov»
txtCode.SetFocus
Else
MsgBox «Поле ввода кода не должно быть пустой строкой!», vbCritical, «SPL by Daniyar Atadjanov»
End If
End Sub
Private Sub cmdExit_Click()
End
End Sub

А вот результат ее работы:

pic

Или вот еще примерчик:

pic

Увидев второй пример, умный читатель подумает, что такая программа, как наш маленький компилятор, — настоящая находка для хакера или кракера. Вы так подумали? Да? Поздравляю вас — у вас чутье на такие вещи (из вас выйдет неплохой хакер). Нет, не подумали? Не огорчайтесь, подумайте, как такие дыры в проге можно залатать, и из вас получится нечто большее, чем хакер. И действительно, функция, которую мы использовали для превращения текста в код, работает и с компонентами на вашей форме и не только с ними, а еще и с самой формой, и со всеми остальными формами (если они есть) в вашем проекте!
А теперь самое-самое интересное. Попробуете ввести в поле например такое:

frmMain.Hide
Сообщ «До свидания!»
frmMain.Show
Сообщ «Приветик!»
И еще такое:
frmMain.Top = 0
frmMain.Left = 0
If MsgBox («Cool?», vbYesNo + vbQuestion) = vbNo Then frmMain.Left = Screen.Width — frmMain.Width:frmMain.Top = Screen.Height — frmMain.Height — 450: MsgBox «Cool!»: End

Не правда ли, здорово? Конечно, здорово, но если вы решили защитить свою программу от подобных вторжений, то в первую очередь стоит заменить frmMain на что-нибудь типа frmMain 96293867209586. Это, конечно же, не очень красиво, но есть хоть уверенность, что пользователь не сможет манипулировать вашей формой и элементами внутри нее. А вдруг пользователь все-таки набрал frmMain 96293867209586? Что же делать? А вы запретите набор такой комбинации символов, то есть в процедуру, обрабатывающую нажатие кнопки cmdRun, добавьте код, проверяющий наличие «frmMain 96293867209586» в текстовом поле! Что-то похожее на это:

If InStr(txtCode.Text, «frmMain 96293867209586») Then MsgBox «Error!»

Ну вот, мы многое успели! Даже разобрали вопросы безопасности. Надеюсь, что в будущем вам это пригодится как со стороны хакера, ломающего чью-то прогу :), так и со стороны программера, пытающегося повысить безопасность своей программы.
И напоследок о том, где и как можно с выгодой использовать замечательную функцию EbExecuteLine. Область применения, конечно, очень широка, и назвать все варианты я не смогу. Я могу лишь рассказать небольшой пример. Допустим, одна программа как-то (не будем вдаваться в подробности, как именно) передает другой программе некоторые параметры, например координаты объекта Z. Вторая программа, получая эти параметры, показывает местоположение объекта Z у себя на экране. Эта вторая программа принимает данные в виде: Z.Top = 50: Z.Left = 75: Timer1.Enabled = False. Как же нарисовать объект на экране, используя эти параметры? Не ломайте себе голову, воспользуйтесь функцией EbExecuteLine, и все!

Очень надеюсь, что вы найдете этой функции хорошее применение. Хочу лишь сказать, что встретил я ее на сайте VBNet.ru, и если вы заинтересовались ею, то советую вам посетить этот сайт и еще некоторые, посвященные программированию на VB.
Весь мир делится на две группы людей: на тех, кто недолюбливает Visual Basic, и на тех, кто жить без него не может. Вы почувствовали себя во второй группе? Тогда смело заходите на VBNet, VBStreets, RussProject, FreeVBCode и другие им подобные сайты и вы поймете, что вы не один такой, и еще полмира программируют на VB вместе с вами.

pic
Orphus system
В Telegram
В Одноклассники
ВКонтакте