Справочник функций

Ваш аккаунт

Войти через: 
Забыли пароль?
Регистрация
Информацию о новых материалах можно получать и без регистрации:

Почтовая рассылка

Подписчиков: -1
Последний выпуск: 19.06.2015

Создание лексического анализатора

11K
04 апреля 2008 года
zuze
84 / / 07.03.2008
У мнея проблема при написании лексического анализатора

При сравнениии например с var или другой маленькой строкой состоящей из трёх или двух символов данные выводятся не правельно.

Скажите пожалуйст, где я ошибся?

Исходные таблицы (они хранятся в текстовых файлах)

1. Ключевые слова

 
Код:
program
input
output
var
intager
end
begin
and
or


2. Служебные знаки

Код:
:
,
;
:=
.
>=
<=
(
)
+
-
*
/


3. Другие лексемы

 
Код:
ivan1
ivan2
x
y
z


Исходный код хранится в файлах с расширением (*.SRC)

1. prog1.src

 
Код:
program ivan2;
z := x + y;
x - y;
ppt >= s : y <= k


Работает правильно
Результат работы

Код:
Анализ строчки: 1
(1,1)
(3,2)
(2,3)
Анализ строчки: 2
(3,5)
(2,4)
(3,3)
(2,10)
(3,4)
(2,3)
Анализ строчки: 3
(3,3)
(2,11)
(3,4)
(2,3)
Анализ строчки: 4
(2,6)
(2,1)
(3,4)
(2,7)


2. prog3.src

 
Код:
program ivan2;
var;
 integer x, y, z;
begin
 z := x * y;
end;


Работает правильно
Результат работы

Код:
Анализ строчки: 1
(1,1)
(3,2)
(2,3)
Анализ строчки: 2
(1,4)
(2,3)
Анализ строчки: 3
(2,2)
(3,4)
(2,2)
(3,5)
(2,3)
Анализ строчки: 4
(1,7)
Анализ строчки: 5
(3,5)
(2,4)
(3,3)
(2,12)
(3,4)
(2,3)
Анализ строчки: 6
(1,6)
(2,3)


3. prog4.src

 
Код:
program ivan2;
input
 integer x, y, z;
begin
 z := x * y;
end;


Работает правильно
Результат работы

Код:
Анализ строчки: 1
(1,1)
(3,2)
(2,3)
Анализ строчки: 2
(1,2)
Анализ строчки: 3
(2,2)
(3,4)
(2,2)
(3,5)
(2,3)
Анализ строчки: 4
(1,7)
Анализ строчки: 5
(3,5)
(2,4)
(3,3)
(2,12)
(3,4)
(2,3)
Анализ строчки: 6
(1,6)
(2,3)


4. prog2.src

 
Код:
program ivan2;
var
 integer x, y, z;
begin
 z := x * y;
end;


Работае неправильно
Результат работы

Код:
Анализ строчки: 1
(1,1)
(3,2)
(2,3)
Анализ строчки: 2
Анализ строчки: 3
(2,2)
(3,4)
(2,2)
(3,5)
(2,3)
Анализ строчки: 4
(1,7)
Анализ строчки: 5
(3,5)
(2,4)
(3,3)
(2,12)
(3,4)
(2,3)
Анализ строчки: 6
(1,6)
(2,3)


Помогите пожалуйста разобраться?

Вот исходный код

Код:
//------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;

//------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
   : TForm(Owner)
{
    StringGrid1->Cells[0][0] = "Номер";
   StringGrid1->Cells[1][0] = "Элемент";
   StringGrid2->Cells[0][0] = "Номер";
   StringGrid2->Cells[1][0] = "Элемент";
   StringGrid3->Cells[0][0] = "Номер";
   StringGrid3->Cells[1][0] = "Элемент";
}
// Открыть таблицу "ключевых слов"
void __fastcall TForm1::Button1Click(TObject *Sender)
{
   if (OpenDialog1->Execute())
   {
      TStringList *slist = new TStringList();
      int j = 0;
      slist->LoadFromFile(OpenDialog1->FileName);
      for (int i = 1; i <= slist->Count; i++)
      {
          StringGrid1->Cells[0] = i;
         StringGrid1->Cells[1] = slist->Strings[j];
         j++;
      }
      delete slist;
   }
}
//------------------------------------------------------------------------

void __fastcall TForm1::Button4Click(TObject *Sender)
{
   if (OpenDialog2->Execute())
   {
      TStringList *slist = new TStringList();
      int j = 0;
      slist->LoadFromFile(OpenDialog2->FileName);
      for (int i = 1; i <= slist->Count; i++)
      {
         StringGrid2->Cells[0] = i;
         StringGrid2->Cells[1] = slist->Strings[j];
         j++;
      }
      delete slist;
   }
}
//------------------------------------------------------------------------

void __fastcall TForm1::Button2Click(TObject *Sender)
{
    if (OpenDialog3->Execute())
      Memo1->Lines->LoadFromFile(OpenDialog3->FileName);
}
//---------------------------------------------------------------------------

void __fastcall TForm1::Button5Click(TObject *Sender)
{
   if (OpenDialog4->Execute())
   {
      TStringList *slist = new TStringList();
      int j = 0;
      slist->LoadFromFile(OpenDialog4->FileName);
      for (int i = 1; i <= slist->Count; i++)
      {
         StringGrid3->Cells[0] = i;
         StringGrid3->Cells[1] = slist->Strings[j];
         j++;
      }
      delete slist;
   }
}
//------------------------------------------------------------------------

void __fastcall TForm1::Button3Click(TObject *Sender)
{
    // Количество итераций в цикле столько, сколько
    // строк в исходном коде
    for (int i = 0; i < Memo1->Lines->Count; i++)
    {//
         AnsiString temp = "";
       char *tempstr = (Memo1->Lines->Strings).c_str();
       Memo2->Lines->Add("Анализ строчки: "+IntToStr(i+1));
       // Количестово итераций в цикле столько,
       // сколько символов в строке
       for (int j = 0; j < (Memo1->Lines->Strings).Length(); j++)
       {//2
          // Проверяем является ли символ
          // буквой или цифрой
          if (isalnum(tempstr[j]))
          {//3
            temp += tempstr[j];
            // Проверка символа в таблице "Ключевых слов"
            for (int k = 1; k < StringGrid1->RowCount; k++)
            {//4
               // Находится в таблице "ключевых слов"
               if (StringGrid1->Cells[1] [k] == temp)
               {//5
                  Memo2->Lines->Add("(1,"+StringGrid1->Cells[0] [k]+") ");
                  temp = "";
               }//5
            }//4
            // Проверка символа в таблице "Другие лексемы"
            for (int k = 1; k < StringGrid3->RowCount; k++)
            {//6
               // Находится в таблице "Другие лексемы"
               if (StringGrid3->Cells[1] [k] == temp)
               {//7
                  Memo2->Lines->Add("(3,"+StringGrid3->Cells[0] [k]+") ");
                  temp = "";
               }//7
            }//6
          }//3
          else
          if (tempstr[j] != ' ')
          {//8
            temp = "";
            temp += tempstr[j];
            if ((tempstr[j] == ':' || tempstr[j] == '>' || tempstr[j] == '<') && tempstr[j+1] == '=')
               temp += tempstr[j+1];
            // Проверка символа в таблице "Служебные знаки"
            for (int k = 1; k < StringGrid2->RowCount; k++)
            {//9
               // Находится в таблице "Служебные знаки"
               if (StringGrid2->Cells[1] [k] == temp)
               {//10
                  Memo2->Lines->Add("(2,"+StringGrid2->Cells[0] [k]+") ");
                  temp = "";
               }//10
            }//9
            temp = "";
          }//8
       }//2
    }//1
}
//-----------------------------------------------------------------------


Попробовал вывести в Memo
Там когда анализируется строка var буква "a" вообще прободает.
И ещё не соединяются символы.

То есть получается так в Memo
v
r
А должно быть
v
va
var

когда в место var сравниваешь например input всё нормально.

В чём же дело, помогите пожалуйста?
8.4K
05 апреля 2008 года
Zor
104 / / 23.04.2006
Вот ваш глюк:
char *tempstr = (Memo1->Lines->Strings).c_str();

При работе со списками из других контролов ВСЕГДА создавайте локальную копию:
AnsiString S = Memo1->Lines->Strings;
char *tempstr = S.c_str();
// зачем было указатель вытаскивать - есть же S
===================================

Попутно:
зачем вам 4 (!!!) OpenDialog-а? Чтоб были? Достаточно одного.
код из конструктора убрать - перенесите его в OnCreate
лишний счетчик при загрузке, вполне пойдет:
for (int i = 1; i <= List->Count; i++)
{
StringGrid1->Cells[0] = i;
StringGrid1->Cells[1] = List->Strings[i - 1];
}
11K
05 апреля 2008 года
zuze
84 / / 07.03.2008
Большое спасибо!!!!!!!!!!

Всё заработало.
Вопрос решён.

Только хотелось бы уточнить одну вещь
Почему надо всегда созавать локальную переменную или где об этом можно почитать.
8.4K
05 апреля 2008 года
Zor
104 / / 23.04.2006
почитать можно исходники vcl.
а создавать копию надо потому что строка возвращается в стеке, и c_str возвращает адрес в стеке, и естественно первый вызов любой функции вашу строку уничтожит. прикол от борланда :)
11K
05 апреля 2008 года
zuze
84 / / 07.03.2008
Большое спасибо за пояснение
255
07 апреля 2008 года
Dart Bobr
1.4K / / 09.04.2004
Цитата: Zor

 
Код:
char *tempstr = S.c_str();


Это пример, как делать не надо. И это уже не раз обсуждалось.

8.4K
07 апреля 2008 года
Zor
104 / / 23.04.2006
пока нормально. потом дозреет до S[Index] :)
276
08 апреля 2008 года
Rebbit
1.1K / / 01.08.2005
Если интересует то могу дать свои исходники на паскале которые делают лексический и синтаксический анализ кода под Турбо Паскаль 6.
За 2 прохода розбивает исходник на лексемы и проверяет синтаксис. Пропускает почти все валидные коды. Точно не пропустит writeln(i[COLOR=Red]:10[/COLOR]) и еще помоему в синтаксисе классов была какаято недороботка.
Реклама на сайте | Обмен ссылками | Ссылки | Экспорт (RSS) | Контакты
Добавить статью | Добавить исходник | Добавить хостинг-провайдера | Добавить сайт в каталог