Ñîâðåìåííàÿ ýëåêòðîííàÿ áèáëèîòåêà ModernLib.Net

Äàâàéòå ñîçäàäèì êîìïèëÿòîð!

ModernLib.Net / Ïðîãðàììèðîâàíèå / Êðåíøîó Äæåê / Äàâàéòå ñîçäàäèì êîìïèëÿòîð! - ×òåíèå (ñòð. 12)
Àâòîð: Êðåíøîó Äæåê
Æàíð: Ïðîãðàììèðîâàíèå

 

 


      Íàêîíåö, ìû äîëæíû âíåñòè èçìåíåíèÿ, ïîçâîëÿþùèå èñïîëüçîâàòü Token âìåñòî Look êàê ñèìâîëà äëÿ ïðîâåðêè è âûçûâàòü Scan â ïîäõîäÿùèõ ìåñòàõ. Ïî áîëüøåé ÷àñòè ýòî âêëþ÷àåò óäàëåíèå âûçîâîâ Match, ðåäêèå çàìåíû âûçîâîâ Match íà âûçîâû MatchString, è çàìåíó âûçîâîâ NewLine íà âûçîâû Scan. Âîò çàòðîíóòûå ïîäïðîãðàììû:
      {–}
      { Recognize and Translate an IF Construct }
      procedure Block; Forward;
      procedure DoIf;
      var L1, L2: string;
      begin
      BoolExpression;
      L1 := NewLabel;
      L2 := L1;
      BranchFalse(L1);
      Block;
      if Token = 'l' then begin
      L2 := NewLabel;
      Branch(L2);
      PostLabel(L1);
      Block;
      end;
      PostLabel(L2);
      MatchString('ENDIF');
      end;
      {–}
      { Parse and Translate a WHILE Statement }
      procedure DoWhile;
      var L1, L2: string;
      begin
      L1 := NewLabel;
      L2 := NewLabel;
      PostLabel(L1);
      BoolExpression;
      BranchFalse(L2);
      Block;
      MatchString('ENDWHILE');
      Branch(L1);
      PostLabel(L2);
      end;
      {–}
      { Parse and Translate a Block of Statements }
      procedure Block;
      begin
      Scan;
      while not(Token in ['e', 'l']) do begin
      case Token of
      'i': DoIf;
      'w': DoWhile;
      else Assignment;
      end;
      Scan;
      end;
      end;
      {–}
      { Parse and Translate Global Declarations }
      procedure TopDecls;
      begin
      Scan;
      while Token <> 'b' do begin
      case Token of
      'v': Decl;
      else Abort('Unrecognized Keyword ' + Value);
      end;
      Scan;
      end;
      end;
      {–}
      { Parse and Translate a Main Program }
      procedure Main;
      begin
      MatchString('BEGIN');
      Prolog;
      Block;
      MatchString('END');
      Epilog;
      end;
      {–}
      { Parse and Translate a Program }
      procedure Prog;
      begin
      MatchString('PROGRAM');
      Header;
      TopDecls;
      Main;
      Match('.');
      end;
      {–}
      { Initialize }
      procedure Init;
      var i: char;
      begin
      for i := 'A' to 'Z' do
      ST[i] := ' ';
      GetChar;
      Scan;
      end;
      {–}
      Ýòî äîëæíî ðàáîòàòü. Åñëè âñå èçìåíåíèÿ ñäåëàíû ïðàâèëüíî, âû äîëæíû òåïåðü àíàëèçèðîâàòü ïðîãðàììû, êîòîðûå âûãëÿäÿò êàê ïðîãðàììû. (Åñëè âû íå ñäåëàëè âñåõ èçìåíåíèé, íå îò÷àèâàéòåñü. Ïîëíûé ëèñòèíã êîíå÷íîé ôîðìû äàí íèæå.)
      Ðàáîòàåò? Åñëè äà, òî ìû ïî÷òè äîìà. Ôàêòè÷åñêè, ñ íåñêîëüêèìè íåáîëüøèìè èñêëþ÷åíèÿìè, ìû óæå ïîëó÷èëè êîìïèëÿòîð, ïðèãîäíûé äëÿ èñïîëüçîâàíèÿ. Èìåþòñÿ åùå íåñêîëüêî îáëàñòåé, òðåáóþùèõ óñîâåðøåíñòâîâàíèÿ.

Ìíîãîñèìâîëüíûå èìåíà ïåðåìåííûõ

      Îäíà èç íèõ – îãðàíè÷åíèå, òðåáóþùåå èñïîëüçîâàíèÿ îäíîñèìâîëüíûõ èìåí ïåðåìåííûõ. Òåïåðü, êîãäà ìû ìîæåì îáðàáàòûâàòü ìíîãîñèìâîëüíûå êëþ÷åâûå ñëîâà, ýòî îãðàíè÷åíèå íà÷èíàåò êàçàòüñÿ ïðîèçâîëüíûì è íåíóæíûì. È äåéñòâèòåëüíî ýòî òàê.  îñíîâíîì, åäèíñòâåííîå åãî äîñòîèíñòâî â òîì, ÷òî îí ïîçâîëÿåò ïîëó÷èòü òðèâèàëüíî ïðîñòóþ ðåàëèçàöèþ òàáëèöû èäåíòèôèêàòîðîâ. Íî ýòî ïðîñòî óäîáñòâî äëÿ ñîçäàòåëåé êîìïèëÿòîðîâ è îíî äîëæíî áûòü óíè÷òîæåíî.
      Ìû óæå äåëàëè ýòîò øàã ïðåæäå. Íà ýòîò ðàç, êàê îáû÷íî, ÿ ñäåëàþ ýòî íåìíîãî ïî-äðóãîìó. ß äóìàþ ïîäõîä, ïðèìåíåííûé çäåñü, ñîõðàíèò ïðîñòîòó íàñòîëüêî, íàñêîëüêî ýòî âîçìîæíî.
      Åñòåñòâåííûì ïóòåì ðåàëèçàöèè òàáëèöû èäåíòèôèêàòîðîâ íà Pascal ÿâëÿåòñÿ îáúÿâëåíèå ïåðåìåííîé òèïà çàïèñü è ñîçäàíèå òàáëèöû èäåíòèôèêàòîðîâ êàê ìàññèâà òàêèõ çàïèñåé. Çäåñü, îäíàêî, íàì â äåéñòâèòåëüíîñòè ïîêà íå íóæíî ïîëå òèïà (ñóùåñòâóåò ïîêà ÷òî òîëüêî îäèí ðàçðåøåííûé òèï), òàê ÷òî íàì íóæåí òîëüêî ìàññèâ ñèìâîëîâ. Ýòî èìååò ñâîå ïðåèìóùåñòâî, ïîòîìó ÷òî ìû ìîæåì èñïîëüçîâàòü ñóùåñòâóþùóþ ïðîöåäóðó Lookup äëÿ ïîèñêà â òàáëèöå èäåíòèôèêàòîðîâ òàêæå êàê è â ñïèñêå êëþ÷åâûõ ñëîâ. Îêàçûâàåòñÿ, äàæå êîãäà íàì íóæíû áîëüøå ïîëåé, ìû âñå ðàâíî ìîæåì èñïîëüçîâàòü òîò æå ñàìûé ïîäõîä, ïðîñòî ñîõðàíÿÿ äðóãèå ïîëÿ â îòäåëüíûõ ìàññèâàõ.
      Âîò èçìåíåíèÿ, êîòîðûå íåîáõîäèìî ñäåëàòü. Ñïåðâà äîáàâüòå íîâóþ òèïèçèðîâàííóþ êîíñòàíòó:
      NEntry: integer = 0;
      Çàòåì èçìåíèòå îïðåäåëåíèå òàáëèöû èäåíòèôèêàòîðîâ êàê ïîêàçàíî íèæå:
      const MaxEntry = 100;
      var ST : array[1..MaxEntry] of Symbol;
      (Îáðàòèòå âíèìàíèå, ÷òî ST íå îáúÿâëåí êàê SymTab. Ýòî îáúÿâëåíèå ëèïîâîå, ÷òîáû çàñòàâèòü Lookup ðàáîòàòü. SymTab çàíÿëÿ áû ñëèøêîì ìíîãî ïàìÿòè è ïîýòîìó ôàêòè÷åñêè íèêîãäà íå îáüÿâëÿåòñÿ).
      Çàòåì ìû äîëæíû çàìåíèòü InTable.
      {–}
      { Look for Symbol in Table }
      function InTable(n: Symbol): Boolean;
      begin
      InTable := Lookup(@ST, n, MaxEntry) <> 0;
      end;
      {–}
      Íàì òàêæå íåîáõîäèìà íîâàÿ ïðîöåäóðà AddEntry, êîòîðàÿ äîáàâëÿåò íîâûé ýëåìåíò â òàáëèöó:
      {–}
      { Add a New Entry to Symbol Table }
      procedure AddEntry(N: Symbol; T: char);
      begin
      if InTable(N) then Abort('Duplicate Identifier ' + N);
      if NEntry = MaxEntry then Abort('Symbol Table Full');
      Inc(NEntry);
      ST[NEntry] := N;
      SType[NEntry] := T;
      end;
      {–}
      Ýòà ïðîöåäóðà âûçûâàåòñÿ èç Alloc:
      {–}
      { Allocate Storage for a Variable }
      procedure Alloc(N: Symbol);
      begin
      if InTable(N) then Abort('Duplicate Variable Name ' + N);
      AddEntry(N, 'v');
      .
      .
      .
      {–}
      Íàêîíåö, ìû äîëæíû èçìåíèòü âñå ïîäïðîãðàììû, êîòîðûå â íàñòîÿùåå âðåìÿ îáðàáàòûâàþò èìåíà ïåðåìåííûõ êàê îäèíî÷íûé ñèìâîë. Îíè âêëþ÷àþò LoadVar è Store (ïðîñòî èçìåíèòå òèï ñ char íà string) è Factor, Assignment è Decl (ïðîñòî èçìåíèòå Value[1] íà Value).
      Ïîñëåäíÿÿ âåùü: èçìåíèòå ïðîöåäóðó Init äëÿ î÷èñòêè ìàññèâà êàê ïîêàçàíî íèæå:
      {–}
      { Initialize }
      procedure Init;
      var i: integer;
      begin
      for i := 1 to MaxEntry do begin
      ST[i] := '';
      SType[i] := ' ';
      end;
      GetChar;
      Scan;
      end;
      {–}
      Ýòî äîëæíî ðàáîòàòü. Èñïûòàéòå åå è ïðîâåðüòå, ÷òî âû äåéñòâèòåëüíî ìîæåòå èñïîëüçîâàòü ìíîãîñèìâîëüíûå èìåíà ïåðåìåííûõ.

Ñíîâà îïåðàòîðû îòíîøåíèé

      Ó íàñ îñòàëîñü ïîñëåäíåå îäíîñèìâîëüíîå îãðàíè÷åíèå – îãðàíè÷åíèå îïåðàòîðîâ îòíîøåíèé. Íåêîòîðûå èç îïåðàòîðîâ îòíîøåíèé äåéñòâèòåëüíî ñîñòîÿò èç îäèíî÷íûõ ñèìâîëîâ, íî äðóãèå òðåáóþò äâóõ. Ýòî '<=' è '>='. ß òàêæå ïðåäïî÷èòàþ Ïàñêàëåâñêîå '<>' äëÿ «íå ðàâíî» âìåñòî '#'.
      Êàê âû ïîìíèòå, â ãëàâå 7 ÿ óêàçàë, ÷òî ñòàíäàðòíûé ñïîñîá ðàáîòû ñ îïåðàòîðàìè îòíîøåíèé – âêëþ÷èòü èõ â ñïèñîê êëþ÷åâûõ ñëîâ è ïîçâîëèòü ëåêñè÷åñêîìó àíàëèçàòîðó îòûñêèâàòü èõ. Íî, îïÿòü, ýòî òðåáóåò âûïîëíåíèå ïîëíîãî àíàëèçà âûðàæåíèÿ, òîãäà êàê äî ýòîãî ìû ó íàñ áûëà âîçìîæíîñòü îãðàíè÷èòü èñïîëüçîâàíèå ñêàíåðà íà÷àëîì óòâåðæäåíèÿ.
      ß óïîìÿíóë òîãäà, ÷òî ìû âñå æå ìîæåì èçáåæàòü íåïðèÿòíîñòåé ñ ýòèì, òàê êàê ìíîãîñèìâîëüíûõ îïåðàòîðîâ îòíîøåíèé íåìíîãî è îíè îãðàíè÷åíû â ïðèìåíåíèè. Áûëî áû ëåãêî îáðàáàòûâàòü èõ ïðîñòî êàê ñïåöèàëüíûå ñëó÷àè è ïîääåðæèâàòü èõ ñïåöèàëüíûì ñïîñîáîì.
      Òðåáóåìûå èçìåíåíèÿ âëèÿþò òîëüêî íà ïîäïðîãðàììû ãåíåðàöèè êîäà è ïðîöåäóðû Relation è åå äðóçåé. Ñïåðâà, íàì ïîíàäîáÿòñÿ åùå äâå ïîäïðîãðàììû ãåíåðàöèè êîäà:
      {–}
      { Set D0 If Compare was <= }
      procedure SetLessOrEqual;
      begin
      EmitLn('SGE D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was >= }
      procedure SetGreaterOrEqual;
      begin
      EmitLn('SLE D0');
      EmitLn('EXT D0');
      end;
      {–}
      Çàòåì èçìåíèòå ïîäïðîãðàììû àíàëèçà îòíîøåíèé êàê ïîêàçàíî íèæå:
      {–}
      { Recognize and Translate a Relational «Less Than or Equal» }
      procedure LessOrEqual;
      begin
      Match('=');
      Expression;
      PopCompare;
      SetLessOrEqual;
      end;
      {–}
      { Recognize and Translate a Relational «Not Equals» }
      procedure NotEqual;
      begin
      Match('>');
      Expression;
      PopCompare;
      SetNEqual;
      end;
      {–}
      { Recognize and Translate a Relational «Less Than» }
      procedure Less;
      begin
      Match('<');
      case Look of
      '=': LessOrEqual;
      '>': NotEqual;
      else begin
      Expression;
      PopCompare;
      SetLess;
      end;
      end;
      end;
      {–}
      { Recognize and Translate a Relational «Greater Than» }
      procedure Greater;
      begin
      Match('>');
      if Look = '=' then begin
      Match('=');
      Expression;
      PopCompare;
      SetGreaterOrEqual;
      end
      else begin
      Expression;
      PopCompare;
      SetGreater;
      end;
      end;
      {–}
      Ýòî âñå, ÷òî òðåáóåòñÿ. Òåïåðü âû ìîæåòå îáðàáàòûâàòü âñå îïåðàòîðû îòíîøåíèé. Ïîïðîáóéòå.

Ââîä/Âûâîä

      Òåïåðü ó íàñ åñòü ïîëíûé, ðàáîòàþùèé ÿçûê, çà èñêëþ÷åíèåì îäíîãî íåáîëüøîãî ñìóùàþùåãî ôàêòà: ó íàñ íåò íèêàêîãî ñïîñîáà ïîëó÷èòü èëè âûâåñòè äàííûå. Íàì íóæíû ïîäïðîãðàììû ââîäà/âûâîäà.
      Ñîâðåìåííîå ñîãëàøåíèå, óñòàíîâëåííîå â C è ïðîäîëæåííîå â Ada è Modula-2, ñîñòîèò â òîì, ÷òîáû âûâåñòè I/O îïåðàòîðû èç ñàìîãî ÿçûêà è ïðîñòî âêëþ÷èòü èõ â áèáëèîòåêó ïîäïðîãðàìì. Ýòî áûëî áû ïðåêðàñíî, çà èñêëþ÷åíèåì òîãî, ÷òî ìû ïîêà íå èìååì íèêàêèõ ñðåäñòâ ïîääåðæêè ïîäïðîãðàìì.  ëþáîì ñëó÷àå, ñ ýòèì ïîäõîäîì âû ñòîëêíåòåñü ñ ïðîáëåìîé ïåðåìåííîé äëèíû ñïèñêà ïàðàìåòðîâ.  Ïàñêàëå I/O îïåðàòîðû âñòðîåíû â ÿçûê, ïîýòîìó ýòî åäèíñòâåííûå îïåðàòîðû, äëÿ êîòîðûõ ñïèñîê ïàðàìåòðîâ ìîæåò èìåòü ïåðåìåííîå ÷èñëî ýëåìåíòîâ.  C ìû ïðèìèðÿåìñÿ ñ êëóäæàìè òèïà scanf è printf è äîëæíû ïåðåäàâàòü êîëè÷åñòâî ïàðàìåòðîâ â âûçûâàåìóþ ïðîöåäóðó.  Ada è Modula-2 ìû äîëæíû èñïîëüçîâàòü íåóäîáíûé (è ìåäëåííûé!) ñïîñîá îòäåëüíîãî âûçîâà äëÿ êàæäîãî àðãóìåíòà.
      Òàê ÷òî ÿ äóìàþ, ÷òî ïðåäïî÷èòàþ Ïàñêàëåâñêèé ïîäõîä âñòðàèâàíèÿ ïîäïðîãðàìì ââîäà/âûâîäà, äàæå åñëè ìû íå íóæäàåìñÿ â ýòîì.
      Êàê îáû÷íî, äëÿ ýòîãî íàì íóæíû åùå íåñêîëüêî ïîäïðîãðàìì ãåíåðàöèè êîäà. Îíè, îêàçûâàåòñÿ, ñàìûå ïðîñòûå èç âñåõ, ïîòîìó ÷òî âñå, ÷òî ìû äåëàåì ýòî âûçûâàåì áèáëèîòå÷íûå ïðîöåäóðû äëÿ âûïîëíåíèÿ ðàáîòû.
      {–}
      { Read Variable to Primary Register }
      procedure ReadVar;
      begin
      EmitLn('BSR READ');
      Store(Value);
      end;
      {–}
      { Write Variable from Primary Register }
      procedure WriteVar;
      begin
      EmitLn('BSR WRITE');
      end;
      {–}
      Èäåÿ ñîñòîèò â òîì, ÷òî READ çàãðóæàåò çíà÷åíèå èç âõîäíîãî ïîòîêà â D0, à WRITE âûâîäèò åãî îòòóäà.
      Ýòè äâå ïðîöåäóðû ïðåäñòàâëÿþò ñîáîé íàøó ïåðâóþ âñòðå÷ó ñ ïîòðåáíîñòüþ â áèáëèîòå÷íûõ ïðîöåäóðàõ... êîìïîíåíòàõ Run Time Library (RTL). Êîíå÷íî êòî-òî (à èìåííî ìû) äîëæåí íàïèñàòü ýòè ïîäïðîãðàììû, íî îíè íå ÿâëÿþòñÿ íåïîñðåäñòâåííî ÷àñòüþ êîìïèëÿòîðà. ß äàæå íå áóäó áåñïîêîèòüñÿ î òîì, ÷òîáû ïîêàçàòü çäåñü ýòè ïîäïðîãðàììû, òàê êàê îíè î÷åâèäíî î÷åíü ÎÑ-çàâèñèìû. ß ïðîñòî ñêàæó, ÷òî äëÿ SK*DOS îíè îñîáåííî ïðîñòû... ïî÷òè òðèâèàëüíû. Îäíà èç ïðè÷èí, ïî êîòîðûì ÿ íå áóäó ïîêàçûâàòü èõ çäåñü â òîì, ÷òî âû ìîæåòå äîáàâëÿòü íîâûå âèäû âîçìîæíîñòåé, íàïðèìåð ïðèãëàøåíèå â READ èëè âîçìîæíîñòü ïîëüçîâàòåëþ ïîâòîðèòü îøèáî÷íûé ââîä.
      Íî ýòî äåéñòâèòåëüíî îòäåëüíûé îò êîìïèëÿòîðà ïðîåêò, òàê ÷òî òåïåðü ÿ áóäó ïîäðàçóìåâàòü ÷òî áèáëèîòåêà, íàçûâàåìàÿ TINYLIB.LIB, ñóùåñòâóåò.
      Òàê êàê íàì òåïåðü íóæíî çàãðóæàòü åå, ìû äîëæíû äîáàâèòü åå çàãðóçêó â ïðîöåäóðó Header:
      {–}
      { Write Header Info }
      procedure Header;
      begin
      WriteLn('WARMST', TAB, 'EQU $A01E');
      EmitLn('LIB TINYLIB');
      end;
      {–}
      Îíà âîçüìåò íà ñåáÿ ýòó ÷àñòü ðàáîòû. Òåïåðü íàì òàêæå íåîáõîäèìî ðàñïîçíàâàòü êîìàíäû ââîäà è âûâîäà. Ìû ìîæåì ñäåëàòü ýòî äîáàâèâ åùå äâà êëþ÷åâûõ ñëîâà â íàø ñïèñîê:
      {–}
      { Definition of Keywords and Token Types }
      const NKW = 11;
      NKW1 = 12;
      const KWlist: array[1..NKW] of Symbol =
      ('IF', 'ELSE', 'ENDIF', 'WHILE', 'ENDWHILE',
      'READ', 'WRITE', 'VAR', 'BEGIN', 'END',
      'PROGRAM');
      const KWcode: string[NKW1] = 'xileweRWvbep';
      {–}
      (Îáðàòèòå âíèìàíèå, ÷òî çäåñü ÿ èñïîëüçóþ êîäà â âåðõíåì ðåãèñòðå ÷òîáû èçáåæàòü êîíôëèêòà ñ 'w' èç WHILE.) Çàòåì íàì íóæíû ïðîöåäóðû äëÿ îáðàáîòêè îïåðàòîðà ââîäà/âûâîäà è åãî ñïèñêà ïàðàìåòðîâ:
      {–}
      { Process a Read Statement }
      procedure DoRead;
      begin
      Match('(');
      GetName;
      ReadVar;
      while Look = ',' do begin
      Match(',');
      GetName;
      ReadVar;
      end;
      Match(')');
      end;
      {–}
      { Process a Write Statement }
      procedure DoWrite;
      begin
      Match('(');
      Expression;
      WriteVar;
      while Look = ',' do begin
      Match(',');
      Expression;
      WriteVar;
      end;
      Match(')');
      end;
      {–}
      Íàêîíåö, ìû äîëæíû ðàñøèðèòü ïðîöåäóðó Block äëÿ ïîääåðæêè íîâûõ òèïîâ îïåðàòîðîâ:
      {–}
      { Parse and Translate a Block of Statements }
      procedure Block;
      begin
      Scan;
      while not(Token in ['e', 'l']) do begin
      case Token of
      'i': DoIf;
      'w': DoWhile;
      'R': DoRead;
      'W': DoWrite;
      else Assignment;
      end;
      Scan;
      end;
      end;
      {–}
      Íà ýòîì âñå. Òåïåðü ó íàñ åñòü ÿçûê!

Çàêëþ÷åíèå

      Ê ýòîìó ìîìåíòó ìû ïîëíîñòüþ îïðåäåëèëè TINY. Îí íå ñëèøêîì çíà÷èòåëåí... â äåéñòâèòåëüíîñòè èãðóøå÷íûé êîìèïëÿòîð. TINY èìååò òîëüêî îäèí òèï äàííûõ è íå èìååò ïîäïðîãðàìì... íî ýòî çàêîí÷åííûé, ïðèãîäíûé äëÿ èñïîëüçîâàíèÿ ÿçûê. Ïîêà ÷òî âû íå èìååòå âîçìîæíîñòè íàïèñàòü íà íåì äðóãîé êîìïèëÿòîð èëè ñäåëàòü ÷òî-íèáóäü åùå î÷åíü ñåðüåçíîå, íî âû ìîãëè áû ïèñàòü ïðîãðàììû äëÿ ÷òåíèÿ âõîäíûõ äàííûõ, âûïîëíåíèÿ âû÷èñëåíèé è âûâîäà ðåçóëüòàòîâ. Íå ñëèøêîì ïëîõî äëÿ èãðóøêè.
      Áîëåå âàæíî, ÷òî ìû èìååì òâåðäóþ îñíîâó äëÿ äàëüíåéøåãî ðàçâèòèÿ. ß çíàþ, ÷òî âû áóäåòå ðàäû ñëûøàòü ýòî: â ïîñëåäíèé ðàç ÿ íà÷àë ñ ñîçäàíèÿ ñèíòàêñè÷åñêîãî àíàëèçàòîðà çàíîâî... ñ ýòîãî ìîìåíòà ÿ ïðåäïîëàãàþ ïðîñòî äîáàâëÿòü âîçìîæíîñòè â TINY ïîêà îí íå ïðåâðàòèòñÿ â KISS. Îõ, áóäåò âðåìÿ, êîãäà íàì ïîíàäîáèòñÿ ïîïðîáîâàòü íåêîòîðûå âåùè ñ íîâûìè êîïèÿìè Cradle, íî êàê òîëüêî ìû ðàçóçíàåì êàê îíè äåëàþòñÿ, îíè áóäóò âñòðîåíû â TINY.
      Êàêèå ýòî áóäóò âîçìîæíîñòè? Õîðîøî, äëÿ íà÷àëà íàì ïîíàäîáÿòñÿ ïîäïðîãðàììû è ôóíêöèè. Çàòåì íàì íóæíà âîçìîæíîñòü îáðàáàòûâàòü ðàçëè÷íûå òèïû, âêëþ÷àÿ ìàññèâû, ñòðîêè è äðóãèå ñòðóêòóðû. Çàòåì íàì íóæíî ðàáîòàòü ñ èäååé óêàçàòåëåé. Âñå ýòî áóäåò â ñëåäóþùèõ ãëàâàõ.
      Óâèäèìñÿ.
      Â ñïðàâî÷íûõ öåëÿõ ïîëíûé ëèñòèíã TINY âåðñèè 1.0 ïîêàçàí íèæå:
      {–}
      program Tiny10;
      {–}
      { Constant Declarations }
      const TAB = ^I;
      CR = ^M;
      LF = ^J;
      LCount: integer = 0;
      NEntry: integer = 0;
      {–}
      { Type Declarations }
      type Symbol = string[8];
      SymTab = array[1..1000] of Symbol;
      TabPtr = ^SymTab;
      {–}
      { Variable Declarations }
      var Look : char; { Lookahead Character }
      Token: char; { Encoded Token }
      Value: string[16]; { Unencoded Token }
      const MaxEntry = 100;
      var ST : array[1..MaxEntry] of Symbol;
      SType: array[1..MaxEntry] of char;
      {–}
      { Definition of Keywords and Token Types }
      const NKW = 11;
      NKW1 = 12;
      const KWlist: array[1..NKW] of Symbol =
      ('IF', 'ELSE', 'ENDIF', 'WHILE', 'ENDWHILE',
      'READ', 'WRITE', 'VAR', 'BEGIN', 'END',
      'PROGRAM');
      const KWcode: string[NKW1] = 'xileweRWvbep';
      {–}
      { Read New Character From Input Stream }
      procedure GetChar;
      begin
      Read(Look);
      end;
      {–}
      { Report an Error }
      procedure Error(s: string);
      begin
      WriteLn;
      WriteLn(^G, 'Error: ', s, '.');
      end;
      {–}
      { Report Error and Halt }
      procedure Abort(s: string);
      begin
      Error(s);
      Halt;
      end;
      {–}
      { Report What Was Expected }
      procedure Expected(s: string);
      begin
      Abort(s + ' Expected');
      end;
      {–}
      { Report an Undefined Identifier }
      procedure Undefined(n: string);
      begin
      Abort('Undefined Identifier ' + n);
      end;
      {–}
      { Recognize an Alpha Character }
      function IsAlpha(c: char): boolean;
      begin
      IsAlpha := UpCase(c) in ['A'..'Z'];
      end;
      {–}
      { Recognize a Decimal Digit }
      function IsDigit(c: char): boolean;
      begin
      IsDigit := c in ['0'..'9'];
      end;
      {–}
      { Recognize an AlphaNumeric Character }
      function IsAlNum(c: char): boolean;
      begin
      IsAlNum := IsAlpha(c) or IsDigit(c);
      end;
      {–}
      { Recognize an Addop }
      function IsAddop(c: char): boolean;
      begin
      IsAddop := c in ['+', '-'];
      end;
      {–}
      { Recognize a Mulop }
      function IsMulop(c: char): boolean;
      begin
      IsMulop := c in ['*', '/'];
      end;
      {–}
      { Recognize a Boolean Orop }
      function IsOrop(c: char): boolean;
      begin
      IsOrop := c in ['|', '~'];
      end;
      {–}
      { Recognize a Relop }
      function IsRelop(c: char): boolean;
      begin
      IsRelop := c in ['=', '#', '<', '>'];
      end;
      {–}
      { Recognize White Space }
      function IsWhite(c: char): boolean;
      begin
      IsWhite := c in [' ', TAB];
      end;
      {–}
      { Skip Over Leading White Space }
      procedure SkipWhite;
      begin
      while IsWhite(Look) do
      GetChar;
      end;
      {–}
      { Skip Over an End-of-Line }
      procedure NewLine;
      begin
      while Look = CR do begin
      GetChar;
      if Look = LF then GetChar;
      SkipWhite;
      end;
      end;
      {–}
      { Match a Specific Input Character }
      procedure Match(x: char);
      begin
      NewLine;
      if Look = x then GetChar
      else Expected('''' + x + '''');
      SkipWhite;
      end;
      {–}
      { Table Lookup }
      function Lookup(T: TabPtr; s: string; n: integer): integer;
      var i: integer;
      found: Boolean;
      begin
      found := false;
      i := n;
      while (i > 0) and not found do
      if s = T^[i] then
      found := true
      else
      dec(i);
      Lookup := i;
      end;
      {–}
      { Locate a Symbol in Table }
      { Returns the index of the entry. Zero if not present. }
      function Locate(N: Symbol): integer;
      begin
      Locate := Lookup(@ST, n, MaxEntry);
      end;
      {–}
      { Look for Symbol in Table }
      function InTable(n: Symbol): Boolean;
      begin
      InTable := Lookup(@ST, n, MaxEntry) <> 0;
      end;
      {–}
      { Add a New Entry to Symbol Table }
      procedure AddEntry(N: Symbol; T: char);
      begin
      if InTable(N) then Abort('Duplicate Identifier ' + N);
      if NEntry = MaxEntry then Abort('Symbol Table Full');
      Inc(NEntry);
      ST[NEntry] := N;
      SType[NEntry] := T;
      end;
      {–}
      { Get an Identifier }
      procedure GetName;
      begin
      NewLine;
      if not IsAlpha(Look) then Expected('Name');
      Value := '';
      while IsAlNum(Look) do begin
      Value := Value + UpCase(Look);
      GetChar;
      end;
      SkipWhite;
      end;
      {–}
      { Get a Number }
      function GetNum: integer;
      var Val: integer;
      begin
      NewLine;
      if not IsDigit(Look) then Expected('Integer');
      Val := 0;
      while IsDigit(Look) do begin
      Val := 10 * Val + Ord(Look) – Ord('0');
      GetChar;
      end;
      GetNum := Val;
      SkipWhite;
      end;
      {–}
      { Get an Identifier and Scan it for Keywords }
      procedure Scan;
      begin
      GetName;
      Token := KWcode[Lookup(Addr(KWlist), Value, NKW) + 1];
      end;
      {–}
      { Match a Specific Input String }
      procedure MatchString(x: string);
      begin
      if Value <> x then Expected('''' + x + '''');
      end;
      {–}
      { Output a String with Tab }
      procedure Emit(s: string);
      begin
      Write(TAB, s);
      end;
      {–}
      { Output a String with Tab and CRLF }
      procedure EmitLn(s: string);
      begin
      Emit(s);
      WriteLn;
      end;
      {–}
      { Generate a Unique Label }
      function NewLabel: string;
      var S: string;
      begin
      Str(LCount, S);
      NewLabel := 'L' + S;
      Inc(LCount);
      end;
      {–}
      { Post a Label To Output }
      procedure PostLabel(L: string);
      begin
      WriteLn(L, ':');
      end;
      {–}
      { Clear the Primary Register }
      procedure Clear;
      begin
      EmitLn('CLR D0');
      end;
      {–}
      { Negate the Primary Register }
      procedure Negate;
      begin
      EmitLn('NEG D0');
      end;
      {–}
      { Complement the Primary Register }
      procedure NotIt;
      begin
      EmitLn('NOT D0');
      end;
      {–}
      { Load a Constant Value to Primary Register }
      procedure LoadConst(n: integer);
      begin
      Emit('MOVE #');
      WriteLn(n, ',D0');
      end;
      {–}
      { Load a Variable to Primary Register }
      procedure LoadVar(Name: string);
      begin
      if not InTable(Name) then Undefined(Name);
      EmitLn('MOVE ' + Name + '(PC),D0');
      end;
      {–}
      { Push Primary onto Stack }
      procedure Push;
      begin
      EmitLn('MOVE D0,-(SP)');
      end;
      {–}
      { Add Top of Stack to Primary }
      procedure PopAdd;
      begin
      EmitLn('ADD (SP)+,D0');
      end;
      {–}
      { Subtract Primary from Top of Stack }
      procedure PopSub;
      begin
      EmitLn('SUB (SP)+,D0');
      EmitLn('NEG D0');
      end;
      {–}
      { Multiply Top of Stack by Primary }
      procedure PopMul;
      begin
      EmitLn('MULS (SP)+,D0');
      end;
      {–}
      { Divide Top of Stack by Primary }
      procedure PopDiv;
      begin
      EmitLn('MOVE (SP)+,D7');
      EmitLn('EXT.L D7');
      EmitLn('DIVS D0,D7');
      EmitLn('MOVE D7,D0');
      end;
      {–}
      { AND Top of Stack with Primary }
      procedure PopAnd;
      begin
      EmitLn('AND (SP)+,D0');
      end;
      {–}
      { OR Top of Stack with Primary }
      procedure PopOr;
      begin
      EmitLn('OR (SP)+,D0');
      end;
      {–}
      { XOR Top of Stack with Primary }
      procedure PopXor;
      begin
      EmitLn('EOR (SP)+,D0');
      end;
      {–}
      { Compare Top of Stack with Primary }
      procedure PopCompare;
      begin
      EmitLn('CMP (SP)+,D0');
      end;
      {–}
      { Set D0 If Compare was = }
      procedure SetEqual;
      begin
      EmitLn('SEQ D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was != }
      procedure SetNEqual;
      begin
      EmitLn('SNE D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was > }
      procedure SetGreater;
      begin
      EmitLn('SLT D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was < }
      procedure SetLess;
      begin
      EmitLn('SGT D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was <= }
      procedure SetLessOrEqual;
      begin
      EmitLn('SGE D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Set D0 If Compare was >= }
      procedure SetGreaterOrEqual;
      begin
      EmitLn('SLE D0');
      EmitLn('EXT D0');
      end;
      {–}
      { Store Primary to Variable }
      procedure Store(Name: string);
      begin
      if not InTable(Name) then Undefined(Name);
      EmitLn('LEA ' + Name + '(PC),A0');
      EmitLn('MOVE D0,(A0)')
      end;
      {–}
      { Branch Unconditional }
      procedure Branch(L: string);
      begin
      EmitLn('BRA ' + L);
      end;
      {–}
      { Branch False }
      procedure BranchFalse(L: string);
      begin
      EmitLn('TST D0');
      EmitLn('BEQ ' + L);
      end;
      {–}
      { Read Variable to Primary Register }
      procedure ReadVar;
      begin
      EmitLn('BSR READ');
      Store(Value[1]);
      end;
      { Write Variable from Primary Register }
      procedure WriteVar;
      begin
      EmitLn('BSR WRITE');
      end;
      {–}
      { Write Header Info }
      procedure Header;
      begin
      WriteLn('WARMST', TAB, 'EQU $A01E');
      end;
      {–}
      { Write the Prolog }
      procedure Prolog;
      begin
      PostLabel('MAIN');
      end;
      {–}
      { Write the Epilog }
      procedure Epilog;
      begin
      EmitLn('DC WARMST');
      EmitLn('END MAIN');
      end;
      {–}
      { Parse and Translate a Math Factor }
      procedure BoolExpression; Forward;
      procedure Factor;
      begin
      if Look = '(' then begin
      Match('(');
      BoolExpression;
      Match(')');
      end
      else if IsAlpha(Look) then begin
      GetName;
      LoadVar(Value);
      end
      else
      LoadConst(GetNum);
      end;
      {–}
      { Parse and Translate a Negative Factor }
      procedure NegFactor;
      begin
      Match('-');
      if IsDigit(Look) then
      LoadConst(-GetNum)
      else begin
      Factor;
      Negate;
      end;
      end;
      {–}
      { Parse and Translate a Leading Factor }
      procedure FirstFactor;
      begin
      case Look of
      '+': begin
      Match('+');
      Factor;
      end;
      '-': NegFactor;
      else Factor;
      end;
      end;
      {–}
      { Recognize and Translate a Multiply }
      procedure Multiply;
      begin
      Match('*');
      Factor;
      PopMul;
      end;
      {–}
      { Recognize and Translate a Divide }
      procedure Divide;
      begin
      Match('/');
      Factor;
      PopDiv;
      end;
      {–}
      { Common Code Used by Term and FirstTerm }
      procedure Term1;
      begin
      while IsMulop(Look) do begin
      Push;
      case Look of
      '*': Multiply;
      '/': Divide;
      end;
      end;
      end;
      {–}
      { Parse and Translate a Math Term }
      procedure Term;
      begin
      Factor;
      Term1;
      end;
      {–}
      { Parse and Translate a Leading Term }
      procedure FirstTerm;
      begin
      FirstFactor;
      Term1;
      end;
      {–}
      { Recognize and Translate an Add }
      procedure Add;
      begin
      Match('+');
      Term;
      PopAdd;
      end;
      {–}
      { Recognize and Translate a Subtract }
      procedure Subtract;
      begin
      Match('-');
      Term;
      PopSub;
      end;
      {–}
      { Parse and Translate an Expression }
      procedure Expression;
      begin
      FirstTerm;
      while IsAddop(Look) do begin
      Push;

  • Ñòðàíèöû:
    1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23