Сети ЭВМ и телекоммуникации

Содержание

  1. Постановка задачи 2
  2. Теоретические основы разработки трансляторов 3
    1. Построение лексического анализатора 3
    2. Построение синтаксического анализатора 4
  3. Описание синтаксических конструкций …………………………………………...6
  4. Грамматика, описывающая язык…………………………………………………… 8
  5. Управляющая таблица 8
  6. Листинг  программы 9
  7. Результаты работы программы 17
  8. Список литературы  22

 

 

 

1.Постановка  задачи:

 

Создать грамматику, описывающую  конструкцию языка Pascal-оператор if. Для этой грамматики разработать интерпретатор, обеспечивающий показ промежуточных шагов анализа (лексический анализ, синтаксический анализ, построение дерева вывода и синтаксическое дерево).

 

 

2.Теоретические основы разработки трансляторов

 

Процесс интерпретации исходной программы происходит в несколько этапов:

- лексический анализ;

- синтаксический и семантический анализ;

- выполнение программы

 

2.1 Построение лексического анализатора

 

На этапе лексического анализа  символы, составляющие исходную программу,  считываются и группируются в отдельные лексические элементы,  называемые лексемами.  Лексический анализ важен по следующим причинам:

- замена в программе идентификаторов  и констант лексемами делает  представление программы удобнее  для дальнейшей обработки;

- уменьшается  длина программы, т.к. из нее  устраняются несущественные пробелы и комментарии.

С точки  зрения реализации процесса сканирования различают два подхода - прямой и  непрямой лексический анализ. При  прямом лексическом анализе требуется найти одну из многих лексем,  которые заданы в описании данного языка.

Моделью прямого  лексического анализатора  служит множество работающих параллельно конечных автоматов (КА), каждый из которых распознает лексемы заданного типа.  Эти КА можно представить и реализовать  как один конечный преобразователь, моделирующий работу всех КА и выдающий сигнал о том, какой из них распознал очередную лексему.

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

Синтаксический  анализатор обращается к SCAN всякий раз, когда ему нужен новый символ при анализе текста программы  и построения ее внутреннего  представления. В ответ на вызов, SCAN распознает очередную лексему в исходной программе  и передает ее анализатору через таблицу лексем.

Непрямой сканер более экономичен ( в смысле экономии памяти), т.к. он не создает полной таблицы лексем для всего исходного текста программы.

Распознавание лексем выполняется  следующим образом:

- входная цепочка считывается  до тех пор, пока КА не  достигнет заключительного состояния;

- по достижению заключительного  состояния КА  сигнализирует о нахождению лексемы данного типа и сканер заносит информацию о ней в таблицу имен  (символов).

Таким образом, проблему построения непрямого  лексического анализатора для данного типа лексем можно представить как проблему построения и реализации КА, который по достижению заключительного состояния, выдает на выходе  лексему ( в этом смысле его можно рассматривать и как конечный преобразователь

При создании нового языка часто  удобно описывать его конструкции  с помощью синтаксических диаграмм, а затем преобразовать в какую-либо грамматику.

Для выполнения такого преобразования  надо разметить синтаксическую диаграмму нетерминальными символами , используя следующие правила :

  1. вершина синтаксической диаграммы помечается начальным символом  грамматики S ;
  2. между двумя подряд идущими терминальными символами вставляется нетерминальный символ AÎ N ;
  3. перед альтернативой (разветвлением на несколько ветвей) ставиться только один нетерминальный символ  AÎN ;
  4. перед выходящими ветвями итерации (цикла ) ставится один нетерминальный символ .

Далее следует записать правила  грамматики для каждого нетерминального символа. Все правила должны иметь вид : A® aB или A® a, где A , B Î N , a Î S È {e} (регулярная грамматика ) . При задании условий следует пользоваться следующими правилами :

1. Если два нетерминала А и В связаны одной ветвью  направленной от А к В и содержащей терминал а, то правило имеет вид     А ® аВ.

2. Если два нетерминала А и В связаны несколькими ветвями, направленными от А к В и содержащими терминалы a,b,..c, то правило имеет вид   А® аВ½bB½...½cB.

3. Если среди ветвей, связывающих нетерминалы А и В, содержится пустая (не содержащая терминалов) ветвь и имеется ветвь, связывающая В и С, содержащая терминал а , тогда правило имеет вид А® аС , то есть нетерминал В пропускается .

В процессе работы сканера должна быть сформирована таблица имен для хранения информации о лексемах. Эта информация используется в дальнейшем для семантического контроля исходного текста программы и при генерации кода (при конструировании компилятора).

Таким образом, после распознавания  каждой лексемы, сканер должен занести в таблицу имен их характеристики (атрибуты). К этим атрибутам относятся: класс лексемы (обозначаемый обычно во внутреннем  представлении целым числом), фактическое значение лексемы (фактическое символическое имя), дополнительная информация.

 

2.2 Построение синтаксического анализатора

 

Синтаксический анализ подразумевает процесс анализа символьных цепочек с целью распознавания “правильных” или “неправильных” языковых конструкций. получение и представлении этой информации в виде дерева разбора или другой структуры. Эта структура называется промежуточной программой и используется для генерации кода.

Синтаксический анализ, в ходе которого уясняется структура анализируемой  цепочки лексем, называется синтаксическим разбором. Выделяют два вида разбора – левый и правый.

Левым разбором цепочки a называется последовательность правил, примененных при левом выводе цепочки a из S.

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

Эти разборы можно  представить в виде последовательности номеров из множества правил анализируемой грамматики.

Большинство методов  синтаксического анализа делят  на два класса разбора, – нисходящего и восходящего. Анализаторы, реализующие методы нисходящего разбора, выдают на выходе левые разборы и называются левыми анализаторами, а реализующие методы восходящего разбора, выдают правые разборы и называются правыми анализаторами. Эти анализаторы можно моделировать при помощи соответствующих МП - преобразователей.

Попытка реализации МП-преобразователей для широкого класса КС-грамматик приводит к так называемым алгоритмам с “возвратами”, которые требуют слишком больших затрат времени. На практике обычно ограничивают классы грамматик таким образом, чтобы сделать процесс разбора полностью детерминированным. Требованиям детерминированности левых анализаторов наилучшим образом удовлетворяют так называемые LL(k)-грамматики, для которых левый анализатор работает детерминировано, если позволить ему принимать во внимание k входных символов, расположенных справа от текущей входной позиции. Входная цепочка считывается таким анализатором один раз слева направо и в процессе анализа не происходит возвратов к уже прочитанной части цепочки. Такие анализаторы называются однопроходными. Иначе говоря, G будет LL(k)-грамматикой, если для данной цепочки w AaÎ(NUE)* и первых k символов (если они есть), выводящихся из Aa, существует не более одного правила, которое можно применить к A, чтобы получить вывод какой-нибудь терминальной цепочки, начинающейся с w и продолжающейся упомянутыми k терминальными символами.

Разбор для LL(k)-грамматики удобно  осуществлять с помощью так называемого k-предсказывающего  алгоритма разбора, k-предсказывающий алгоритм А для КС-грамматики  G=(N,S,P,S)  использует входную ленту, магазин и выходную ленту и, по существу, моделирует работу МП-преобразователя, опустошающего магазин.

При чтении анализируемой цепочки, находящейся на  входной  ленте, входная головка может “заглядывать вперед” на k очередных символов.

На каждом такте сначала определяется  аванцепочка u и верхний символ магазина Х. Затем рассматривается элемент М(Х, u) управляющей таблицы и в соответствии с его содержанием выполняется одно из 4 действий:

1) если М(Х, u) = (b, i), то (x, Xa, p) (x, ba, p i), т.е. верхний символ магазина заменяется цепочкой b  и к выходу добавляется номер правила i, входная головка не сдвигается;

2) если М(а, u)= «выброс» и x=a , то (x, aa, p) ( , a, p), т.е. если верхний символ магазина совпадает с текущим входным символом, то он выбрасывается из магазина и входная головка сдвигается на один символ вправо;

3) если алгоритм достигает конфигурации (e, $, p), работа прекращается и выходная цепочка p называется разбором первоначальной входной цепочки. Будем считать, что M($, e) = «допуск» и (e, $, p) — допускающая конфигурация;

4) если M(Х, u)= «ошибка», то разбор прекращается и выдается сообщение об ошибке, а соответствующая конфигурация (x, Xa, p) называется ошибочной.

Для построения корректной управляющей таблицы М для заданной LL(1)-грамматики можно использовать следующий алгоритм:

Вход алгоритма: заданная LL(1)-грамматика G=(N, S, P, S).

Выход алгоритма: управляющая таблица М.

Описание алгоритма.

$ — маркер дна магазина. Таблица М определяется на множестве (N È S È {$})´(S È {e}) следующим образом:

1) если А®a — правило из P с номером i, то М(А, а) = (a, i) для всех (а¹е)ÎFIRST1(a); если еÎFIRST1(a), то М(А, b) = (a, i) для всех bÎFOLLOW1(A);

2) М(а, а) = «выброс» для всех аÎS;

3) М($, е) = «допуск»;

4) в остальных случаях М(X, а)= «ошибка» для XÎ N È S È {$} и аÎS È {e}.

 

3. Описание синтаксических конструкций

 

Синтаксическая диаграмма  оператора присваивания:

Выражение оператора условия:

 

Синтаксическая диаграмма конструкции  If

 

 

 

 

 

 

Синтаксическая диаграмма описания переменных

 

 


 

 

 

 

 

 

 

 

 

 

 

 

4 Грамматика, описывающая язык.

 

1)  S -> VAR PER; IF A THEN B ELSE B           12) I->+TI 

2) PER->K: INTEGER; M: DOUBLE;                 13) I->-TI

3) K -> F,F                                                         14) J->*FJ

4) F-> P                                                              15) J->/FJ

5) M-> F,F                                                          16) B->P:=E

6) A->E>E                                                           17) I->e          

7) A->E<E                                                          18) J->e               

8) E->TI                                                        

9) T->FJ                                                      

10) F->P                                                         

11) F->(E)       

 

5.Управляющая таблица такого анализатора построена по приведённому выше алгоритму и приведена ниже.

 
6.Листинг  программы:

unit Unit1;

 

interface

 

uses

  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,

  Dialogs, DB, ADODB, Grids, ComCtrls, StdCtrls, Buttons, XPMan, ExtCtrls;

 

type

  TForm1 = class(TForm)

    Memo1: TMemo;

    BitBtn1: TBitBtn;

    AT: TADOTable;

    ADOConnection1: TADOConnection;

    DataSource1: TDataSource;

    Button2: TButton;

    Kontr: TPageControl;

    TabSheet1: TTabSheet;

    StringGrid1: TStringGrid;

    TabSheet2: TTabSheet;

    StringGrid_UprTabl: TStringGrid;

    TabSheet4: TTabSheet;

    TV: TTreeView;

    OpenDialog1: TOpenDialog;

    TabSheet3: TTabSheet;

    TVV: TTreeView;

    TabSheet5: TTabSheet;

    Memo2: TMemo;

    TabSheet6: TTabSheet;

    Memo3: TMemo;

    GroupBox1: TGroupBox;

    GroupBox2: TGroupBox;

    Image1: TImage;

    Image2: TImage;

    procedure BitBtn1Click(Sender: TObject);

    procedure FormCreate(Sender: TObject);

   procedure Button2Click(Sender: TObject);

procedure SintaxTree(T:TTreenode; l,r: integer);

    procedure BuildSintaxTree;

    procedure Button3Click(Sender: TObject);

 

 

  private

    { Private declarations }

    StrCount :integer;

    Pri :array [1..255] of integer;

    Str :array [1..255] of string;

    procedure RecBuildTree(T: TTreeNode; i :integer);

 

  public

    { Public declarations }

  end;

 

var

  Form1: TForm1;

    globalX,GlobalY:integer;

 

 

implementation

 

var typ:array [3..10] of string=('Îïåðàòîð ïðèñâàèâàíèÿ','Çíàê ñðàâíåíèÿ','Çíàê îïåðàöèè','Ïåðåìåííàÿ','Öåëîå ÷èñëî','Ñêîáêà','Çàðåçåðâèðîâàíîå ñëîâî','Âåùåñòâåííîå ÷èñëî');

list:array [1..100] of string;

listZ:array [1..100] of integer;

list_cur:integer;

 

{$R *.dfm}

procedure LoadTiGrid();

var i,j,b,bj:integer;

begin

                form1.AT.First;

    for j:=0 to 28 do    begin

    for i:=0 to 17 do    begin

              form1.StringGrid_UprTabl.Cells[i,j+1]:=form1.AT.Fields.Fields[i].AsString;

                          end;

              form1.AT.Next;

                          end;

form1.StringGrid_UprTabl.Cells[1,0]:='VAR';

form1.StringGrid_UprTabl.Cells[2,0]:='IF';

form1.StringGrid_UprTabl.Cells[3,0]:='THEN';

form1.StringGrid_UprTabl.Cells[4,0]:='ELSE';

form1.StringGrid_UprTabl.Cells[5,0]:='ZN';

form1.StringGrid_UprTabl.Cells[6,0]:='P';

form1.StringGrid_UprTabl.Cells[7,0]:='(';

form1.StringGrid_UprTabl.Cells[8,0]:=')';

form1.StringGrid_UprTabl.Cells[9,0]:='+';

form1.StringGrid_UprTabl.Cells[10,0]:='*';

form1.StringGrid_UprTabl.Cells[11,0]:=';';

form1.StringGrid_UprTabl.Cells[12,0]:=':=';

form1.StringGrid_UprTabl.Cells[13,0]:=':';

form1.StringGrid_UprTabl.Cells[14,0]:=',';

form1.StringGrid_UprTabl.Cells[15,0]:='INTEGER';

form1.StringGrid_UprTabl.Cells[16,0]:='DOUBLE';

form1.StringGrid_UprTabl.Cells[17,0]:='e';

form1.StringGrid_UprTabl.Cells[18,0]:='';

form1.StringGrid_UprTabl.Cells[0,0]:='ñèìâîëû';

end;

 

 

Function GetString(s:string;var state:integer):string;

var i:char;max:integer;

begin

if s='' then

  begin

  GetString:='';state:=1;

  exit;

  end;

if s[1]=' ' then

  begin

  GetString:=' ';state:=2;

  exit;

  end;

if length(s)>1 then

if copy(s,1,2)=':=' then

  begin

  GetString:=':=';state:=3;

  exit;

  end;

if length(s)>1 then

if (copy(s,1,2)='<>')or(copy(s,1,2)='<=')or(copy(s,1,2)='>=') then

  begin

  GetString:=copy(s,1,2);state:=4;

  exit;

  end;

if (s[1]='(')or(s[1]=')') then

  begin

  GetString:=s[1];state:=8;

  exit;

  end;

if (s[1]='<')or(s[1]='>') then

  begin

  GetString:=s[1];state:=4;

  exit;

  end;

if (s[1]='/')or(s[1]='*')or(s[1]='-')or(s[1]='+')or(s[1]=';') or(s[1]=',')or(s[1]=':')or(s[1]=',')then

  begin

  GetString:=s[1];state:=5;

  exit;

  end;

 

if length(s)>1 then

if copy(s,1,2)='IF' then

  begin

  GetString:='IF';state:=9;

  exit;

  end;

if length(s)>3 then

if copy(s,1,4)='THEN' then

  begin

  GetString:='THEN';state:=9;

  exit;

  end;

  if length(s)>3 then

if copy(s,1,4)='ELSE' then

  begin

  GetString:='ELSE';state:=9;

  exit;

  end;

   if length(s)>2 then

  if copy(s,1,3)='VAR' then

  begin

  GetString:='VAR';state:=9;

  exit;

  end;

     if length(s)>6 then

  if copy(s,1,7)='INTEGER' then

  begin

  GetString:='INTEGER';state:=9;

  exit;

  end;

  if length(s)>5 then

  if copy(s,1,6)='DOUBLE' then

  begin

  GetString:='DOUBLE';state:=9;

  exit;

  end;

 

   if ((s[1]>='A')and(s[1]<='Z')) then

  begin

  max:=1000;

  for i:=#0 to #255 do

    begin

    if not(((i>='A')and(i<='Z'))or((i>='0')and(i<='9'))) then

      if (pos(i,s)>0)and(pos(i,s)<max) then max:=pos(i,s);

    end;

  if max=1000 then max:=length(s);

  GetString:=copy(s,1,max-1);state:=6;

  exit;

  end;

 

 

if (s[2]='.') then

  begin

  max:=1000;

  for i:=#0 to #255 do

    begin

    if not(((i>='0')and(i<='9'))or((i='.'))) then

      if (pos(i,s)>0)and(pos(i,s)<max) then max:=pos(i,s) ;

    end;

  if max=1000 then max:=length(s);

  GetString:=copy(s,1,max-1);state:=10;

  exit;

  end;

 

 

  if (s[1]='0')or(s[1]='1')or(s[1]='2')or(s[1]='3')or(s[1]='4')or(s[1]='5')or(s[1]='6')or(s[1]='7')or(s[1]='8')or(s[1]='9') then

  begin

  GetString:=s[1];state:=7;

  exit;

  end;

 

 

 

 

state:=0;

GetString:='error';

end;

 

 

 

 

procedure TForm1.BitBtn1Click(Sender: TObject);

var

s,s1:string;

i,state:integer;

begin

list_cur:=0;

stringgrid1.RowCount:=2;

for i:=0 to memo1.Lines.Count do

  begin

  s:=' ';

  s1:=memo1.Lines[i];

  while (s<>'')and(s<>'error') do

    begin

    s:=GetString(UpperCase(s1),state);

    if (length(s)<=length(s1))and(length(s)>0) then

    begin

      delete(s1,1,length(s));

      if (s<>' ')and(s<>'error') then

        begin

        stringgrid1.Cols[0][stringgrid1.RowCount-1]:=typ[state];

        stringgrid1.Cols[1][stringgrid1.RowCount-1]:=s;

        stringgrid1.RowCount:=stringgrid1.RowCount+1;

        inc(list_cur);

        list[list_cur]:=s;

        listZ[list_cur]:=state;

        end;

      end;

    if s='error' then messagebox(0,'error',0,0);

    end;

  end;

end;

  Function Find(x,y:string):string;

var i,j,bi,bj:integer;

begin

  form1.AT.RecNo:=1;

  bi:=100;bj:=100;

  for i:=1 to form1.at.FieldCount-1 do

    if x=form1.AT.Fields.Fields[i].FieldName then bi:=i;

  for j:=1 to form1.at.RecordCount do begin

    if j>1 then form1.AT.RecNo:=form1.AT.RecNo+1;

    if y=form1.at.Fields.Fields[0].AsString then bj:=j;

    end;

  form1.AT.RecNo:=bj;

  if (bi<100)and(bj<100) then

    Find:=form1.at.Fields.Fields[bi].AsString

    else Find:='Error';

    globalX:=bi;

    GlobalY:=bj;

end;

 

 

 

 

procedure TForm1.FormCreate(Sender: TObject);

begin

stringgrid1.Cols[0][0]:='Type';

stringgrid1.Cols[1][0]:='Value';

LoadTiGrid();

 

end;

procedure TForm1.Button2Click(Sender: TObject);

var

  st:string;

  Rez,inP:string;

  stek:array [1..100] of string;

  stek_cur,i,j,k,m{,s_c}:integer;

  bExt,bDel,bRez:boolean;

  cur,cur1,cu,cu1:TTreeNode;

     m_i:integer;

     s_temp_stek,s_temp_str,s_temp_rules:string;

     ruls:integer;

begin

s_temp_rules:='';

  BitBtn1Click(Sender);

  bRez:=True;

  tv.Items.Clear;

  tv.Items.Add(nil,'Äåðåâî  âûâîäà');

  cur:=tv.Items.Item[0];

  cu:=tvv.Items.Item[0];

 

  Stek[1]:='$';

  Stek[2]:='START';

  Stek_cur:=2;

 

  inc(list_cur);

  list[list_cur]:='e';

  i:=1;

  bExt:=false;

  while not(bExt) do begin

     case listz[i] of

        4:inP:='ZN';

        6,7,10:inP:='P';

         5:begin

        if List[i]=';' then inp:=';';

        if List[i]=',' then inp:=',';

        if List[i]=':' then inp:=':';

         if (List[i]='+')or(List[i]='-') then inp:='+';

          if (List[i]='/')or(List[i]='*') then inp:='*';

          end;

        else inP:=List[i];

        end;

 

     Rez:= Find(inP,Stek[stek_cur]);  //s_temp_stek,s_temp_str

      //////////////////////////////////////

      s_temp_stek:='';

      s_temp_str:='';

       for m_i:=1 to stek_cur do s_temp_stek:=s_temp_stek+Stek[m_i];

       for m_i:=i to list_cur-1 do s_temp_str:=s_temp_str+list[m_i];

 

        //form1.Memo2.Lines.Add(s_temp_str+'  -  '+s_temp_stek+'    -    '+inP);// íàéäåííûé ýëåìåíò  inP

        //form1.Memo2.Lines.Add(s_temp_str+'  -  '+s_temp_stek+'    -    '+inttostr(listz[stek_cur]));

      //////////////////////////////////////////

     if (Rez='Error')or(Rez='') then begin

              bExt:=True;

              bRez:=False;

              MessageBox(0,'Îøèáêà àíàëèçà òåêñòà','',0);

              end;

     if (Rez='DOPUSK') then begin

              bExt:=True;

              bRez:=True;

              form1.Memo2.Lines.Add('['+s_temp_str+'e'+','+s_temp_stek+','+ s_temp_rules+']');

             // MessageBox(0,'Òåêñò ïðîàíàëèçèðîâàí','',0);

              end;

     if (Rez='VYBROS') then begin

              cur.Text:=list[i];

              inc(i);

              dec(stek_cur);

              cur1:=cur.GetNext;

              cur:=cur1;

             form1.Memo2.Lines.Add('['+s_temp_str+','+s_temp_stek+','+ s_temp_rules+']');

              end

      else if not(bExt) then begin

 

 

              dec(stek_cur);

              k:=2;

              for j:=1 to length(rez) do

                if rez[j]=' ' then k:=k+1;

 

              m:=stek_cur;

              if Rez[1]<>'e' then begin

 

                 if  (globaly = 18) then globaly:=7;

                 if  (globaly = 19) then globaly:=8;

 

                s_temp_rules:=s_temp_rules+' '+inttostr(globaly);

 

                while pos(' ',rez)>0 do begin

                  inc(stek_cur);

                  Stek[k+m+m-stek_cur]:=copy(rez,1,pos(' ',rez)-1);

                  delete(rez,1,pos(' ',rez));

                  end;

                inc(stek_cur);

                Stek[{stek_cur}m+1]:=rez;

              for j:=stek_cur downto m+1 do

                 cur1:=tv.Items.AddChild(cur,Stek[j]);

              cur:=cur1.Parent.getFirstChild;

              end

              else begin

                tv.Items.AddChild(cur,'e');

                cur:=cur.GetNext.GetNext;

 

                end;

              end;

    end;

//if bRez then BuildSintaxTree;

end;

 

procedure TForm1.RecBuildTree(T: TTreeNode; i :integer);

var

   j :integer;

begin

     if T.Count=0 then

     begin

       if T.Text = 'e' then

         Exit;

       if T.Text = ')' then

         Exit;

       if T.Text = '(' then

         Exit;

      if T.Text = ';' then

         Exit;

      if T.Text = ',' then

         Exit;

     if T.Text = ':' then

         Exit;

 

   if T.Text = 'VAR' then

         Exit;

 

   if T.Text = 'INTEGER' then

         Exit;

 

   if T.Text = 'DOUBLE' then

         Exit;

 

 

   if T.Text = 'THEN' then

         Exit;

 

   if T.Text = 'ELSE' then

         Exit;

 

       Inc(StrCount);

       Pri[StrCount]:=i;

       Str[StrCount]:=T.Text;

     end

     else

       for j:=T.Count-1 downto 0 do

         RecBuildTree(T.Item[j], i+1);

end;

 

procedure TForm1.BuildSintaxTree;

var i: integer;

    T: TTreeNode;

begin

     StrCount:=0;

     RecBuildTree(TV.TopItem, 0);

     for i:= 1 to StrCount do

      if (Str[i]<>'+')and(Str[i]<>'*')and(Str[i]<>'-')and(Str[i]<>'/')and(Str[i]<>'IF')and(Str[i][1]<>'>')and(Str[i][1]<>'<') then Pri[i]:=0;

     TVV.Items.Clear;

     if StrCount = 1 then TVV.Items.AddChild(nil,str[1])

     else

     begin

       T:= nil;

       SintaxTree(T,1,StrCount);

     end;

end;

 

procedure TForm1.SintaxTree(T: TTreenode; l, r: integer);

var i, min,m,mmin,ii,jj: integer;

    T1,T2: TTreeNode;

begin

  if r-l < 2 then

   begin

     T.Text:=str[l];

   end

   else

   begin

     min:=maxInt;

     for i:= l to r do

      if (pri[i] <= min)and(pri[i]<>0) then begin

        min:= pri[i];

        m:=i;

        end;

     i:=m;

     if T = nil then

     begin

       T1:=TVV.Items.AddChild(T,str[i]);

       TVV.Items.AddChild(T1,'');

       TVV.Items.AddChild(T1,'');

       T:= T1;

     end

     else

     begin

       T.Text:=str[i];

       TVV.Items.AddChild(T,'');

       TVV.Items.AddChild(T,'');

     end;

     if T.Text<>'IF'  then begin

       if T.Text<>':=' then begin

        SintaxTree(T.Item[1],l,i-1);

        SintaxTree(T.Item[0],i+1,r);

        end else begin

        SintaxTree(T.Item[0],i+1,r);

        mmin:=0;

        for ii:=l to i-1 do

          if str[ii]=':=' then mmin:=ii;

        if mmin>0 then begin

          SintaxTree(T.Item[1],mmin+2,i-1);

          T2:=TVV.Items.AddChild(T.Parent,'');

          SintaxTree(T2,l,mmin+1);

          end

          else SintaxTree(T.Item[1],l,i-1);

        end;

     end else begin

        jj:=1;

        while(pri[jj]>0)or(pri[jj+1]>0) do inc(jj);

        SintaxTree(T.Item[0],l,{l+2}jj);

        SintaxTree(T.Item[1],{l+3}jj+1,r-1);

 

     end;

 

      end;

   end;

 

procedure TForm1.Button3Click(Sender: TObject);

begin

if OpenDialog1.Execute then memo1.Lines.LoadFromFile(OpenDialog1.FileName);

end;

 

 

 

end.

7. Результаты работы программы

 

 

 

 

 

 
8. Список литературы

 

  1. Иванченко А.Н., Гавриков М.М., Гринченков Д.В. Теоретические основы разработки компиляторов. Учеб. пос. – Новочеркасск: ЮРГТУ, 2006.



Сети ЭВМ и телекоммуникации