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

Автор: Пользователь скрыл имя, 10 Мая 2011 в 21:35, лабораторная работа

Краткое описание

Цель работы:
Изучение основных понятий теории грамматик простого и операторного предшествования, ознакомление с алгоритмами синтаксического анализа (разбора) для некоторых классов КС-грамматик, получение практических навыков создания простейшего синтаксического анализатора для заданной грамматики операторного предшествования.

Файлы: 1 файл

отчет по 3лабе СА.docx

— 82.91 Кб (Скачать)

    в  таблице }

  begin

    { Цикл  по всем прочитанным лексемам }

    GridLex.RowCount := listLex.Count+1;

    iCnt := listLex.Count-1;

    for i:=0 to iCnt do

    begin

      { Первая колонка - номер }

      GridLex.Cells[0,i+1] := IntToStr(i+1);

      { Вторая колонка - тип лексемы }

      GridLex.Cells[1,i+1] :=

        LexTypeName(listLex[i].LexType);

      { Третья колонка - значение лексемы }

      GridLex.Cells[2,i+1] := listLex[i].LexInfoStr;

    end;

    { Добавляем в конец списка лексем информационную

      лексему "конец строки" }

    with ListIdents do

     listLex.Add(TLexem.CreateInfo('Конец строки',

                          Length(Text),Lines.Count-1,0));

    { Строим дерево синтаксического разбора и

      получаем ссылку на его корень }

    symbRes := BuildSyntList(listLex,symbStack);

    { Если эта ссылка содержит лексические данные,

      значит была ошибка в месте,  указанном лексемой }

    if symbRes.SymbType = SYMB_LEX then

    begin

      MessageDlg(

              Format('Синтаксическая ошибка в строке %d!',

                     [symbRes.Lexem.StrNum+1]),

              mtWarning,[mbOk],0);

      { Берем позицию ошибочной лексемы по ссылке

        и позиционируем на нее список  строк }

      ListIdents.SelStart := symbRes.Lexem.PosAll;

      ListIdents.SetFocus;

      { Освобождаем ссылку на лексему }

      symbRes.Free;

    end

    else

    { Если не было синтаксической ошибки,

      заполняем дерево синтаксического  разбора }

    begin

      { Записываем данные в корень  дерева }

      nodeTree := TreeSynt.Items.Add(nil,

                                     symbRes.SymbolStr);

      { Строим остальные элементы дерева  от его корня }

      MakeTree(nodeTree,symbRes);

      { Раскрываем всё дерево }

      nodeTree.Expand(True);

      { Позиционируем указатель на корневой элемент }

      TreeSynt.Selected := nodeTree;

    end;

  end;

end; 

procedure TLab3Form.MakeTree(

{ Процедура отображения синтаксического дерева }

  nodeTree: TTreeNode;

  {ссылка на корневой элемент отображаемой

   части дерева на экране}

  symbSynt: TSymbol

  {ссылка на синтаксический символ, связанный

   с корневым элементом этой части дерева});

var

  i,iCnt: integer;

  nodeTmp: TTreeNode;

begin

  { Берем количество  дочерних вершин для текущей }

  iCnt := symbSynt.Count-1;

  { Цикл по  всем дочерним вершинам }

  for i:=0 to iCnt do

  begin

    { Добавляем к дереву на экране вершину и

      запоминаем ссылку на нее }

    nodeTmp := TreeSynt.Items.AddChild(nodeTree,

                                symbSynt[i].SymbolStr);

    { Если эта вершина связана с нетерминальным символом,

      рекурсивно вызываем процедуру  построения дерева

      для нее }

    if symbSynt[i].SymbType = SYMB_SYNT then

     MakeTree(nodeTmp,symbSynt[i]);

  end;

end; 

procedure TLab3Form.BtnExitClick(Sender: TObject);

{ Завершение  работы с программой }

begin

  Self.Close;

end; 

end. 
 

unit LexAuto; { 

interface

{ Модуль, обеспечивающий  построение таблицы лексем

  по исходному  тексту программы } 

uses Classes, TblElem, LexType, LexElem; 

{ Функция создания  списка лексем

  по исходному  тексту программы }

function MakeLexList(listFile: TStrings;

                     listLex: TLexList): integer; 

implementation 

uses SysUtils, FncTree; 

type

{ Перечень всех  возможных состояний конечного  автомата }

TAutoPos = (

  AP_START,AP_THEN1,AP_THEN2,AP_THEN3,AP_THEN4,

  AP_ELSE1,AP_ELSE2,AP_ELSE3,AP_ELSE4,AP_IF1,AP_IF2,

  AP_ASSIGN,AP_VAR,AP_CONST,AP_COMM,AP_ERR); 

function MakeLexList(listFile: TStrings;listLex: TLexList): integer;

{ Функция создания  списка лексем

   по исходному  тексту программы }

var

  i,j,iCnt,iStr,   { Переменные и счетчики циклов }

  iAll,    { Счетчик общего количества входных символов }

  iStComm,iStart,comm_pos: integer;

  { Переменные для запоминания позиции начала лексемы }

  posCur: TAutoPos; { Текущее состояние КА }

  sCurStr,sTmp: string;

  { Строки  для временного хранения результатов }

{ Несколько простых  процедур для работы со списком  лексем }

procedure AddVarToList(posNext: TAutoPos; iP: integer);

{ Процедура добавления  переменной в список }

begin

  { Выделяем  имя переменной из текущей  строки }

  sTmp := System.Copy(sCurStr,iStart,iP-iStart);

  { При создании переменной она сначала заносится в таблицу

    идентификаторов,  а потом ссылка на нее -

    в  таблицу лексем }

  listLex.Add(TLexem.CreateVar(AddTreeVar(sTmp),iStComm,i,iStart));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure AddVarKeyToList(keyAdd: TLexType;

                          posNext: TAutoPos);

{ Процедура добавления  переменной и разделителя в  список }

begin

  { Выделяем  имя переменной из текущей  строки }

  sTmp := System.Copy(sCurStr,iStart,j-iStart);

  { При создании переменной она сначала заносится в таблицу

    идентификаторов,  а потом ссылка на нее -

    в  таблицу лексем }

  listLex.Add(TLexem.CreateVar(AddTreeVar(sTmp),iStComm,i,iStart));

  listLex.Add(TLexem.CreateKey(keyAdd,iAll,i,j));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure AddConstToList(posNext: TAutoPos; iP: integer);

{ Процедура добавления  константы в список }

begin

  { Выделяем  константу из текущей строки }

  sTmp := System.Copy(sCurStr,iStart,iP-iStart);

  { Заносим константу в список вместе с ее значением }

  listLex.Add(TLexem.CreateConst(StrToInt(sTmp),iStComm,

                                 i,iStart));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure AddConstKeyToList(keyAdd: TLexType;

                            posNext: TAutoPos);

{ Процедура добавления  константы и разделителя в  список }

begin

  { Выделяем  константу из текущей строки }

  sTmp := System.Copy(sCurStr,iStart,j-iStart);

  { Заносим константу в список вместе с ее значением }

  listLex.Add(TLexem.CreateConst(StrToInt(sTmp),iStComm,

                                 i,iStart));

  listLex.Add(TLexem.CreateKey(keyAdd,iAll,i,j));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure AddKeyToList(keyAdd: TLexType;

                       posNext: TAutoPos);

{ Процедура добавления  ключевого или разделителя слова

  в список }

begin

  listLex.Add(TLexem.CreateKey(keyAdd,iStComm,i,iStart));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure Add2KeysToList(keyAdd1,keyAdd2: TLexType;

                         posNext: TAutoPos);

{ Процедура добавления  ключевого слова и разделителя

  в список  подряд }

begin

  listLex.Add(TLexem.CreateKey(keyAdd1,iStComm,i,iStart));

  listLex.Add(TLexem.CreateKey(keyAdd2,iAll,i,j));

  iStart := j;

  iStComm := iAll-1;

  posCur := posNext;

end;

procedure KeyLetter(chNext: char; posNext: TAutoPos);

{ Процедура проверки  очередного символа ключевого  слова }

begin

  case sCurStr[j] of

    ':': AddVarToList(AP_ASSIGN,j);

    ';': AddVarKeyToList(LEX_SEMI,AP_START);

    '>': AddVarKeyToList(LEX_GT,AP_START);

    '<': AddVarKeyToList(LEX_LT,AP_START);

    '=': AddVarKeyToList(LEX_EQ,AP_START);

    '{': begin AddVarToList(AP_COMM,j); comm_pos:=i;end;

    ' ',#10,#13,#9: AddVarToList(AP_START,j);

    else

      if sCurStr[j] = chNext then posCur := posNext

      else

      if sCurStr[j] in ['0'..'9','A'..'Z','a'..'z','_']

      then posCur := AP_VAR

      else posCur := AP_ERR;

  end{case list};

end;

procedure KeyFinish(keyAdd: TLexType);

{ Процедура проверки  завершения ключевого слова }

begin

  case sCurStr[j] of

    ':': AddKeyToList(keyAdd,AP_ASSIGN);

    '=': Add2KeysToList(keyAdd,LEX_EQ,AP_START);

    '>': Add2KeysToList(keyAdd,LEX_GT,AP_START);

    '<': Add2KeysToList(keyAdd,LEX_LT,AP_START);

    ';': Add2KeysToList(keyAdd,LEX_SEMI,AP_START);

    '0'..'9','A'..'Z','a'..'z','_': posCur := AP_VAR;

    '{': begin AddKeyToList(keyAdd,AP_COMM); comm_pos:=i;end;

    ' ',#10,#13,#9: AddKeyToList(keyAdd,AP_START);

    else posCur := AP_ERR;

  end{case list};

end;

begin

  { Обнуляем  общий счетчик символов и результат  функции }

  iAll := 0;

  Result := 0;

  iStComm := 0;

  { Устанавливаем  начальное состояние конечного  автомата }

  posCur := AP_START;

  { Цикл по  всем строкам входного файла }

  iCnt := listFile.Count-1;

  for i:=0 to iCnt do

Информация о работе Синтаксический анализатор