суббота, 9 октября 2010 г.

Простейший компилятор простейшего языка C в Assembler. Часть 2. Лексический блок

Прежде чем читать этот пост, сначала ознакомьтесь с "Простейший компилятор простейшего языка C в Assembler. Часть 1. Транслитератор".

Построение лексического блока не такая уж и тривиальная задача, как может сначала показаться. Казалось бы, что может быть сложного в том, что бы разрезать программный код на слова, а оказывается сложность есть. Вдогонку ко всему, чистый лексический блок писать не практично, поэтому он уже берет на себя часть обязанностей синтаксического анализатора.

Прежде, чем писать код лексического блока, необходимо определиться с лексемами, для этого приведем пример программы:

X = (0.5E1 + 2 + Y);
SCAN(Y);
IF (Y > (X + 2)) {
    PRINT(Y);
} 
Y1 = 10;
M0:
  IF (Y1 != 20 + 30) {
      GOTO M0;
  }    

Разобьем код на лексемы:

(опер. присваивания, 1)  // 1 - номер строки в 
                         // таблице идентификаторов
                         // пример: X = 
(число, 1)               // 1 - номер строки 
                         // в таблице констант 
                         // пример: 0.5
(SCAN, 1)                // 1 - номер строки в 
                         // таблице идентификаторов
                         // пример: SCAN(X)
(IF, IF)                 // пример: IF
((, ()                   // пример: (
(идентификатор, 1)       // 1 - номер строки в 
                         // таблице идентификаторов
                         // пример: x
(), ))                   // пример: )
(ар. операц, +)          // пример: + 
(оп. отношения, >=)      // пример: >=
({, {)                   // пример: {
(}, })                   // пример: }
(;, ;)                   // точка с запятой
(метка, 3)               // 3 - номер строки в 
                         // таблице идентификаторов
                         // пример M0: 
(GOTO, 3)                // 3 - номер строки в 
                         // таблице идентификаторов 
                         // GOTO M0
(PRINT, 2)               // 2 - номер строки в 
                         // таблице идентификаторов
                         // пример: PRINT(Y)

Здесь приведены, только уникальные лексемы для наглядности, так как дважды писать лексему "идентификатор" не нужно.

Теперь вы видите и понимаете, какая задача стоит перед лексическим блоком. Необходимо разбить код на лексемы да и еще в не которых местах проверить синтаксис.

С этой задачей нам позволят разобраться конечные автоматы: детерминированные и не детерминированные, также они решат проблему с производительностью, так как они могут обрабатывать огромные тексты за одни проход. Далее ознакомьтесь с статьями [1], [2], после чего с статьей [3]. Мы будем делать нечто похожее, как описано в третьей статье.

Сначала спроектируем конечный автомат. Я этот делал в файле формата Microsoft Excel. Сам файл можете скачать отсюда, а также всякий случай оставлю "скриншот", для тех кто качать не хочет:



Если вы прочитали, указанные мной, статьи, то для вас не составит труда разобраться с приведенным конечным автоматом. Хотя это может забрать не мало времени. После того, как КА спроектирован осталось перевести его в код на языке программирования C#, аналогично [3] статье.

Код проекта уже с транслитератором и лексическим блоком вы можете скачать отсюда. Проект создан в Visual Studio 2010 Premium.

Если вы заметите ошибки - пишите. Если у вас возникнут вопросы - задавайте их!

воскресенье, 3 октября 2010 г.

Перевод из одной системы координат в другую.

На самом деле перевод не простой. А вот такой:


То есть у вас есть установка фотографирующая точку P (красного цвета на изображении), и задача показать ее в новой координатной системе (V, U), в данном случае это две желтые линии, они означают вектора V, U.

На самом деле после решения данной задачи, стало понятно, что она довольно тривиальная.

Решение заключается вот в чем:  мы точку P повернем на угол между (V, U) и линией l2 + a2 (угол между линией l1, l2) + a1 (угол между l1 и осью X). После поворота мы ее сдвинем на расстояние -l2, потом повернем на угол -a2, после чего можем сдвинуть ее на расстояние -1l и повернем на угол a1 и сдвинем на расстояние -O (точка из которой начинается линия l1). В итоге мы получим точку P в новых координатах (V, U).

Если грубо, то вот, что мы делаем. Мы просто всю нашу фотографирующую установку складываем к осям Y, X.

Я решение выполнил используя javascript-библиотеку Dojo Toolkit, а конкретно dojox.gfx. Приведу пример кода перевода точки P(x, y) в P(v, u):

Весь код можете скачать отсюда. Но внимание, что бы код заработал не открывайте index.html, а создайте хост на веб-сервере, скопируйте туда файлы, а уже потом обращайтесь к нему через браузер.

Спасибо за внимание! Буду рад вопросам в комментариях!