Äàâàéòå ñîçäàäèì êîìïèëÿòîð!
ModernLib.Net / Ïðîãðàììèðîâàíèå / Êðåíøîó Äæåê / Äàâàéòå ñîçäàäèì êîìïèëÿòîð! - ×òåíèå
(ñòð. 12)
Àâòîð:
|
Êðåíøîó Äæåê |
Æàíð:
|
Ïðîãðàììèðîâàíèå |
-
×èòàòü êíèãó ïîëíîñòüþ
(666 Êá)
- Ñêà÷àòü â ôîðìàòå fb2
(192 Êá)
- Ñêà÷àòü â ôîðìàòå doc
(207 Êá)
- Ñêà÷àòü â ôîðìàòå txt
(181 Êá)
- Ñêà÷àòü â ôîðìàòå html
(198 Êá)
- Ñòðàíèöû:
1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23
|
|
Íàêîíåö, ìû äîëæíû âíåñòè èçìåíåíèÿ, ïîçâîëÿþùèå èñïîëüçîâàòü 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
|
|