You are on page 1of 261

.

http://www.litres.ru/pages/biblio_book/?art=174317
. : ; -;
2005
ISBN 978-5-469-00391-4

,
, .

,
. ,
,
. ,
, ,
, ,
.
,
, . ,
.

. . . .



- -
-
-








-




2





()










7
9
10
10
11
11
12
12
14
16
18
19
21
23
23
23
23
25
26
26
26
27
29
31
32
34
34
35
35
36
37
38
41
41
41
41
43
45
45
45
45
50
3

. . . .



3



-
-


-














4






()
-




53
55
57
57
58
58
59
60
62
65
71
74
74
74
75
76
76
76
78
78
78
85
88
89
91
91
92
92
93
94
95
97
98
101
102
104
105
107
107
107
109
110
111
111
111
113
4

. . . .







1
2
3

-




,



4
1.
2.

116
122
124
126
126
127
128
129
131
134
135
136
136
137
138
138
142
149
159
161
166
168
171
177
177
182
185
187
190
199
202
209
210
211
216
222
229
239
249
249
252
259
259
5

. . . .

260

. . . .


,1 2003 .
, , , , .
,
.
,
.
, ,
.
, . , ,
[13, 7], [3, 5, 6].
( )
, ,
( ,
, [3]).
, , . , , ,
, ,
.

Object Pascal Delphi,
Intel 80x86.
C. , [13, 2325, 28, 31, 32, 37, 39, 41, 44].
Delphi 5
Object Pascal VCL.
, , .

. . : . .: , 2003. 396 .

. . . .

Delphi, , C++,
.
, ,
. ,
, .
, ,
, . , ,
. .
:
. , ,
, . , ,
, , , .
. , ,
. :
, , , ,
. . ,
,

( ).

. ,
, .
,
, .

. , - .
, ( ). .

.
[3, 5],
( - [7]).
, .

. . . .


,
comp@piter.com ( , ).
!
- : http://
www.piter.com.

. . . .

1


: , , .
, ,
, . .
32 .

10

. . . .



, , ,
. (
), ( ).
, ,
, () , , ,
.

, . , . ,
, ,
, .
,
[1, 3, 7].
.
, ,
.
. ()
. , , [13, 7], , .
, ,
, ,
. , , . (), .

. , , . , ,
[1, 2].

11

. . . .



, .
,
. ,
, . , ,
, , . ,

, .
,
(
),
. ,
, .
:
;
;
- ;
- ;
- .

. [3, 7].


, , .

.
,
.
, ( ), ,
N , N/2 .
, (T),
(N). N , . (T) T = O(N).
, .
, .
, () . ,
12

. . . .


.
N , , .
: (N + 1)/2 ; ,
, 1 (N + 1)/2 1,
(N + 1)/2 + 1 N ,
, .
. ,
, ,
( ).
, ,
, 1 + log2 N.
T = O(log2 N). :
N = 128 8 , 64 . ,
, , ,
.

. , ,
, .
, ,
,
. , .
, , ,
, :

k , ,

.

. , ,
,
. , .

13

. . . .



, , .
.
,
. ,
, .
, .
.
. , , . ,
, . :
1. .
, .
2. .
3. , .
4. , 5,
( !),
7.
5. ,
3, 6.
6. , , 1.
7. ,
3, 8.
8. , , 1.
Ga, D1, 22, ,
12, , F. . 1.1
.

14

. . . .

. 1.1. .
,
:
1. .
2. ,
.
3. , , ,
4.
4. , 5,
6.
5. ,
2, , .
6. ,
2, , .
, . , Ga, D1, 22, , 12, , F
12, , D1, , F, Ga, 22,
.
15

. . . .

. :
.
,
( ),
, .
() ()
[3, 7]:

, .
. [1, 2, 3, 7].

- -
,
. . , , - -.
- F R
Z:

- hash function (hash


, , ).
R . - F
Z:

, F:

-
.
16

. . . .

- . - .
- , -, . -. ,
-
.
, , ,
-, .

- .
- ,
( ,
). ,
, .
, ,
, , , .
. : -, .
-. , - .
- .
. -
. -
, .
, - :
,
, -.
-
, . ,
-, .
, -, ,
- .
, -
. -, ?
- :
- ,
.
-
17

. . . .

. , - (
), ( )
,
.
,
- . ,
-
.
, , .
. ,
, , 32
128 ( - ). , -,
(
). , - . , .

-. , .

-
.
( ). ,
n0 = h(A), - h,
, n 1 = h1(A)
1. , h 2(A), ,
, h i() h(A).
,
.
, ,
:
1. - n = h(A) .
2. , , ,
n A.
, , i:= 1 3.
3. ni = hi(A). ni n = ni,
, ni
A. , , i:= i + 1
3.
.
, .

, . , -, ,
18

. . . .

. , ,
, .

- hi i. hi - h. , hi(A) hi(A) = (h(A) + pi) mod Nm, pi , Nm - h.
, pi = i. hi(A) = (h(A) + i) mod Nm. -
-
, - h(A).
: - , .
.

, .
pi hi(A) = (h(A) + pi) mod Nm p1, p2, , pk.
k = Nm.
hi(A),
, , :
hi(A) = (h(A)Ni) mod N'm, N'm , Nm.
(, ),
-
, .
.

[1, 3, 7].

-

, .
,
. ,
-.
- , . - , -,
. , -
.
- ,
(
, - ).
19

. . . .

: -,
-; -,
.
-, ,
, - ,
.
-, .
,
.
( ). ,

( ).
:
1. - , , FreePtr ( )
.
2. - n A. n , FreePtr
5; 3.
3. - m
4.
4. m .
, FreePtr 5;
m 4.
5. ,
A ( ), FreePtr
. ,
, , 2.
, ,
:
1. - n A. n , ,
- m.
2. m
A. , ,
3.
3. m.
, ;
m 2.

,
. ,
-. , . , .
20

. . . .

. 1.2 -
: A1, A2, A3, A4, A5 , h(A1) = h(A2) = h(A5) = n1;
h(A3) = n2; h(A4) = n4. A 1 , A2 , A3 , A4 A5 ( , ).
.
, . , ,
, -. ,
.

. 1.2. .




-.
- , , 21

. . . .

,
. , -
( ),
.
: , ,
.
:
-, .
, ,
-
: , .
-, -
. - , . -,
, - , .
,
, -
.
,
,
-. - .
, , , .
,
( ),
.
, , .
, , .
,
. , .
- , , , . -

, .
-, , ,
.
- ,
.
, [5, 6, 11].
22

. . . .



, -. ,
.
,
.
.
-, . - 200 ,
32 . -, .
:
1. .
2. -.
3. ,
.
4. .
5. .
6. .


:
;
-;
( );
( );
( );
( ) , ;

.


?
?
?
? ?
23

. . . .

?
?
?
. ?
- ? -?
? ? ?
? ?

- .
?

- .
-?

.

24

. . . .


. 1.1 ,
.

1.1.

. 1.2 , . 1.1.

1.2.

25

. . . .




: - - . . 1.1,
2 7 ( . 1.2
).

-
- - ,
, , . ,
, ,
.
, .2 ASCII,
Microsoft Windows. , ,
- , - 0, z.
, - Object
Pascal :
(Ord(0 )+Ord(0 )+Ord(0 ))..(Ord('z')+Ord('z')+Ord('z'))
223 ,
( 200 ).
. , -:
HASH_MIN = Ord(0 )+Ord(0 )+Ord(0 );
HASH_MAX = Ord('z')+Ord('z')+Ord('z').
- :
Ord(sName[1]) + Ord(sName[(Length(sName)+1) div 2]) + Ord(sName[Length(sName);
sName ( -).
, F = i-H1 mod 2, 1 2
, , H1 2/2 2. ,

HASH_MIN HASH_MAX, 2 HASH_MAX
HAS_IN + 1. 223 , 223
, 2 = 223 ( ,
2

, , ,
, .
Delphi 5 Upper TblElem ( 3.1, 3). ,
, [7, 13, 23, 25, 28, 32].

26

. . . .

2 ).
H1 127: H1 = 127.
:
REHASH1 = 127;
REHASH2 = 223;
- :
function VarHash(const sName: string; iNum: integer):longint;
begin
Result:=(Ord(sName[1])+Ord(sName[(Length(sName)+1) div 2])
+ Ord(sName[Length(sName)]) HASH_MIN
+ iNum*REHASH1 mod REHASH2)
mod (HASH_MAX-HASH_MIN+1) + HASH_MIN;
if Result < HASH_MIN then Result:= HASH_MIN;
end;
: sName , iNum
( iNum = 0, ). (Result < HASH_MIN) ,
, ,
0 ..'z' ( , ).
- - .
- Object Pascal :
(Ord(0 )+Ord(0 ))..(Ord('z')+Ord('z'))
200 ,
,
( ).
- ,
- :
function VarHash(const sName: string): longint;
begin
Result:=(Ord(sName[1])+Ord(sName[(Length(sName)+1) div 2])
HASH_MIN) mod (HASH_MAX-HASH_MIN+1) + HASH_MIN;
if Result < HASH_MIN then Result:= HASH_MIN;
end.


,
.
(
) . , .
.
( TVarInfo) ( sName: string),
. -
27

. . . .

,
TVarInfo TAddVarInfo
( pInfo: TAddVarInfo).
Object Pascal , class, , , ,
, (
). , ,
. , ,
, , ( TVarInfo)
.
, ,
, , , . ,
( 4).
TVarInfo :
constructor Create destructor Destroy;
procedure
SetInfo procedure ClearInfo.

.
TVarInfo
,
:
() ()
minEl, maxEl: TVarInfo;
function AddElCnt function AddElem;
function FindElCnt function FindElem;
procedure ClearAllInfo;
(
) function GetElList.
,
, .
,
,

(minEl maxEl).
TVarInfo
TblElem. 3.1 3.
(function TVarInfo.FindElCnt). (
sN
28

. . . .

sName) Object Pascal,


:
if sN < sName then
begin

end
else
if sN > sName then
begin

end
else
: (sN < sName), (sN > sName).
,
( !).
, , :
i:= StrComp(PChar(sN), PChar(sName));
if i < 0 then
begin

end
else
if i > 0 then
begin

end
else

, ,
.



HASH_MIN..HASH_MAX, TVarInfo.
Object Pascal, , .

nil.
, , .
. 1.3 ,
. 1 , 2
- . nil -.
29

. . . .

. 1.3. .
:
- InitTreeVar InitHashVar;
- ClearTreeVar ClearHashVar;
ClearTreeInfo
ClearHashInfo;
AddTreeVar
AddHashVar;
GetTreeVar GetHashVar;
, GetTreeCount GetHashCount.
, .
(AddTreeVar AddHashVar ; GetTreeVar GetHashVar
). ( TblElem)
.
,
,
,
, . , . ,
.
: FncHash
, , FncTree ,
- . ,
.

30

. . . .

(FncHash FncTree) - , FncHash.pas FncTree.pas. , FncTree


3.2 3.
, (initialization)
, (finalization) . ,
Object Pascal .


, . (FormLab1) TLab1Form
TForm VCL. Graphical
User Interface (GUI) Windows
. ( FormLab1.pas)
( FormLab1.dfm).
GUI
[3, 5, 6, 7].
FormLab1
(iCountNum, iCountHash, iCountTree),

, (procedure ViewStatistic) .
, ,
:
(EditFile),
(BtnFile), (BtnLoad);
(Listldents);
(EditSearch);
(BtnSearch) (procedure SearchStr);
(BtnAllSearch)
(procedure SearchStr)
( , Listldents);
(BtnReset);
;
(BtnExit).
. 1.4.

31

. . . .

. 1.4. 1.
(procedure TLab1Form.
BtnLoadClick) BtnLoad. ,
Listldents, .
, . (, 223 ,
).
(procedure TLab1Form.SearchStr) BtnSearch ( procedure TLab1Form.BtnSearchClick)
BtnAllSearch ( procedure TLab1Form.
BtnAllSearchClick). , .

, -
, FormLab1.pas FormLab1.dfm .
,
1, , , LABS COMMON ( COMMON ,
).
LAB1.DPR LABS. ,
FncTree 3.1 3.



, 20 % ( 45 )
,
- .
32

. . . .

20 % 40 % ( 4590 )
, , 40 % (90-223 ),
. 223 , .
, ,
- ( 35
, 500700 ),
- .

33

. . . .

2


: , (),

.

34

. . . .



( ) ,
() .
,

.
( ) ,
. , , , . .
.
, .
. ,
. :
,

;
,
, ;
,
.
, , , , .

, : , , , ,
() .
. , , , . ,
, . , .
[14, 7].
35

. . . .


.
.

, DO 10 I=1 ( , ). DO 10 I=1.15
DO10I 1.15 ( ), DO 10 I=1,15 1 15 I
10.
C++
k=i+++++j;, ( ): k = i++ + ++j;.
,
.
, . , , ,
,
.
, .
[3, 7].
, ,
, . , ,
.
.
,
. , C++ ,
.
k=i+++++j; ,
+ (+ C++, ++
) ++ (
) k = i++ ++ +j; (
), , C++
. , ,
( C++),

( k=i++ + ++j;,
).
, .
36

. . . .

, .
,
.



.
, .
, , .
, , , .
, , : ,
.
, , ,
( ,

).
!

,
.
,
. , ,
.
.
, () , .
, ( )
. ,
, (
),
, .

Object Pascal , . 2.1:

begin
for i:=1 to N do
fg:= fg * 0.5

2.1. Pascal

37

. . . .

. 2.1 , . ,
, , . . , ( , :,
).

()
, ( ). ,
[14, 7]. (). ,
, ,
.

[3, 7, 26].
: M(Q,,,q0,F),
:
Q ;
( );
Q P(Q): Q
P(Q) ( );

.
38

. . . .

.
, ,
, ()
. q
q' , ,
, q q'.
, , , ,
, . ,
. M(Q,,,q0,F)

:

, , [3, 7, 26] (, ).
. [3, 7, 26].
, . , , ,
.
,
. . ,
, ,
.
,
. ( )
( ).
.
.
.
,
. (
),
. ,
, , (,
.).
. ,
.
, :
39

. . . .

, ;
;

, ;
, : ,
( ).
- ,
.

40

. . . .



,
. () . , .
32 . . .
:
1. .
2. , (
).
3. .
4. .
5. .


:
.
- .
( ).
( ).
.

, , , ?
? -

?
? , .
?
? ?
? ?
?
? . .
? ?
41

. . . .

? .

.

?
.

42

. . . .


1. , ; (
). ,
( ), (:=),
+, , *, / .
2. , ; (
). , true false,
(:=), or, xor, and, not .
3. if then else if then, ; ( ). ,
<, >, =, (
), (:=).
4. for (; ; ) do, ; ( ). , <,
>, =, ( ),
(:=).
5. , ; (
). , ,
(:=), +, , *, / .
6. , ; (
). , 0 1, (:=), or, xor, and, not .
7. if then else if then, ; ( ). ,
<, >, =, , (:=).
8. for (; ; ) do, ; ( ). , <,
>, =, , (:=).
9. , ; (
). ,
, (:=), +, , *, / .
10. , ; (
). , ,
(:=), or, xor, and, not .
11. if then else if then, ; ( ). ,
<, >, =, , (:=).
12. for (; ; ) do, ; ( ). , <,
>, =, , (:=).
13. , ;
( ). ,
( ), (:=), +,
-, *, / .
14. , ; (
). , 'F',
(:=), or, xor, and, not .
43

. . . .

15. if then else if then, ; ( ). ,


<, >, =, ( ), (:=).
16. for (;;) do, ; ( ). , <,
>, =, ( ), (:=).
.

X, V I;

, , , d, f, (: 89,
459, 0abc4);
2
3,
, 3
.

44

. . . .



, if then else if then, ; (
). ,
or, xor and,
. (:=), .
,
({)
(}). - ,
.


-
G({if,then,else,a,=,or,xor,and,(,),},{S,F,E,D,C},P,S) :
S F;
F if E then T else F | if E then F | a:= E
T if E then T else T | a:= E
E E or D | E xor D | D
D D and |
a | (E)
. .

. , , , . , ,
.
2,
3 4.



,
.
:
(if, then, else, or, xor and);
: , ;
;
;
45

. . . .

.

, .

.
, . ,
, , . .
:

( Z z), ( 0 9) (_),
;
(
0 9), .
, ,
, ,
, . ,
,
, , ,
.

,
.

46

. . . .

. 2.1. , .
,
. . 2.1
, , , , ( , ).
. 2.2 , if then ( ,
. 2.1). .

47

. . . .

. 2.2. if then.
, . 2.1 2.2, :
- ;
(*) - , ;
(, , ,
);
( ) (_);
(*) ( ) (_), ;
0 9;
F ,
. :
v , ;
d , ;
a .
, :
M(Q,,,q0,F):
Q = {H, C, G, V, D, I1, I2, T1, T2, T3, T4, E1, E2, E3, E4, O1, O2, X1, X2, X3, A1, A2,
A3, F}
= ( - );
q 0 = H;
F = {F}.
48

. . . .

() 2.
i, t, e, o, x a
, :
I1, I2 if;
T1, T2, T3, T4 then;
E1, E2, E3, E4 else;
O1, O2 or;
X1, X2, X3 xor;
A1, A2, A3 and.
, (), V. - ,
, , V,
(
, i els,
).
, , D.
C,
, .
G . ,
, .
H , F .
, ,
, .
.
,
.
, , .
F, ,
.
. ,
, ,
.
,
. ,
, H.
, ,
( ).

, V.
, ,

.
, , . 2.1.
( ).
, , ,
,
( ,
).
49

. . . .

, ! , .
, ,
, ,
.
. , .



, , :
, ;
, .
:
LexElem ;
FormLab2 .
:
LexType , ;
LexAuto .

.
2
(TblElem FncTree),
,
1. , , .
,
.


LexType .
( TLexType), .
LexTypeName, LexTypeInfo. ,

(LEXSTART), .
LexElem (TLexem)
(TLexList), , .


( LexInfo).
(LexType), :
50

. . . .

VarInfo -

ConstVal ;
szInfo .
.
,
, .
1. , . , ,
,
( 3 4).
, , .

:
iStr , ;
iPos ;
iAllP .
, ,
.
:
:
CreateVar ;
CreateConst ;
CreateInfo ;
CreateKey ;
Destroy , ( );
.
( ,
).
( TLexList) TList VCL ( Classes) Delphi 5.
TList ,
(
). TLexList
, , , ( Clear Destroy),
GetLexem Lexem,
( ).


LexAuto, , , . . 51

. . . .

, . 2.1 2.2,
.
LexList,
. ( listFile) ,
( listLex). 0, ,
, .
.

( ).
TAutoPos . .
MakeLexList, ,
. (
, ),
case . case
, case .
:
AddVarToList ;
AddVarKeyToList
;
AddConstToList ;
AddConstKeyToList
;
AddKeyToList
;
Add2KeysToList
.
, , ,
F.
.
,
( T2, T3, E2, E3, X2 A2)
(
I2, T4, E4, O2, X3 A3).
:
(, 2a :6
);
( , );
( :
,
:=).
.
,
,
52

. . . .


, . 1, (FormLab2)
TLab2Form TForm VCL
:
( FormLab2.pas);
( FormLab2.dfm).
FormLab2
(listLex), .
, ,
:
(PageControll) (SheetFile
SheetLexems) ;
SheetFil:
(EditFile), (BtnFile), (BtnLoad);
(Listldents);
SheetLexems:
(GridLex) ;
(BtnExit).
. 2.3 2.4.

53

. . . .

. 2.3.
2.

54

. . . .

2.

. 2.4.

,
1.
( listLex) MakeLexList,
iErr.
,
, .
, listLex GridLex, :
;
( );
.

2.4 2,
2.5 2.
,
2, 2.


2
.
:
55

. . . .

(if, then, else, or, xor and);


( );
;
;
( ).
, , , .
( , ), ( :)
.
.
,
. , ,
.

56

. . . .

3


: , ()
-,
.

57

. . . .



( ) [1, 3, 4, 7]. - () .
.
, , . : , , , ,
.

(). ,
.
.
. -, .
( ) ,
.
:
;
;
,
.
.
, , , .
.


.
.
, . , .
.
, .
, ,
, . . ,
, ,
. , 58

. . . .

. 2.
, . ,
-;
, .
, , -.

.

-
, ,
. :
, , , () .
.
-
- ( [1,
4, 3, 7]). , - - . ,
.
- (), (
). -
, .
, : , ( )
.
-
, , ,
. .
, (
). ^-.
,
, ( ). .
- , . (
- ) - (-). -, -.
59

. . . .

, [14, 7].
-

-,
, [13, 7]. -
.

. , - , , , -, ,
, - -.
- .
,
, -
.
- [1, 3, 7].
, -, .

-
-, , -
. [1, 3, 7].
:
;
-.
: - A,
, A , ( ); a,
,
(
). - ,

A , (q,,A) .
, - , . , ,
.
60

. . . .

:
.
,
, ().3
- :
- ,
A ,
A , (
); ,
a, ,
( ).
, , .
:
: ;
, (
);
, ,
A ( ).
-
, -.
, .
- :
. ,
, .

, [3, 7].
n = ||, ,
. ,
, , .
,
[1, 3]. (n3 n2 -). -.
.
. , ,
.
-.

, , .

61

. . . .

-. ,

-, .
, , , -.
, .

:
(
);
LL(1) LL(k) (
);
LR(0) LR(1) (
-);
SLR(1) LALR(1) (
-);
(
-).
[14, 7].


.
, ,
. , , ,
.
, , .

. ,
. , - [1, 2, 7].
, ,
, , 4, .
, . .
,
, . , -,
62

. . . .

. , (
, ,
).
- ,
, . ,
(
, -,
,
).
,
- .
, -, , . - : - ,
-, , . ,
, ,
, .
- , .
,
-, . , :
. ,
( ).
- , -, .
, .
, , .
:
, -.
,
, . , , .
[1, 7].
.
,
.
.

, , .

- , 63

. . . .

.
, . ,
, .
, , ,
, .
, .
:
1. -.
2. -, , -,
.
3. ,
, ,
.
4. , . 2
- . 2.
5. . 3, . 4 (
), .
6. , ( ).
. 3 5 , . 6.
,
. , ,
- ,
.
.
, , , - LR(1) LALR(1),
, , , (
[1, 2, 7]).
.
,
(
LL(1) ). ,
.

.
,
64

. . . .

- (
- [13, 7]).


- .
. . .
,
, . -
, . ,
.
, . .
, . ,
.
=., <. .>.
.
- ,
. , ,
(
) ,
. , , i.> j, j <.
i ( : =., <., .>).
,

:
i <. Bi+1, Bi+1 (
);
i.> Bi+1, i (
);
i =. i+1, i i+1 (
).
.
. 3.1.
, .
, b . ,
,
-
,
<. =..
.>, .
65

. . . .

, =.
.

. 3.1. -

,
,
- .
. () ,
() .
.
, .
. ,
( ) .
,
- ( , ) [1].
:
;
;
;
;
.

.
- ,
[1, 3, 7],

,
.
-

U;
66

. . . .

U,
U

z (

z ).

:


U;


U,
t

U (U,

z (

z ).
L(U) R(U)

:
1. U , U
. L(U) , 67

. . . .

R(U) ( L(U)
, U, R(U) ,
). U
, L(U) R(U).
2. U :
L(U) [U', U', ,
, L(U'), L(U') L(U). R(U). , - U' U, U' U,
U.
3. L(U) R(U)
, 2, .
L t(U) Rt(U) :
1. U L(U)
R(U).
2. U U tz
U Ctz,

t L t(U).
Rt(U) U zt U ztC ( Lt(U)
U,
Rt(U) ). ,
Lt(U) Rt(U).
3. L(U), U', U'
Lt(U) , L t(U'), Lt(U')
Lt(U). Rt(U)
R(U).

( ). -

68

. . . .

Lt(U) Rt(U), - G(VT,VN,P,S) :


1. VT:

.
2. C xaiby C xaiUbjy, i
, j

, i
j (
i j).
3. j, 2, :
=. ( ) , i, , b j.
4. xaiUjy, i , Uj (Uj,

, i Uj.
5. Uj, 4, Lt(Uj).
ck, , :
<. () , a i, , k.
6. xUjaiy, ai , Uj

69

. . . .

x y ,

, Uj.
7. Uj, 6, Rt(Uj).
ck, , : .> ()
, k, , i.
8. VT,
9,

VT, i:= i + 1, 2.
9. Lt(S) S.
ck, , : <. () ,

( ), , c k.
10. Rt(S) S. ck, , : .> () , ck, ,

( ). .

, , (
=., <. .>
). - , , - G(VT,VN,P,S) .
, ( ), .
[14, 7].
70

. . . .

-

- - . ,
, .
- G(VT,VN,P,S)
:
1. , (
).
.
2. sj (
, , ), sj .
ai ( -).
3. sj , ai ,
, .
4. , sj, , a i (
).
5. , 3, , ,
-, .
6. , 3, =. ( )
<. (), (). ai , ( ai+1, i:= i+ 1). 2.
7. , 3, .> (),
. , =. ( ), ,
, .
( , =.,

).
8. G(VT,VN,P,S) ,
(
, ,
). ,
, , , , -, .
, ai . 2.
71

. . . .


. ,
, S

,
. .
- .
, . , ( ).

, [1, 7].
( ) .
,

.
.
,
- , .
, ,
, .

.
,
, , , .
,
. , , . ,
. .4
-
G(VT,VN,P,S) :
1.

( ) ,
() , . .

72

. . . .

2. 1 L(U)
R(U)

: Lt(U) Rt(U).
3. 2 Lt(U) Rt(U)

.
4. G(VT,VN,P,S) G'(VT,
{S},P,S) .
5. - .
,
. , ,

.

.

73

. . . .



, ,

. () .
.
, .
, ,
.
( ),
.
: ,
.
( a).
.
,
. ,
a .

, 2.
32 . . .
1. .
2. , (
, , ).
3. , , .
4. .
5. .
6. .


:
.
.
(
, 74

. . . .

, ).
.
.
( , , ).
.
( ).


?

?
? -?
.
- ? .
.
?
?
?
?
. ?
.
, ? -?
, - ( ).
- ( )?

75

. . . .



. S ; S, F, T .
. .
1. S a:= F;
F F+T |
| TIE |
(F) | (F) |
2. S a:= F;
F F or | F T | T
T and E |
(F) | not (F) | a
3. S F;
F if E then T else F| if E then F| a:= a
T if E then T else T | a:= a
E a<a | a>a | a=a
4. S F;
F for (T) do F | a:= a
T F;E;F |;E;F | F;E; |;E;
E a<a I a>a I a=a


. 3.1 . .

3.1.

76

. . . .

.
X, V I.
,
, , d, f, (: 89, 459, 0abc4).
,
2.

77

. . . .



,
2.
, , -
G({if,then,else,a,=,or,xor,and,(,),},{S,F,E,D,C},P,S) P:
S F;
F if E then T else F | if E then F | a:= E
T if E then T else T | a:= E
E E or D | E xor D | D
D D and C | C
C a | (E)
.
,
, ,
,
.




.
G. , . 3.2.

3.2.
. 1

. 3.2 , L(U) S, , D, R(U)


F, , , D ,
. , L(S) L(F), F L(S): F
L(S), R(F) R(E), R(F): R(F).
78

. . . .

3.3.

, .

3.3.
. 2

. 3.3 . 3.2 (
), , . . , . 3.4.
. 3.4 . 3.3 F,
. . , . 3.5.

3.4.
. 3

3.5.
. 4 ()

79

. . . .

. 3.5 . 3.4 R(U)


F T . .
( 5), , (
, ). ,
, . 3.5, G.




.

G. , . 3.6.

3.6.
. 1

, . 3.6,
, . 3.5. , Lt() Lt(D) Lt(C), D C L(E): D,
e L(E), Rt(F) Rt(E), Rt(D) Rt(C), E, D
R(F): E, D, R(F).
, . 3.7.

3.7.
.

.
80

. . . .



, . 3.7,
G.
or (.
or . =. ( ) . or
D or D. Lt(D) and, (. , or, <. () , and, (.
, or
or D. Rt(E) or, xor, and, ). ,
or, .> () , or, xor, and, ).
or ,
.
( ) () (
).
, (, =. ( )
, ).
( ().
Lt(E) or, xor, and, (. , (, <. () ,
or, xor, and, (.
( ,
.
G, .
, , , .
G S,
, , Lt(S). if, ;.
, , <. ()
, if, ;.
, , , R^(S).
;. ,
, .> () ,
;.
, . 3.8.

3.8.

81

. . . .

G
G'({if,then,else,a,=,or,xor,and,(,),},{E},P',E) P':
E E; 1;
E if E then E else E | if E then E | a:= E 2, 3 4;
E if E then E else E | a:= E 5 6;
E E or E | E xor E | E 7, 8 9;
E E and E | E 10 11;
E a | (E) 12 13.
.
13 . 2 5, 4 6
, 9 11 ( , ). ,
, , ( )
( 2 5
, 9 11 ).
. ,
G'.


-, .
. (
-) .
- .
- {||}, :
;
-;
.
,
, .
82

. . . .

- ,
.

1
if a or b and c then a:= 1 xor c;.
,
a, : if a or a and a then a:= a xor a;.
. - .
, (), , .
{if a or a and a then a := a xor a;| |}
{a or a and a then a := a xor a;| if|}
{or a and a then a := a xor a;| if a|}
{or a and a then a := a xor a;| if E|12}
{a and a then a := a xor a;| if E or|12}
{and a then a := a xor a;| if E or a|12}
{and a then a := a xor a;| if E or E|12 12}
{a then a := a xor a;| if E or E and|12 12}
{then a := a xor a;| if E or E and a|12 12}
{then a := a xor a;| if E or E and E|12 12 12}
{then a := a xor a;| if E or E|12 12 12 10}
{then a := a xor a;| if E|12 12 12 10 7}
{a := a xor a;| if E then|12 12 12 10 7}
{:= a xor a;| if E then a|12 12 12 10 7}
{a xor a;| if E then a :=|12 12 12 10 7}
{xor a;| if E then a := a|12 12 12 10 7}
{xor a;| if E then a := E|12 12 12 10 7 12}
{a;| if E then a := E xor|12 12 12 10 7 12}
{;| if E then a := E xor a|12 12 12 10 7 12}
{;| if E then a:= E xor E|12 12 12 10 7 12}
{;| if E then a := E|12 12 12 10 7 12 12 8}
{;| if E then E|12 12 12 10 7 12 12 8 4}
{;| E|12 12 12 10 7 12 12 8 4 3}
{| E;|12 12 12 10 7 12 12 8 4 3}
{|E |12 12 12 10 7 12 12 8 4 3 1} , - , .
: 12 12 12 107 12 12843 1. :
E1 E; 3 if E then E; 4 if E then a := E; 8 if E then a := E xor E; 12 if E then a
:= E xor a; 12 if E then a := a xor a; 7 if E or E then a:= a xor a; 10 if E or E and E then
a := a xor a; 12 if E or E and a then a := a xor a; 12 if E or a and a then a := a xor a; 12
if a or a and a then a := a xor a;
, , -
,
.
83

. . . .

, , . 3.2.

. 3.2. if a or a and a then :=


;.

2
if {a or b then := 25;.
,
, : if (a or a then := .
:
{if (a or a then a := a;| |}
{(a or a then a := a;| if|}
{a or a then a := a;| if(|}
{or a then a := a;| if(a|}
{or a then a := a;| if(E|12}
{a then a := a;| if(E or|12}
{then a := a;| if(E or a|12}
{then a := a;| if(E or E|12 12}
84

. . . .

{then a := a;| if(E|12 12 7}


( then, , - ,
( ).



3, , 2, , :
, ;
, .
:
SyntSymb
- ;
FormLab3 .
:
SyntRul
.

.
3 TblElem FncTree, , 1,
LexType, LexElem, LexAuto,
( 2).
,
.


SyntRul , .
(GramMatrix) , ( TLexType).
, ,
TLexType LexType.
, :
< <. ();
> .> ();
= =. ( );
(
).

SyntRul CorrectRul , . (
).
85

. . . .

SyntRul
GramMatrix
(. . 3.8). , , a G ( ),
GramMatrix , a . 3.8, .
, . 3.8 .
. : ( ). ,
:
1. ( G) , , .
2. .
,
4 ( ). , , (. ,
).
. ,
, .
G' GramRules.
,
( ).
, G. ( 13),
.
(GramMatrix GramRules) SyntRul
MakeSymbolStr,
. G , MakeSymbolStr '' . ,
.


-
SyntSymb -
, . , ( ).
:
TSymbInfo : ;
TSymbol , ;
TSymbStack .
TSymbInfo
SymbType, : SYMBLEX ( )
SYMBSYNT ( ), :
86

. . . .

(LexOne) ;
(LexList) .
LexList
( TList VCL Delphi
5). , ,
, .
TSymbol ( SymbInfo
TSymbInfo), , (
iRuleNum). 0, 1 13.
,
:
CreateLex ;
CreateSymb
;
Destroy (
);
, ,
.
SymbInfo TSymbol , , , . ., TSymbol
.
TSymbStack
TList VCL Delphi 5.
, -.
( , TList),
, :
(Clear)
(Destroy);
(GetSymbol);
(Push),
;
, (TopLexem),
;
, (MakeTopSymb); ,
, .
SyntSymb
Bui 1 dSyntList, -
.
(1 istLex), , (symbStack), . :
( ), ;
, , ,
.
87

. . . .

BuildSyntList - , .


, . (FormLab3) TLab3Form
TForm VCL :
( FormLab3.pas);
( FormLab3.dfm).
FormLab3 FormLab2,
2. , ,
2, 3 , , 2.
, ,
2, symbStack,
, .
. , .
, 2,
, FormLab3,
3:
(PageControl1) (SheetSynt)
;
SheetSynt (TreeSynt TTreeView).
TLab3Form . 3.3.
,
2.
, 2.
, listLex
, ,
BuildSyntList, (listLex) (symbStack). symbRes.
symbRes , ,
, .
, .
, , symbRes . TreeSynt
,
MakeTree.
MakeTree
TTreeView. TTreeView
88

. . . .

Windows
( ).

. 3.3.
3.

, - , FormLab3.pas FormLab3.dfm .
,
3, , - ,
LABS COMMON ( COMMON
,
). LAB3.DPR LABS.
, SyntSymb 3.7 3.


3
.
. . . .
,
.
89

. . . .

, . ,
2, , , .

90

. . . .

4


:
, .

91

. . . .




.
( ) ,
,
( ).
,

: ( ), ,
. .
,
. ,
. [14, 7],
, .

,
. ( ) ,
.
, ,
, ,
. , , ,
, ,
.
, , . . ,

.
.

.
, ,
. ,
. .
, .
, . .
92

. . . .

()
, ,
.
, , . . ,
( ),
( ).
, . .



, , -.
- , .
, .
. ,
: ,
(, , .) .
,
, (
). ,
,
.
,
.
, .
, ().
.
,
, (). ,
. ,
, .
, - ,
( )
.
, , .
-
.
, , .
93

. . . .

- :
N C(N).
N () C(N) , ,
N. , N
N . . , , , .
- ,
.
, , , ,
. C(N), , N. ,
, () . -
.
, .
, .
- ( ).
- . - -,
- [1, 2, 7].
- - , ,
. - :
, () ;

( , ,
);
, ,
( , ,
).
, - .
- - [1, 2, 7].


-
, . , , .
94

. . . .


.
,
.
, . ,
. ( ).

. , .
,
. , , , .
:5
, ;
();
();
() ;
.
, .
.
,
.
, , .
-, , , .
.
, , .
.
[13, 7].


()
:
. , :
5
, . , , .
. ( , ). .
Forth.

95

. . . .

<>(<1>,<2>). ,
,
.
( ,

).
, A:=B-C+D-B-10, , :
1: * (B, C)
2: + (^1, D)
3: * (B, 10)
4: (^2, ^3)
5::= (A, ^4)
(
), ^
.
.
, , .
: , , , ( ) , . ,
. - (,
),
( ).
, , (, ,
- ).
,
, ( ). .
, , , ( ).
, . -
.
:
,
, ;
, ,
, ;
, , ;
, - ;
96

. . . .

,
, .
, , .
.

-
-, .
, ( )
. -
. , , - .

.
, , (
, ).
.
( ,
). ,
.
.

, , , . , , , ,
. , ,
, , ,
(
).
:
( , ,
- );
,
;
,
;
.
, , , ,
97

. . . .

. ,
, :
1. . ,
, ,
.
2. . ,
, ,
.
3. , . , 1, , 2.
4. .
,
.
,
( ).

, .
. , , , ,
. ,
,
. .
, , , , .
, . , , : , , Break Continue ( C, C++ Object Pascal),
, .
, ,
. , ,
, - .
- , .


, ,
. -.
.
. 98

. . . .

. , ,
()
.
,
( ),
, .
: -,
.
,
, . -, .
, , .
,
.
.
, . .
: , , () .
, .
, . . .
,
,
, . , ,
. . ,
,
[1, 2].
. , ,
.
,
, (, ), ,
.
,
, . , , , , 1,11,3. ,
, 1030 % , 99

. . . .

, , 1030 %
.6
,
,
.
(
).
, , .
, ,
[13, 7]. ,
.
:
( ), ;
.

, .
, (
).

( ), , . , ,
- .

- . .

( ,
).
. , , ,
. .

, , .
,
, ,
, ,
, . , -

6
,
. ,
.

100

. . . .

,
.
. , , , .
.

. .
:
;
;
;
;
.
-, - .
-
. .
- [1, 2, 7]. - , , ,
.
.


, . , .
, .
.
.
, , .
,
, ( ).
.
, .
, , :
;
( );
;
;
.
101

. . . .

:
.


, .
.
!

3 -.

!
,
. ,
.

.
, (<>,<>) ,
. ,
,
. ,
, ( ) , .
.
, , (,0).

:
1. , , .
2. (,0),
.
3. , .
(,0),
, . (
,
.)
4. :=, :
, (
, );
, , .
.
( Pascal) :
I:= 1 + 1;
I:= 3;
102

. . . .

J:= 6*I + I;
:
1: + (1,1)
2::= (I, ^1)
3::= (I, 3)
4: * (6, I)
5: + (^4, I)
6::= (J, ^5)
. 4.1.

4.1.

C(K,0) ( ),
:
1::= (I, 2)
2::= (I, 3)
3::= (J, 21)
, , ( [1,
2, 7]).
, .
,7 .
, ,
. , . ,
. ( ) , .

,
, . -,
( ) , ; -, , .

103

. . . .


( )
, .
i ,
j, j< i ,
i, , i j.
. ,
, .
.
, , , :
0,
;
i- , , A (dep(A)) i,
i- ;
i- (dep(i)) 1+ (____).
,
, i j- (j<i), i
, dep(i) = dep(j).

SAME(j,O). i, ,
i j.

. , :
1. - SAME(j,0),
j (*j).
2. i, .
3. j- ,
j < i dep(i) = dep(j), i SAME(j,O).
4. , .
:
D:= D + C*B;
A:= D + C*B;
C:= D + C*B;

:
1: * (C, B)
2: + (D, ^1)
3::= (D, ^2)
4: * (C, B)
104

. . . .

5: + (D, ^4)
6::= (A, ^5)
7: * (C, B)
8: + (D, ^7)
9::= (C, ^8)
,
, , .
. 4.2.

4.2.

, SAME(j,O),
:
1: * (C, B)
2: + (D, ^1)
3::= (D, ^2)
4: + (D, ^1)
5::= (A, ^4)
6::= (C, ^4)
,
. , ,
.

.
, .



,
( )
.
:
;
105

. . . .

;

;

( ).

- .
,
.
.
, ( TMPi, i ).
. .8

106

. . . .



,
.
,
, 3.
: ( 3),

( ).
(
).

Intel 80x86 ( ).
, .
3.
1. .
2. .
3. -
.
4. . .
5. ( )
.
6. ( ).
7. .
8. .
9. .


:
.
.
.
-
.
107

. . . .


.
( ).

108

. . . .


, ?
.
( )?
?
? ? ?
, , .
, .
.
?
. ? ?
, : .
?
?
?
. .
? ?
.
.

109

. . . .


3.
, 2 3.

110

. . . .



, -
G({if,then,else,a,=,or,xor,and,(,),},{S,F,_,), C},P,S) :
S F;
F if-then T else F | if E then F | a:= E
T if-then T else T | a:= E
E E or D | E xor D | D
D D and |
a | (E)
.

2 3.
4
.
(. ).

-
, , G, () :
(or, xor and);
;
(ifthen else) (if
then);
, , ( :
).
- .

-
, ,
. , (. ) .
,
. -,
.
.

,
(1) (0).
111

. . . .

.
, -
, [2].

-
,
-.
, . ,
, .

,
( 3).

-
:
1. 1, ,
if ( ) then ( ),
.
2. , :
2, ;
3 ( )
( ), .
3. 2, then ( ), .
4.
.
5. 3,
else ( ),
.
-
. 4.1.

112

. . . .

. 4.1. - .
, :
.
:
IF(<1>,<2>) ;
JMP(1,<2>) .
IF , , . IF , , , .
JMP (
1), . JMP
, .

-
, ,
. -.
.
:
, , ( ) ,
;
, (
) ,
.


:
113

. . . .

if a and b or a and b and 345 then a:= 5 or 4 and 7;



, . 4.2.
:
1: and (a, b)
2: and (a, b)
3: and (^2, 345)
4: or (^1, ^3)
5: if (^4, ^9)
6: and (4, 7)
7: or (5, ^6)
8::= (a, ^7)
9:
: 1 5
6 9.

:
1: and (a, b)
2: and (a, b)
3: and (^2, 345)
4: or (^1, ^3)
5: if (^4, ^9)
6: C (4, 0)
7: C (5, 0)
8::= (a, 5)
9:
, :
1: and (a, b)
2: and (a, b)
3: and (^2, 345)
4: or (^1, ^3)
5: if (^4, ^7)
6::= (a, 5)
7:

114

. . . .

. 4.2. if a and b or a and b and 345 then


a:= 5 or 4 and 7;.
:
1: and (a, b)
2: same (^1, 0)
3: and (^1, 345)
4: or (^1, ^3)
5: if (^4, ^7)
6::= (a, 5)
7:
same, :
1: and (a, b)
2: and (^1, 345)
3: or (^1, ^2)
4: if (^3, ^6)
5::= (a, 5)
6:
.
37,5 % , , . ,
37,5 % ( ,
,

).
115

. . . .

,
. a and b or a and b and
345 a and b , a-b
+ a-b-345 a-b-346, , ,
.
,
[1, 2, 7].



, 2 3, ,
, 4 :
, ;
, .
:
Triads ;
TrdOpt :
;
FormLab4 .
:
TrdType ;
TrdMake ;
TrdCal
.

.
4 :
TblElem FncTree ( 1);
LexType, LexElem, LexAuto
( 2);
SyntRule SyntSymb
( 3).
,
.


TrdType ,
.
:
TTriadType ;
TriadStr ;
116

. . . .

TriaD1ineSet , (
).


Triads ,
. , .
:
TOperand ;
TTriad ;
TTriaD1ist .
TOperand . :
, :
OPC0NST ;
OPVAR ();
OPLINK ;
:
ConstVal ( );
VarLink ( );
TriadNum ( ).
, ,
:
() ?
:
(
), ,
,
;
,
.
, .
( , ), ,
, ( ). (
same), , , .
TTriad . :
TriadType ( TTriadType TrdType);
Operands ( TOperand);
Info ;
IsLinked , ,
, ( IF JMP).

:
(),
.
117

. . . .


1. , .
, ,

. ,

. (
, ).

Info.

: - IF JMP, ,
.
, .
TTriad
:
Create ;
IsEqual;
MakeString, ;
, .
, IsEqual , .
, , . ( )
.
TTriaD1ist .
, ( 2 3),
TList VCL
Delphi 5. ( , TList), , :
(Clear)
(Destroy);
(WriteToList);
(DelTriad);
GetTriad Triads
.
, (WriteToList)
MakeString
. (DelTriad) , , , ,
(IsLinked) .
Triads
DelTriadTypes, .
.
118

. . . .

same,
.
:
;

- .
N + K-N-N,
N , . , , .
( N) .
.
:
1.
, .
2. , ,
, .

2N
. , N
,
.


TrdMake ,
. ,
TrdType, , Triads.
SyntSymb, 3. , .
, , MakeTriaD1ist. :
symbTop ,
;
listTriad , .
,
, ,
, .
.
MakeTriaD1ist ,
NOP (No Operation ),
,
IsLinked .
MakeTriaD1ist TrdMake
MakeTriaD1istNOP, .
,
MakeTriaD1ist.
119

. . . .

MakeTriaD1istNOP -, . - G', :
2 5 ;
3 ;
4 6 ;
7, 8 10 ;
13 ;
.
MakeTriaD1istNOP :
MakeOperand ,
( );
MakeOperation, -
.
MakeTriaD1istNOP .
MakeOperand, , , (
-).


TrdCalc , ,
.
. ,
, .
- CalcTriad,
.

,
TrdOpt :
;
.
, TrdOpt, , (
TRDASSIGN). , , , ( TRDIF
TRDJMP). ,
TRDC TRDSAME.
:
;
;
.
(
,
). ,
, , ,
TrdOpt .
120

. . . .

,
, ( TrdCalc, CalcTriad).
, , TrdOpt
:
TConstInfo ;
TDepInfo .
TAddVarInfo,
TblElem ( 1), , .
TConstInfo , .
.
TDepInfo .
.
,
.
, TAddVarInfo.

.
:
1. ( ).
2. (),
.
:
;
,
.
:
, ;
.
:

;

, ;
(,

nil).
:
,
;
, , .
, ,
.
: () 1
4, 4.
, , .
121

. . . .

TrdOpt :
OptimizeConst ;
OptimizeSame .
.
,
, , :
(TRDC) ;
Same (TRDSAME) .
(DelTriadTypes), Triads.
, ,
,
.
OptimizeConst OptimizeSame , ,
.
, ,
( ), . ,

, .
, .
, ,
.


,
. (FormLab4) TLab4Form
TForm VCL :
( FormLab4.pas);
( FormLab4.dfm).
FormLab4 FormLab3,
3. , ,
2 3. ,
4 , , 2, , , 3.
, , 2 3,
listTriad, .
. , .
, 3,
, FormLab4,
4:
122

. . . .

(PageControll) (Sheet-Triad)
;
SheetTriad
( ):
GroupTriadAll ListTriadAll ,
;
GroupTriadConst ListTriadConst ,
;
GroupTriadSame ListTriadSame ,
.
SheetTriad
;
SheetFi 1 ( )
( ):
CheckDelC
;
CheckDelSame same
.
TLab4Form . 4.3.

. 4.3.
4.
,
2.
123

. . . .

, 2, , , , 3.
, symbRes . ,
MakeTree,
MakeTriaD1ist
( TrdMake). listTriad,
lexTmp.
lexTmp
, , . ,
lexTmp, , .

.
, lexTmp
(nil), , , listTriad .
ListTriadAll, OptimizeConst. CheckDel_C,
C ( DelTriadTypes
TRD_CONST), ListTriadConst.

OptimizeSame. CheckDelSame,
same (
DelTriadTypes TRD_SAME),
ListTriadSame.

,
- , FormLab4.pas FormLab4.dfm .
,
4, , , LABS COMMON ( COMMON
,
). LAB4.DPR LABS.
, Triads 3.10, TrdOpt
3.11 3.


4 , , .
,
( ).

. , .

, 124

. . . .

,
.
C same , .

, : , 2, ,
3.
.
:
( );
(
);
.
(, )
. .
.
14 , :
1. .
2.
.
3. .
4. .
5. .
, .
,
, ,
.

125

. . . .



: , , .

(
).
,
.
Object Pascal Borland Delphi. .
:
1. .
2. .
3. .
4. .
,
.

126

. . . .


. 5.1.

5.1.

127

. . . .


:
1. .
2. ( ).
3. :
;
;
.
4. .
5. .
6. .
7. - .
8. ( ).
9. ,
.
10. .
11. .
12. , , .
13. .
14. , .
15. .
,
.

-. ,
,
().
()
(
LEX YACC) [2, 3, 7, 27, 35].
( )
.
: ,
, ,
.

128

. . . .


. ,
.
( ) .
.

( ) .
:
prog (program)
end.;
, ;
,
( );
, , ;
:
<>:=<>;
if <> then <> if <> then
<> else <>;
begin end;
, ;
():
(+) (-);
(<), (>), (=);
(and), (or), (not);
, ;
() ( );
, , , , ( );
InpVar Compi 1 eTest,
.
(
).
.
,
.
, .
,
.
129

. . . .

,
.

:
;
InpVar;
Compi 1 eTest,
.
() Intel 80x86 Pascal Borland.
:
Prog <_>;
{ }
Var InpVar: <_>;
{ }
Var <_>: <_>;
{
}
Function CompileTest(InpVar: <_>): <_>;
{ CompileTest InpVar
}
Begin
Asm
{ ,
}
end;
end;
begin
readln(InpVar);
writeln(CompileTest(InpVar));
end.

.
. InpVar CompileTest ,
.
, , .

, .
, 32.
,
,
, .
.
, .
130

. . . .


. 5.2.

5.2.

131

. . . .

132

. . . .

, . 5.2. :
2 ;
8 ;
16 .
:
*, / ;
>> << ( );
++ ( 1);
( 1).
:
1. while <> do <>.
2. repeat <> until <>.
3. do <> while <>.
4.
for <>:=<> to <> do <> for
<>:=<> downto <> do <>.
:
1. : {}.
2. : (**).
3. : //.
4. : /**/.
:
1. .
2. .

133

. . . .


:
;
;

.
.
.

( ).
Delphi 5 .
.
(
).

:
;
;
() ( 4 ,
-);
.
(break) (continue);
;
(
-, -);
,
, .
, ,
, .
,
, .

.

134

. . . .



:
1.
. ,
, , . , , ,
.
2. , : () (
LEX YACC). ,
.
: , LEX (
), . ,
.
3. , ,
( ). ,
, , , ,
, , ,
. , ,
. , ,
.
4. - ,
, . , ,
: ( (1) ),
LR(1)
LALR(1) . , , .
, .
, 3, .
5. , .
,
.
[14, 7].

135

. . . .



, , , ,
, .
,
14, . , ,
, ,
. ,
.
:

( -
);

( 3 4
);
,
( );
;
;

( InpVar CornpileTest);
- .
, 14, .
,
.


:
1. : .
2. : (-).
3. : while (<>) do <>.
4. : (1 2).
5. : Long integer (longint, 32 ).
6. : ({ }).
, ( ):
if (<>) <> else <>;
if (<>) <>;
(<>).
, C++ ( ) Object Pascal ( ,
begin end, ).
136

. . . .

()
Intel 80386
Delphi 5 [9, 23, 28, 41, 44].
, :
CompileTest ( );
Result,
.
,
(, i I
).


, 3.
( ) . .
.
,
.
- :
G({prog,end.,if,else, begin, end,while, do, or,xor,and,not,<,>,=, <>, (,), ,+,um,a,c,=},
{S,L, 0,B,C,D,E, T,F},P,S)
P:
S prog L end.
L | L;0 | L;
if(B) else | if(B) | begin L end | while(B)do | a:=E
or | xor |
and D | D
D E<E | E>E | E=E | E<>E | () | not(B)
E E-T | E+T | T
T um T | F
F (E) | a |
.
G 28 .
:
S ;
L ( );
( : , ,
, , );
, ;
D ;
,, F .
:
um ( ) ,
(-),
;
137

. . . .


, ;
not ,
(
!), :
D not D | G
G E<E | E>E | E=E | E<>E | (B)
, : , .
( , ).



,

- (
, -).
- ,
1.
, , 3.1 3.2 3. , .


,
2.
,
.
:
(prog, end., if, else, begin, end, while, end, not, or, xor
and);
: , ;
: , ( ), ,
;
;
.
, end end. .

, .

.
,
.
138

. . . .

,
G E, T F :
E ET | E+T | T
T T | F
F (E) | a | c
,
ET T
( , , , ). .
, , ( ) . ,
, ( ) ,
, .
, , ,
( ) .
, , ,
( ,
, ).
,
.
, .
,
:
<>. .
,
. ,
.
, , . ,
, ,
.
, if( while(
( if_ w_l) .
,
:
if_ ) else | if_ ) | begin L end | w_l B)do | :=
, ,
( , ,
).

,
.
,
2, :
M(Q,,,q0,F):
139

. . . .

Q = {H, C, C1, G, S, L, V, D, P1, P2, P3, P4, E1, E2, E3, I1, I2, L2, L3, L4, B1, B2, B3, B4,
B5, W1, W2, W3, W4, W5, O1, O2, D1, D2, X1, X2, X3, A1, A2, A3, N1, N2, N3, F};
= ( - );
q0 = H;
F = {F, S}.
() 2.
p, e, i, b, w, o, x, a n
, (,
e, ):
P1, P2, P3, P4 prog;
E1, E2, E3 end end.;
I1, I2 if;
B1, B2, B3, B4, B5 begin;
W1, W2, W3, W4, B5 while;
E1, L2, L3, L4 else;
D1, D2 do;
O1, O2 or;
X1, X2, X3 ;
A1, A2, A3 and;
N1, N2, N3 not.
, () V. - ,
, , V,
(
, i els,
).
, , D.
C,
, .
G . ,
, .

140

. . . .

. 5.1. ( ).
(+ ), (<., .>
=.), ,
S, ,
,
. S ,
C1 ( C),
S.
L , <.. L , <.
<> () <. ().
H , F S .
, H,
, .
(H F) .
, .
, , .

141

. . . .

, ,
. (
) . 5.1.
, 2. , , LexElem, 2 ( 3.4, 3).
LexType ( 3.3, 3),
LexAuto ( 3.5, 3).



. ( ),
[13, 7]. - 3,
, .



(
3).
G.
, . 5.3.

5.3.
. 1

142

. . . .

, . 5.4
(
3).

5.4.
.

. G. , . 5.5.

5.5.
. 1

, . 5.5, , . 5.4 (

3). , . 5.6.

5.6.
.

143

. . . .

, . 5.6,
.

,

:
) else if(B) else ( ). , , else, , ), =. ( ). else
if(B) else , Rt(0) ). , else, , ), .> (). (
=. >), , G
.
?
-, ,
, , . , then endif, :
O if B then O else O endif | if B then O endif | begin L end | while(B)do O | a:=E
, G O, ,
.
-, , , G
, ( , [1, 3, 7], ,
).
, then, O :
O if B then O else O | if B then O | begin L end | while(B)do O | a:=E
then
else ,
144

. . . .

( else. G R, ,
, 3:
O if B then R else O | if B then O | begin L end | while(B)do O | a:=E
R if B then R else R | begin L end | while(B)do O | a:=E
, G O, ,
.
, . , ,

.
,
(, , G
). , ,
, ( ).9
, ,
. .
,
= >, ,
.
? :
-, , if else ( : if(a<b) then if(a<c) then a:=c else a:=b;);
-, if ( ) ( ),
else:
, )
. .
, : else if. , , .
, else
if, , .
, , , else, , ), =. ( ), , .
, ,
. 5.7 ( , <., .> =. ).
9

, ,
, .

145

. . . .

-
,
, [1, 2].

else
CorrectRul ( SyntRule, 3.6
3).
!


,
.
, ,
.
, G O
( do):
O if(B) O else O | if(B) O | begin L end | while(B) O | a:=E
,
while
else . , , . 5.7,
, :
if (<0) while (<10) :=+1 else :=1;
,
, ( , ,
do).

5.7.

146

. . . .



. while C
C++, , [13, 25,
32, 39]. ( R), G L
:
L | L;P | L;
if(B) ; else | if(B) R else | if(B) | while(B) | :=
R begin L end
|R
:
if (<0) while (<10) :=+1; else :=1;
C C++ begin end { }, : =. :
, (
else Pascal, ,
then else , .
5.7).
, .


,
G G'({prog,end.,if,
else,begin,end,while,do,or,xor,and,not,<,>,=,<>,(,), ,+,um,a,c,=}, {E},P',E) P':
E prog E end. 1
E E | E;E | E; 2, 3 4
147

. . . .

if(E) else | if(E) | begin end | while()do | := 5-9


or | | 10, 11 12
andE | 13 14
< | > | =. | <> | () | not(E) 15-20
- | + | 21, 22 23
urn | 24 25
(_) | | 26, 27 28
28 . .
, 2, 12, 14, 23 25, 19 26.
, ,
, ( :=( or b);, ). ,
, ,
, , .
B, .
,
G({prog,end.,if,else,begin,end,while,do,or,xor,and,not,<,>,=,<>,(,), ,+,um,a,c,=}, {E,B},P, E)
P:
E prog E end. 1
E E | E;E | E; 2-4
E if(B) EelseE | if(B) E | begin Eend | while(B)do E | a:=E 5-9
or | | 10-12
and | 13 14
< | > | = | <> | () | not(B) 15-20
- | + | 21-23
urn | 24 25
() | | 26-28
.


, 3.
SyntSymb ( 3.7, 3), - ,
, , .
SyntRul,
.
3.6 3 (
MakeSymbolStr,
!).
. ,
, 3.
148

. . . .



. ( 4).
:
( 4);
, , .
, . , .



. -
( 4).
:
(or, xor, and not);
(<, >, = <>);
(, , );
;
(if then else ) (if
then);
(while()do);
, , ( ,
beginend, ).
- (
), 4. .
-
- ( . 4.1
4).
:
1, ,
while (( ) ) ( )
.
, :
2, ;
149

. . . .

, .
2, do (
)
.
1. . 5.2.

. 5.2. - .
, ,
:
IF(<1>,<2>) ;
JMP(1,<2>) .

4.
. 4 ( ). ,
.
, : (1)
(0). , ( (TRUE)
(FALSE) , ,
). ,
:
OR ,
TRUE, TRUE;
OR ,
FALSE, FALSE.
:
if (a<b or a<c and b<c) a:=0 else a:=1;

:
150

. . . .

1: < (a, b)
2: < (a, c)
3: < (b, c)
4: and (^2, ^3)
5: or (^1, ^4)
6: if (^5, ^9)
7::= (a, 0)
8: jmp (1, ^10)
9::= (a, 1)
, :
1: < (a, b)
2: if01 (^3, ^7)
3: < (a, c)
4: if01 (^9, ^5)
5: < (b, c)
6: if01 (^9, ^7)
7::= (a, 0)
8: jmp (1, ^10)
9::= (a, 1)
IF01 : IF01(<1>,
<2>) , , 0 (), ,
.


, , .
, ,
( , ).
, , . ,
:
if (a<b or F1(a)<c and b<c) a:=0 else a:=1;
F1 , a < b, .
:
if (a>0 and M[a]<>0) M[a]:=0;
.
, M[a] <> 0
M a,
a>0, M,
M[a] <> 0. , .
, -
151

. . . .

. ,
- :
1 2.
- :
1. -
.
2. IF01, 2,
1.
- AND :
1. 1 .
,
2, 2.
2. 2 . , 1, 2.
- OR :
1. 1 .
,
1, 2.
2. 2 . , 1, 2.
- NOT :
.
, 2,
1 ( ).
, - ,
.
: , . : ,
- (, ), ,
, .10
-
.
:
1. 1, ,
if ( ) then ( ).
, 2, 3 ( )
( ).

10


3.12 3, .

152

. . . .

2. 2, then ( ) ( ).
3.
.
4. 3,
else ( )
(
).
:
1. 1, ,
while (( ) ) ( ).
,
2, .
2. 2, do (
)
( ).
3. 1.
:
;
( , ).
, Object Pascal , and, or, xor not,
( ),
C C++ .
,
( Complete Boolean
evaluations) .

. ,
, ,
. , ,
, ,
.
.
, ( - , ).
.

3 .

(
).
153

. . . .

[2].


3).

TrdType ( 3.8,

, 4, . .
Triads ( 3.10, 3).
, 4. , ( ),
- ( . 5.2).
:
,
Result;
,
InpVar Result.
,
(
).
TrdMake 3.12, 3.


. TrdAsm ( 3.13, 3).
( ) ( ). ,
, .
, ,
.
, , .
,
, , . ,
, ,
.
, , , ,
.
, .
154

. . . .


, , ,
.
, :
d:= a + b + c;
:= d *(a + b);
a:= d *(a + b) + 1;
:
1: + (a, b)
2: + (^1, c)
3::= (d, ^2)
4: * (d, ^1)
5::= (, ^4)
6: + (^4, 1)
7::= (a, ^6)
. 5.3.
,
( , ), . 5.3 , , 1,
4. , .

. 5.3. .
,
:
,
.
MakeRegisters TrdAsm.
.
( 0, , ). , ,
( listReg). ,
155

. . . .

,
.
Intel 80386
.
32 [41, 44]:
;
ebx;
;
edx;
esi;
edi.
esp , ebp
(
, [2, 3, 7]).
, eax ,
, .
,
, .

, . ( ).
, ,
,
, , . , , , ,
.
, .
,
.

eax. , ,
Intel 80x86
, (
) [41, 44].

MakeAsmCode TrdAsm ( 3.13, 3).
:
1. . , , , , , ( ).
2. , eax.
mov,
156

. . . .

( ), eax ,
, .
3. , eax (
: not ; neg ).
4. , (
and).
5. ,
mov, eax , .

:
1. .
, , ,
, ( ).
2. ( ), eax,
mov, eax.
3. , eax.
, , .
4. , ( sub ,
, neg).
5. ,
mov, eax , .
GetOpName.
MakeOper1 , MakeOper2 . , GetOpName CompileTest, ,
Result.
(
Result ). , , , .
,
,
,
( ).
(JMP) .
,
, , .
, , ( 157

. . . .

), .
,
. , :
1: < (a, b)

mov eax, a
cmp eax, b
jl @M1_1
xor eax, eax
jmp @M1_2
@M1_1: xor eax, eax
inc eax
@M1_2:
(eax) (0 , 1 ).
, ,
. . , , ,
. Intel 80x86 set<*>,
<*> [41, 44].
:
mov eax, a
cmp eax, b
setl al
and eax, 1
.

.
IF.
, ,
. ,
:
test eax, eax
, , IF , ,
, , , .
IF ( Intel 80x86 jz).
Intel 80x86 :
, 128
. IF, , ,
128 . , :
158

. . . .

,
:
jnz @Fx
jmp @Mx
Fx:
@Fx () , @Mx ,
. .11
IF:

, ,
. IF ,
. ,
:
a:= 1;
if (a<0) b:=0 else b:=1;
(b:=0)
( IF 0).
:
0 ; 0,
IF .
,
, ,
, .


-
- 4, .
, , , 4,
.
, - , TrdOpt ( 3.11, 3).
,
. , ( 4
).
TrdCalc ( 3.9, 3).

11

,
Delphi 5, .
, ,
.

159

. . . .


, .
. :
OR ,
, 0;
AND , ,
1;
, , 0,
0.
,
(), .
MakeOpcode TrdAsm ( 3.13, 3).

-
, , -
. ,
, , - .
- Intel 80x86 [41, 44]:
1. eax.
2. .
, eax
mov eax, 0
, eax, xor ( ) sub () . :
xor eax, eax
, eax
, . , , 1,
xor eax, eax
inc eax
-1
xor eax, eax
dec eax
. MakeMove TrdAsm ( 3.13,
3).
, ( Intel
80x86), (,
, ).
160

. . . .

,
, 1 -1,
, 1 ( inc dec):
inc add,
1;
dec add,
-1;
inc sub,
-1;
dec sub,
1.
. MakeOpcode TrdAsm ( 3.13,
3).
,
( ,
1) .
- . , ,
- - .


, , 3. ,
, 14.
, , - ,
CURSOV COMMON.
.


( ). , ,
24. ,
.
, (FormLab4), TCursovForm TForm VCL. Graphical User Interface (GUI) Windows
.
:
( FormLab4.pas);
( FormLab4.dfm).
GUI
[3, 57].
3.14 3. ,
161

. . . .

, , - ,
FormLab4.dfm CURSOV.
FormLab4 ,
4. , ,
24. , .
, 24, , FormLab4,
, :
(PageControl1) (SheetAsm)
;
SheetAsm : ListAsm
;
SheetFile ( )
( ): CheckAsm ,
.
TCursovForm . 5.4.

. 5.4. .
, 4.
, , . :
162

. . . .

MakeRegisters ( TrdAsm 3.13,


3), ,
(
), ;
ListAsm;
;
(
IdentList FncTree 3.2, 3);
, :
;
(integer);
CompileTest
;
, :
;

Compi 1 eTest ;
( begin asm
pushad );
MakeAsmCode ( 3.13, 3), ;
( popad
end);
.

CompRun. ,
,
.


,
.
:
<> <_> [<>]
:
<> ;
<> ( , ), ;
<> () ( ).
( ), , . ,
, , , ,
.
163

. . . .

( ). , ( ).
,
( ).

( FormCreate, FormLab4, 3.14 3). Param-Count
Object Pascal, (0
).
ParamStr Object Pascal, . .
.
( ,
).
. . . ( , "",
).
- (),
( ), ,
.
(
, ):
, , ; :
1 ( );
0 ( ), ,
, 0;
, ,
;
:
1 ( );
0 ( ), ,
, 0;
S , , ; :
1 ( );
0 ( ), ,
S, 0;
0 ,
( , ,
, );
164

. . . .

,
( , , ,
).
- , . :
;
;
.
, . asm. , . err.
, (
).

ProcessParams ( FormLab4, 3.14 3).
, :
cursov.exe myfile.txt
(cursov. ) myfi 1 . txt.
myfi 1 . asm,
, , myfile.err. ( ,

), .
:
cursov.exe infile.txt Ooutfile.asm Eerrfile.txt A0 S0
(cursov.exe) infile.txt.
outfile.asm,
, , errfile.txt. , (-
SO) .
,
, .
. ,
,
.
( ,
).
.
, .


:
1. , .
2. ,
.
4.
165

. . . .

, 31, 0.
. 4.1, 4.2, 4.
, , 0, . 4.3,
4.4 , ,
4.5 , . .12



,
Intel 80386 . , , .
,
:
(
);
InpVar;
Result.

,
.
, .
:
;
;
;
Intel 80x86.
, .
:
1. .
2.
.
12
Object Pascal,
, , Delphi ( ) ( ).
.
.

166

. . . .

3. .
4. .
5. .
6. .
, .
,
, , .

, .
,
, ,
. , ,
Intel 80x86.
, , , , , - .
,
, .

167

. . . .

1

2
:
- ;
(*) - , ;
(, , ,
);
( ) (_);
(*) ( ) (_), ;
0 9;
F ,
; :
v , ;
d , ;
a .
F .
:
M(Q,,,q0,F):
Q = {H, C, G, V, D, I1, I2, T1, T2, T3, T4, E1, E2, E3, E4, O1, O2, X1, X2, X3, A1, A2,
A3, F}
= ( - ); q0 = H; F = {F}.
1.1. .

1.1.

168

. . . .

169

. . . .

| F,
( ).

170

. . . .

2


:
- ;
(*) - , ;
(, , ,
);
( ) (_);
(*) ( ) (_), ;
0 9;
F ,
, :
v , ;
d , ;
a .
F .
:
M(Q,,,q0,F):
Q = {H, C, C1, G, S, L, V, D, P1, P2, P3, P4, E1, E2, E3, I1, I2, L2, L3, L4, B1, B2, B3, B4,
B5, W1, W2, W3, W4, W5, O1, O2, D1, D2, X1, X2, X3, A1, A2, A3, N1, N2, N3, F}
= ( - ); q0 = H; F = {F, S}.
2.1. .

2.1.

171

. . . .

172

. . . .

173

. . . .

174

. . . .

175

. . . .

| F,
( ).

176

. . . .

3




, Upper 3.1
:
REGNAME,
, (
);
REGNAME , , (
).

3.1.

unit TblElem;
interface
{ ,
}
type
TAddVarInfo = class(TObject) {
, }
public
procedure SetInfo(iIdx: integer; iInfo: longint);
virtual; abstract;
function GetInfo(iIdx: integer): longint;
virtual; abstract;
property Info[iIdx: integer]: longint
read GetInfo write SetInfo; default;
end;
TVarInfo = class(TObject)
protected { - }
sName: string; { }
pInfo: TAddVarInfo; { }
minEl,maxEl: TVarInfo; {
}
public
{ - }
constructor Create(const sN: string);
{ , }
destructor Destroy; override;
177

. . . .

{ }
procedure SetInfo(pI: TAddVarInfo);
{ }
procedure ClearInfo;
procedure ClearAllInfo;
{ }
property VarName: string read sName;
property Info: TAddVarInfo read pInfo write SetInfo;
{ }
function AddElCnt(const sAdd: string;
var iCnt: integer): TVarInfo;
function AddElem(const sAdd: string): TVarInfo;
{ }
function FindElCnt(const sN: string;
var iCnt: integer): TVarInfo;
function FindElem(const sN: string): TVarInfo;
{ }
function GetElList(const sLim,sInp,sOut: string): string;
end;
function Upper(const x: string): string;
implementation
uses SysUtils;
{ : REGNAME,
,
}
{$IFDEF REGNAME}
function Upper(const x: string): string;
begin Result:= UpperCase(x); end;
{$ELSE}
function Upper(const x: string): string;
begin Result:= x; end;
{$ENDIF}
constructor TVarInfo.Create(const sN: string);
{ - }
begin
inherited Create; { }
{ }
sName:= sN; pInfo:= nil;
minEl:= nil; maxEl:= nil;
end;
destructor TVarInfo.Destroy;
{ , }
begin
{ ,
}
ClearAllInfo;
minEl.Free; maxEl.Free;
inherited Destroy; { }
end;
178

. . . .

function TVarInfo.GetElList(const sLim{ },


sInp,sOut{, }: string): string;
{ }
var sAdd: string;
begin
Result:= ; { }
{
, }
if (Upper(sName) <> Upper(sInp))
and (Upper(sName) <> Upper(sOut)) then Result:= sName;
if minEl <> nil then { }
begin { }
sAdd:= minEl.GetElList(sLim,sInp,sOut);
if sAdd <> then { , }
begin { }
if Result <> then Result:= Result + sLim + sAdd
else Result:= sAdd;
end;
end;
if maxEl <> nil then { }
begin { }
sAdd:= maxEl.GetElList(sLim,sInp,sOut);
if sAdd <> then { , }
begin { }
if Result <> then Result:= Result + sLim + sAdd
else Result:= sAdd;
end;
end;
end;
procedure TVarInfo.SetInfo(pI: TAddVarInfo);
{ }
begin pInfo:= pI; end;
procedure TVarInfo.ClearInfo;
{ }
begin pInfo.Free; pInfo:= nil; end;
procedure TVarInfo.ClearAllInfo;
{ }
begin
if minEl <> nil then minEl.ClearAllInfo;
if maxEl <> nil then maxEl.ClearAllInfo;
ClearInfo;
end;
function TVarInfo.AddElCnt(const sAdd: string;
var iCnt: integer): TVarInfo;
{
}
var i: integer;
begin
Inc(iCnt); { }
179

. . . .

{ ( !) }
i:= StrComp(PChar(Upper(sAdd)), PChar(Upper(sName)));
if i < 0 then
{ , }
begin { ,
}
if minEl <> nil then
Result:= minEl.AddElCnt(sAdd,iCnt)
else
begin { ,
}
Result:= TVarInfo.Create(sAdd);
minEl:= Result;
end;
end
else
{ , }
if i > 0 then
begin { ,
}
if maxEl <> nil then
Result:= maxEl.AddElCnt(sAdd,iCnt)
else
begin { ,
}
Result:= TVarInfo.Create(sAdd);
maxEl:= Result;
end;
end { ,
}
else Result:= Self;
end;
function TVarInfo.AddElem(const sAdd: string): TVarInfo;
{ }
var iCnt: integer;
begin Result:= AddElCnt(sAdd,iCnt); end;
function TVarInfo.FindElCnt(const sN: string;
var iCnt: integer): TVarInfo;
{
}
var i: integer;
begin
Inc(iCnt); { }
{ ( !) }
i:= StrComp(PChar(Upper(sN)), PChar(Upper(sName)));
if i < 0 then
{ , }
begin { ,
, }
180

. . . .

if minEl <> nil then Result:= minEl.FindElCnt(sN,iCnt)


else Result:= nil;
end
else
if i > 0 then
{ , }
begin { ,
, }
if maxEl <> nil then Result:= maxEl.FindElCnt(sN,iCnt)
else Result:= nil;
end { , }
else Result:= Self;
end;
function TVarInfo.FindElem(const sN: string): TVarInfo;
{ }
var iCnt: integer;
begin Result:= FindElCnt(sN,iCnt); end;
end.

181

. . . .


3.2.
-
unit FncTree;
interface
{ ,
, -
}
uses TblElem;
{ - }
procedure InitTreeVar;
{ - }
procedure ClearTreeVar;
{ }
procedure ClearTreeInfo;
{ }
function AddTreeVar(const sName: string): TVarInfo;
{ }
function GetTreeVar(const sName: string): TVarInfo;
{ , }
function GetTreeCount: integer;
{ }
function IdentList(const sLim,sInp,sOut: string): string;
implementation
const { - }
HASH_MIN = Ord(0 )+Ord(0 ); {( }
HASH_MAX = Ord('z')+Ord('z'); { -)}
var { - }
HashArray: array[HASH_MIN..HASH_MAX] of TVarInfo;
iCmpCount: integer; { }
function GetTreeCount: integer;
begin Result:= iCmpCount; end;
function IdentList(const sLim,sInp,sOut: string): string;
{ }
var
i: integer; { }
sAdd: string; { }
begin
Result:= ; { }
for i:=HASH_MIN to HASH_MAX do
begin { }
{ , , }
if HashArray[i] = nil then sAdd:=
182

. . . .

{ }
else sAdd:= HashArray[i].GetElList(sLim,sInp,sOut);
if sAdd <> then
begin { ,
}
if Result <> then Result:= Result + sLim + sAdd
else Result:= sAdd;
end;
end{for};
end;
function VarHash(const sName: string): longint;
{ - }
begin
Result:= (Ord(sName[1])
+ Ord(sName[(Length(sName)+1) div 2])
HASH_MIN) mod (HASH_MAX-HASH_MIN+1)+HASH_MIN;
if Result < HASH_MIN then Result:= HASH_MIN;
end;
procedure InitTreeVar;
{ - }
var i: integer;
begin for i:=HASH_MIN to HASH_MAX do HashArray[i]:= nil;
end;
procedure ClearTreeVar;
{ - }
var i: integer;
begin
for i:=HASH_MIN to HASH_MAX do
begin
HashArray[i].Free; HashArray[i]:= nil;
end;
end;
procedure ClearTreeInfo;
{ }
var i: integer;
begin
for i:=HASH_MIN to HASH_MAX do
if HashArray[i] <> nil then HashArray[i].ClearAllInfo;
end;
function AddTreeVar(const sName: string): TVarInfo;
{ - }
var iHash: integer;
begin
iCmpCount:= 0; { }
iHash:= VarHash(Upper(sName)); { - }
if HashArray[iHash] <> nil then
Result:= HashArray[iHash].AddElCnt(sName,iCmpCount)
else
begin
183

. . . .

Result:= TVarInfo.Create(sName);
HashArray[iHash]:= Result;
end;
end;
function GetTreeVar(const sName: string): TVarInfo;
{ }
var iHash: integer;
begin
iCmpCount:= 0; { }
iHash:= VarHash(Upper(sName)); { - }
if HashArray[iHash] = nil then Result:= nil
{ , }
else { }
Result:= HashArray[iHash].FindElCnt(sName,iCmpCount)
end;
initialization
{ }
InitTreeVar;
finalization
{ }
ClearTreeVar;
end.

184

. . . .


..
unit LexType; {!!! !!!}
interface
{ , }
type
TLexType = { }
(LEX_PROG, LEX_FIN, LEX_SEMI, LEX_IF, LEX_OPEN, LEX_CLOSE,
LEX_ELSE, LEX_BEGIN, LEX_END, LEX_WHILE, LEX_DO, LEX_VAR,
LEX_CONST, LEX_ASSIGN, LEX_OR, LEX_XOR, LEX_AND,
LEX_LT, LEX_GT, LEX_EQ, LEX_NEQ, LEX_NOT,
LEX_SUB, LEX_ADD, LEX_UMIN, LEX_START);
{ }
function LexTypeName(lexT: TLexType): string;
{ }
function LexTypeInfo(lexT: TLexType): string;
implementation
function LexTypeName(lexT: TLexType): string;
{ }
begin
case lexT of
LEX_OPEN: Result:= ' ';
LEX_CLOSE: Result:= ' ';
LEX_ASSIGN: Result:= ' ';
LEX_VAR: Result:= '';
LEX_CONST: Result:= '';
LEX_SEMI: Result:= '';
LEX_ADD,LEX_SUB,LEX_UMIN,LEX_GT,LEX_LT,LEX_EQ,
LEX_NEQ: Result:= ' ';
else Result:= ' ';
end;
end;
function LexTypeInfo(lexT: TLexType): string;
{ }
begin
case lexT of
LEX_PROG: Result:= 'prog';
LEX_FIN: Result:= 'end.;
LEX_SEMI: Result:=; ;
LEX_IF: Result:= 'if';
LEX_OPEN: Result:= ( ;
LEX_CLOSE: Result:=) ;
LEX_ELSE: Result:= 'else';
LEX_BEGIN: Result:= 'begin';
LEX_END: Result:= 'end';
185

. . . .

LEX_WHILE: Result:= 'while';


LEX_DO: Result:= 'do';
LEX_VAR: Result:= 'a';
LEX_CONST: Result:= 'c';
LEX_ASSIGN: Result:=:=;
LEX_OR: Result:= 'or';
LEX_XOR: Result:= 'xor';
LEX_AND: Result:= 'and';
LEX_LT: Result:= <;
LEX_GT: Result:= >;
LEX_EQ: Result:= = ;
LEX_NEQ: Result:= <>;
LEX_NOT: Result:= 'not';
LEX_ADD: Result:= + ;
LEX_SUB,
LEX_UMIN: Result:= ;
else Result:= ;
end;
end;
end.

186

. . . .



3.4.
unit LexElem;
interface
{ , }
uses Classes, TblElem, LexType;
type
TLexInfo = record { }
case LexType: TLexType of
LEX_VAR: (VarInfo: TVarInfo);
LEX_CONST: (ConstVal: integer);
LEX_START: (szInfo: PChar);
end;
TLexem = class(TObject) { }
protected
LexInfo: TLexInfo; { }
{ }
iStr,iPos,iAllP: integer;
public
{ }
constructor CreateKey(LexKey: TLexType;
iA,iSt,iP: integer);
constructor CreateVar(VarInf: TVarInfo;
iA,iSt,iP: integer);
constructor CreateConst(iVal: integer;
iA,iSt,iP: integer);
constructor CreateInfo(sInf: string;
iA,iSt,iP: integer);
destructor Destroy; override;
{ }
property LexType: TLexType read LexInfo.LexType;
property VarInfo: TVarInfo read LexInfo.VarInfo;
property ConstVal: integer read LexInfo.ConstVal;
{ }
property StrNum: integer read iStr;
property PosNum: integer read iPos;
property PosAll: integer read iAllP;
function LexInfoStr: string; { }
function VarName: string; { - }
end;
TLexList = class(TList)
public { }
{ }
187

. . . .

destructor Destroy; override;


procedure Clear; override; { }
{ }
function GetLexem(iIdx: integer): TLexem;
property Lexem[i: integer]: TLexem read GetLexem; default;
end;
implementation
uses SysUtils, LexAuto;
constructor TLexem.CreateKey(LexKey: TLexType;
iA,iSt,iP: integer);
{ }
begin
inherited Create; { }
LexInfo.LexType:= LexKey; { }
iStr:= iSt; { }
iPos:= iP; iAllP:= iA;
end;
constructor TLexem.CreateVar(VarInf: TVarInfo;
iA,iSt,iP: integer);
{ }
begin
inherited Create; { }
LexInfo.LexType:= LEX_VAR; { }
{ }
LexInfo.VarInfo:= VarInf;
iStr:= iSt; { }
iPos:= iP; iAllP:= iA;
end;
constructor TLexem.CreateConst(iVal: integer;
iA,iSt,iP: integer);
{ }
begin
inherited Create; { }
LexInfo.LexType:= LEX_CONST; { }
{ }
LexInfo.ConstVal:= iVal;
iStr:= iSt; { }
iPos:= iP; iAllP:= iA;
end;
constructor TLexem.CreateInfo(sInf: string;
iA,iSt,iP: integer);
{ }
begin
inherited Create; { }
LexInfo.LexType:= LEX_START; { . }
{ }
LexInfo.szInfo:= StrAlloc(Length(sInf)+1);
StrPCopy(LexInfo.szInfo,sInf); { }
iStr:= iSt; { }
188

. . . .

iPos:= iP; iAllP:= iA;


end;
destructor TLexem.Destroy;
{ }
begin { , }
if LexType = LEX_START then StrDispose(LexInfo.szInfo);
inherited Destroy; { }
end;
function TLexem.VarName: string;
{ }
begin Result:= VarInfo.VarName; end;
function TLexem.LexInfoStr: string;
{ }
begin
case LexType of { }
LEX_VAR: Result:= VarName; { }
LEX_CONST: Result:= IntToStr(ConstVal);
{ }
LEX_START: Result:= StrPas(LexInfo.szInfo);
{ . }
else Result:= LexTypeInfo(LexType);
{ }
end;
end;
procedure TLexList.Clear;
{ }
var i: integer;
begin { }
for i:=Count-1 downto 0 do Lexem[i].Free;
inherited Clear; { }
end;
destructor TLexList.Destroy;
{ }
begin
Clear; { }
inherited Destroy; { }
end;
function TLexList.GetLexem(iIdx: integer): TLexem;
{ }
begin Result:= TLexem(Items[iIdx]); end;
end.

189

. . . .



3.5.

unit LexAuto; {!!! !!!}
interface
{ }
uses Classes, TblElem, LexType, LexElem;
{ }
function MakeLexList(listFile: TStrings;
listLex: TLexList): integer;
implementation
uses SysUtils, FncTree;
type { }
TAutoPos = (
AP_START,AP_IF1,AP_IF2,AP_NOT1,AP_NOT2,AP_NOT3,
AP_ELSE1,AP_ELSE2,AP_ELSE3,AP_ELSE4,AP_END2,AP_END3,
AP_PROG1,AP_PROG2,AP_PROG3,AP_PROG4,AP_OR1,AP_OR2,
AP_BEGIN1,AP_BEGIN2,AP_BEGIN3,AP_BEGIN4,AP_BEGIN5,
AP_XOR1,AP_XOR2,AP_XOR3,AP_AND1,AP_AND2,AP_AND3,
AP_WHILE1,AP_WHILE2,AP_WHILE3,AP_WHILE4,AP_WHILE5,
AP_COMM,AP_COMMSG,AP_ASSIGN,AP_VAR,AP_CONST,
AP_DO1,AP_DO2,AP_SIGN,AP_LT,AP_FIN,AP_ERR);
function MakeLexList(listFile: TStrings;
listLex: TLexList): integer;
{ }
var
i,j,iCnt,iStr, { }
iAll,{ }
{ }
iStComm,iStart: 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;
190

. . . .

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;
191

. . . .

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_SUB,AP_SIGN);
'+: AddVarKeyToList(LEX_ADD,AP_SIGN);
'=: AddVarKeyToList(LEX_EQ,AP_SIGN);
'>: AddKeyToList(LEX_GT,AP_SIGN);
'<: AddVarToList(AP_LT,j);
'(: AddVarKeyToList(LEX_OPEN,AP_SIGN);
'): AddVarKeyToList(LEX_CLOSE,AP_START);
';: AddVarKeyToList(LEX_SEMI,AP_START);
'{: AddVarToList(AP_COMM,j);
',#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
'-: Add2KeysToList(keyAdd,LEX_UMIN,AP_SIGN);
'+: Add2KeysToList(keyAdd,LEX_ADD,AP_SIGN);
'=: Add2KeysToList(keyAdd,LEX_EQ,AP_SIGN);
'>: Add2KeysToList(keyAdd,LEX_GT,AP_SIGN);
'<: AddKeyToList(keyAdd,AP_LT);
'(: Add2KeysToList(keyAdd,LEX_OPEN,AP_SIGN);
'): Add2KeysToList(keyAdd,LEX_CLOSE,AP_START);
';: Add2KeysToList(keyAdd,LEX_SEMI,AP_START);
'0.. 9 ,'A'..'Z','a'..'z', _ : posCur:= AP_VAR;
'{: AddKeyToList(keyAdd,AP_COMMSG);
',#10,#13,#9: AddKeyToList(keyAdd,AP_SIGN);
else posCur:= AP_ERR;
end{case list};
end;
192

. . . .

begin { }
iAll:= 0; { }
Result:= 0; { }
posCur:= AP_START;{ }
iStComm:= 0; iCnt:= listFile.Count-1;
for i:=0 to iCnt do { }
begin
iStart:= 1; { }
sCurStr:= listFile[i]; { }
iStr:= Length(sCurStr);
for j:=1 to iStr do { }
begin
Inc(iAll); { }
{
}
case posCur of
AP_START:
begin {
}
iStart:= j; iStComm:= iAll-1;
case sCurStr[j] of
'b': posCur:= AP_BEGIN1;
'i': posCur:= AP_IF1;
'p': posCur:= AP_PROG1;
'e': posCur:= AP_ELSE1;
'w': posCur:= AP_WHILE1;
'd': posCur:= AP_DO1;
'o': posCur:= AP_OR1;
'x': posCur:= AP_XOR1;
'a': posCur:= AP_AND1;
'n': posCur:= AP_NOT1;
':: posCur:= AP_ASSIGN;
'-: AddKeyToList(LEX_SUB,AP_SIGN);
'+: AddKeyToList(LEX_ADD,AP_SIGN);
'=: AddKeyToList(LEX_EQ,AP_SIGN);
'>: AddKeyToList(LEX_GT,AP_SIGN);
'<: posCur:= AP_LT;
'(: AddKeyToList(LEX_OPEN,AP_SIGN);
'): AddKeyToList(LEX_CLOSE,AP_START);
';: AddKeyToList(LEX_SEMI,AP_START);
'0.. 9 : posCur:= AP_CONST;
'A'..'Z','c','f'..'h','j'..'m',
'q'..'v','y','z', _ : posCur:= AP_VAR;
'{: posCur:= AP_COMM;
',#10,#13,#9:;
else posCur:= AP_ERR;
end{case list};
end;
AP_SIGN:
193

. . . .

begin { ,
}
iStart:= j; iStComm:= iAll-1;
case sCurStr[j] of
'b': posCur:= AP_BEGIN1;
'i': posCur:= AP_IF1;
'p': posCur:= AP_PROG1;
'e': posCur:= AP_ELSE1;
'w': posCur:= AP_WHILE1;
'd': posCur:= AP_DO1;
'o': posCur:= AP_OR1;
'x': posCur:= AP_XOR1;
'a': posCur:= AP_AND1;
'n': posCur:= AP_NOT1;
'-: AddKeyToList(LEX_UMIN,AP_SIGN);
'(: AddKeyToList(LEX_OPEN,AP_SIGN);
'): AddKeyToList(LEX_CLOSE,AP_START);
'0.. 9 : posCur:= AP_CONST;
'A'..'Z','c','f'..'h','j'..'m',
'q'..'v','y','z', _ : posCur:= AP_VAR;
'{: posCur:= AP_COMMSG;
',#10,#13,#9:;
else posCur:= AP_ERR;
end{case list};
end;
AP_LT: { ? }
case sCurStr[j] of
'b': AddKeyToList(LEX_LT,AP_BEGIN1);
'i': AddKeyToList(LEX_LT,AP_IF1);
'p': AddKeyToList(LEX_LT,AP_PROG1);
'e': AddKeyToList(LEX_LT,AP_ELSE1);
'w': AddKeyToList(LEX_LT,AP_WHILE1);
'd': AddKeyToList(LEX_LT,AP_DO1);
'o': AddKeyToList(LEX_LT,AP_OR1);
'x': AddKeyToList(LEX_LT,AP_XOR1);
'a': AddKeyToList(LEX_LT,AP_AND1);
'n': AddKeyToList(LEX_LT,AP_NOT1);
'>: AddKeyToList(LEX_NEQ,AP_SIGN);
'-: Add2KeysToList(LEX_LT,LEX_UMIN,AP_SIGN);
'(: Add2KeysToList(LEX_LT,LEX_OPEN,AP_SIGN);
'0.. 9 : AddKeyToList(LEX_LT,AP_CONST);
'A'..'Z','c','f'..'h','j'..'m','q'..'v',
'y','z', _ : AddKeyToList(LEX_LT,AP_VAR);
'{: AddKeyToList(LEX_LT,AP_COMMSG);
',#10,#13,#9: AddKeyToList(LEX_LT,AP_SIGN);
else posCur:= AP_ERR;
end{case list};
AP_ELSE1: { else, end, ? }
case sCurStr[j] of
194

. . . .

'l': posCur:= AP_ELSE2;


'n': posCur:= AP_END2;
':: AddVarToList(AP_ASSIGN,j);
'-: AddVarKeyToList(LEX_SUB,AP_SIGN);
'+: AddVarKeyToList(LEX_ADD,AP_SIGN);
'=: AddVarKeyToList(LEX_EQ,AP_SIGN);
'>: AddKeyToList(LEX_GT,AP_SIGN);
'<: AddVarToList(AP_LT,j);
'(: AddVarKeyToList(LEX_OPEN,AP_SIGN);
'): AddVarKeyToList(LEX_CLOSE,AP_START);
';: AddVarKeyToList(LEX_SEMI,AP_START);
'{: AddVarToList(AP_COMM,j);
'0.. 9 ,'A'..'Z','a'..'k','m',
'o'..'z', _ : posCur:= AP_VAR;
',#10,#13,#9: AddVarToList(AP_START,j);
else posCur:= AP_ERR;
end{case list};
AP_IF1: KeyLetter('f',AP_IF2);
AP_IF2: KeyFinish(LEX_IF);
AP_ELSE2: KeyLetter('s',AP_ELSE3);
AP_ELSE3: KeyLetter('e',AP_ELSE4);
AP_ELSE4: KeyFinish(LEX_ELSE);
AP_OR1: KeyLetter('r',AP_OR2);
AP_OR2: KeyFinish(LEX_OR);
AP_DO1: KeyLetter('o',AP_DO2);
AP_DO2: KeyFinish(LEX_DO);
AP_XOR1: KeyLetter('o',AP_XOR2);
AP_XOR2: KeyLetter('r',AP_XOR3);
AP_XOR3: KeyFinish(LEX_XOR);
AP_AND1: KeyLetter('n',AP_AND2);
AP_AND2: KeyLetter('d',AP_AND3);
AP_AND3: KeyFinish(LEX_AND);
AP_NOT1: KeyLetter('o',AP_NOT2);
AP_NOT2: KeyLetter('t',AP_NOT3);
AP_NOT3: KeyFinish(LEX_NOT);
AP_PROG1: KeyLetter('r',AP_PROG2);
AP_PROG2: KeyLetter('o',AP_PROG3);
AP_PROG3: KeyLetter('g',AP_PROG4);
AP_PROG4: KeyFinish(LEX_PROG);
AP_WHILE1: KeyLetter('h',AP_WHILE2);
AP_WHILE2: KeyLetter('i',AP_WHILE3);
AP_WHILE3: KeyLetter('l',AP_WHILE4);
AP_WHILE4: KeyLetter('e',AP_WHILE5);
AP_WHILE5: KeyFinish(LEX_WHILE);
AP_BEGIN1: KeyLetter('e',AP_BEGIN2);
AP_BEGIN2: KeyLetter('g',AP_BEGIN3);
AP_BEGIN3: KeyLetter('i',AP_BEGIN4);
AP_BEGIN4: KeyLetter('n',AP_BEGIN5);
AP_BEGIN5: KeyFinish(LEX_BEGIN);
195

. . . .

AP_END2: KeyLetter('d',AP_END3);
AP_END3: { end, end., ? }
case sCurStr[j] of
'-: Add2KeysToList(LEX_END,LEX_UMIN,AP_SIGN);
'+: Add2KeysToList(LEX_END,LEX_ADD,AP_SIGN);
'=: Add2KeysToList(LEX_END,LEX_EQ,AP_SIGN);
'>: Add2KeysToList(LEX_END,LEX_GT,AP_SIGN);
'<: AddKeyToList(LEX_END,AP_LT);
'(: Add2KeysToList(LEX_END,LEX_OPEN,AP_SIGN);
'):Add2KeysToList(LEX_END,LEX_CLOSE,AP_START);
';: Add2KeysToList(LEX_END,LEX_SEMI,AP_START);
'.: AddKeyToList(LEX_FIN,AP_START);
'0.. 9 ,'A'..'Z','a'..'z', _ :
posCur:= AP_VAR;
'{: AddKeyToList(LEX_END,AP_COMMSG);
',#10,#13,#9: AddKeyToList(LEX_END,AP_SIGN);
else posCur:= AP_ERR;
end{case list};
AP_ASSIGN: { }
case sCurStr[j] of
'=: AddKeyToList(LEX_ASSIGN,AP_SIGN);
else posCur:= AP_ERR;
end{case list};
AP_VAR: { }
case sCurStr[j] of
':: AddVarToList(AP_ASSIGN,j);
'-: AddVarKeyToList(LEX_SUB,AP_SIGN);
'+: AddVarKeyToList(LEX_ADD,AP_SIGN);
'=: AddVarKeyToList(LEX_EQ,AP_SIGN);
'>: AddVarKeyToList(LEX_GT,AP_SIGN);
'<: AddVarToList(AP_LT,j);
'(: AddVarKeyToList(LEX_OPEN,AP_SIGN);
'): AddVarKeyToList(LEX_CLOSE,AP_START);
';: AddVarKeyToList(LEX_SEMI,AP_START);
'0.. 9 ,'A'..'Z','a'..'z', _ :
posCur:= AP_VAR;
'{: AddVarToList(AP_COMM,j);
',#10,#13,#9: AddVarToList(AP_START,j);
else posCur:= AP_ERR;
end{case list};
AP_CONST: { }
case sCurStr[j] of
':: AddConstToList(AP_ASSIGN,j);
'-: AddConstKeyToList(LEX_SUB,AP_SIGN);
'+: AddConstKeyToList(LEX_ADD,AP_SIGN);
'=: AddConstKeyToList(LEX_EQ,AP_SIGN);
'>: AddConstKeyToList(LEX_GT,AP_SIGN);
'<: AddConstToList(AP_LT,j);
'(: AddConstKeyToList(LEX_OPEN,AP_SIGN);
196

. . . .

'): AddConstKeyToList(LEX_CLOSE,AP_START);
';: AddConstKeyToList(LEX_SEMI,AP_START);
'0.. 9 : posCur:= AP_CONST;
'{: AddConstToList(AP_COMM,j);
',#10,#13,#9: AddConstToList(AP_START,j);
else posCur:= AP_ERR;
end{case list};
AP_COMM: { }
case sCurStr[j] of
'}: posCur:= AP_START;
end{case list};
AP_COMMSG: { }
case sCurStr[j] of
'}: posCur:= AP_SIGN;
end{case list};
end{case pos};
if j = iStr then { }
begin { }
case posCur of
AP_IF2: AddKeyToList(LEX_IF,AP_SIGN);
AP_PROG4: AddKeyToList(LEX_PROG,AP_START);
AP_ELSE4: AddKeyToList(LEX_ELSE,AP_START);
AP_BEGIN5: AddKeyToList(LEX_BEGIN,AP_START);
AP_WHILE5: AddKeyToList(LEX_WHILE,AP_SIGN);
AP_END3: AddKeyToList(LEX_END,AP_START);
AP_OR2: AddKeyToList(LEX_OR,AP_SIGN);
AP_DO2: AddKeyToList(LEX_DO,AP_SIGN);
AP_XOR3: AddKeyToList(LEX_XOR,AP_SIGN);
AP_AND3: AddKeyToList(LEX_AND,AP_SIGN);
AP_NOT3: AddKeyToList(LEX_AND,AP_SIGN);
AP_LT: AddKeyToList(LEX_LT,AP_SIGN);
AP_FIN: AddKeyToList(LEX_FIN,AP_START);
AP_CONST: AddConstToList(AP_START,j+1);
AP_ASSIGN: posCur:= AP_ERR;
AP_IF1,AP_PROG1,AP_PROG2,AP_PROG3,
AP_ELSE1,AP_ELSE2,AP_ELSE3,AP_XOR1,AP_XOR2,
AP_OR1,AP_DO1,AP_AND1,AP_AND2,AP_NOT1,AP_NOT2,
AP_WHILE1,AP_WHILE2,AP_WHILE3,AP_WHILE4,
AP_END2,AP_BEGIN1,AP_BEGIN2,AP_BEGIN3,AP_BEGIN4,
AP_VAR: AddVarToList(AP_START,j+1);
end{case pos2};
end;
if posCur = AP_ERR then {, }
begin { }
iStart:= (j iStart)+1; {
}
listLex.Insert(0,{ }
TLexem.CreateInfo(' ',
iAll-iStart,i,iStart));
197

. . . .

Break; { , }
end;
end{for j};
Inc(iAll,2); {
c 2: }
if posCur = AP_ERR then { , }
begin { }
Result:= i+1; Break;
end;
end{for i};
if posCur in [AP_COMM,AP_COMMSG] then
begin { , }
listLex.Insert(0,
TLexem.CreateInfo(' ',
iStComm,iCnt,iAll-iStComm));
Result:= iCnt;
end
else
if not (posCur in [AP_START,AP_SIGN,AP_ERR]) then
begin { }
listLex.Insert(0, { }
TLexem.CreateInfo(' ',
iAll-iStart,iCnt,iStart));
Result:= iCnt;
end;
end;
end.

198

. . . .



3.6.

unit SyntRule; {!!! !!!}
interface
{ ,
}
uses LexType, Classes;
const { }
RULE_LENGTH = 7; { ( ) }
RULE_NUM = 28; { }
Var { }
GramMatrix: array[TLexType,TLexType] of char =
({pr. end.; if () else beg end whl do a c:= or xor and < > = <> not + um! }
{pr.} ( , = , <, <, ,', ,'<, ,'<, ,'<, ,', ,', ,', ,', ,
', , , , ),
{end.}( , , , , , , , , , , , , , , , , , , , , ,
', , , , >),
{;} ( , >, >, <, ,', ,'<, >, <, ,'<, ,', ,', ,', ,', ,
', , , , ),
{if} ( , , , , = , , , , , , , , , , , , , , , , ,
', , , , ),
{(} ( , , , , <, =, ,', ,', ,'<, <,
', <, <, <, <, <, <, <, <, <, <, <, ),
{)} ( , >, >, <, ,'>, =, <, >, <, =, <, ,', >, >, >, >, >, >, >,
', >, >, ,'),
{else}( , >, >, <, ,', >, <, >, <, ,'<, ,', ,', ,', ,', ,
', , , , ),
{beg.}( , , <, <, ,', ,'<, =, <, ,'<, ,', ,', ,', ,', ,
', , , , ),
{end} ( , >, >, ,', ,'>, ,'>, ,', ,', ,', ,', ,', ,',
', , , , ),
{whil}( , , , , = , , , , , , , , , , , , , , , , ,
', , , , ),
{do} ( , >, >, <, ,', >, <, <, <, ,'<, ,', ,', ,', ,', ,
', , , , ),
{a} ( , >, >, ,', >, >, ,'>, ,', ,', =, >, >, >, >, >, >, >,
', >, >, ,'),
{c} ( , >, >, ,', >, >, ,'>, ,', ,', ,'>, >, >, >, >, >, >,
', >, >, ,'),
{:=} ( , >, >, ,'<, ,'>, ,'>, ,', <, <, ,', ,', ,', ,',
', <, <, <, ),
{or} ( , , , , <, >, ,', ,', ,'<, <,
199

. . . .

', >, >, <, <, <, <, <, <, <, <, <, ),
{xor} ( , , , , <, >, ,', ,', ,'<, <,
', >, >, <, <, <, <, <, <, <, <, <, ),
{and} ( , , , , <, >, ,', ,', ,'<, <,
', >, >, >, <, <, <, <, <, <, <, <, ),
{<} ( , , , , <, >, ,', ,', ,'<, <, ,'>, >, >, ,', ,',
', <, <, <, ),
{>} ( , , , , <, >, ,', ,', ,'<, <, ,'>, >, >, ,', ,',
', <, <, <, ),
{=} ( , , , , <, >, ,', ,', ,'<, <, ,'>, >, >, ,', ,',
', <, <, <, ),
{<>} ( , , , , <, >, ,', ,', ,'<, <, ,'>, >, >, ,', ,',
', <, <, <, ),
{not} ( , , , , = , , , , , , , , , , , , , , , , ,
', , , , ),
{-} ( , >, >, ,'<, >, >, ,'>, ,', <, <, ,'>, >, >, >, >, >, >,
', >, >, <, ),
{+} ( , >, >, ,'<, >, >, ,'>, ,', <, <, ,'>, >, >, >, >, >, >,
', >, >, <, ),
{um} ( , >, >, ,'<, >, >, ,'>, ,', <, <, ,'>, >, >, >, >, >, >,
', >, >, <, ),
{!} (<, ,', ,', ,', ,', ,', ,', ,', ,', ,', ,',
', , , , ));
{ }
GramRules: array[1..RULE_NUM] of string =
('progEend.,'E','E;E','E;,'if(B)EelseE','if(B)E',
'beginEend','while(B)doE','a:=E','BorB','BxorB','B',
'BandB','B','E<E','E>E','E=E','E<>E', (B),'not(B),
'E-E','E+E','E', -E','E', (E),'a','c');
{ }
function MakeSymbolStr(iRuleNum: integer): string;
{
}
function CorrectRule(cRule: char; lexTop,lexCur: TLexType;
symbStack: TList): char;
implementation
uses SyntSymb;
function MakeSymbolStr(iRuleNum: integer): string;
begin
if iRuleNum in [10..20] then Result:= 'B'
else Result:= 'E';
end;
function CorrectRule(cRule: char; lexTop,lexCur: TLexType;
symbStack: TList): char;
var j: integer;
begin { else,
}
Result:= cRule;
if (cRule = = ) and (lexTop = LEX_CLOSE)
200

. . . .

and (lexCur = LEX_ELSE) then


begin
j:= TSymbStack(symbStack). Count-1;
if (j > 2)
and (TSymbStack(symbStack)[j-2].SymbolStr <> 'B')
then Result:= >;
end;
end;
end.

201

. . . .


-
3.7.
-
unit SyntSymb;
interface
{ ,
- }
uses Classes, LexElem, SyntRule;
{ : () }
type TSymbKind = (SYMB_LEX, SYMB_SYNT);
TSymbInfo = record{ }
case SymbType: TSymbKind of { }
{ }
SYMB_LEX: (LexOne: TLexem);
{
, }
SYMB_SYNT: (LexList: TList);
end;
TSymbol = class; { }
{ , }
TSymbArray = array[0..RULE_LENGTH] of TSymbol;
TSymbol = class(TObject)
protected { , }
SymbInfo: TSymbInfo; { }
iRuleNum: integer; { , }
public
{ }
constructor CreateLex(Lex: TLexem);
{ }
constructor CreateSymb(iR,iSymbN: integer;
const SymbArr: TSymbArray);
{ }
destructor Destroy; override;
{ }
function GetItem(iIdx: integer): TSymbol;
{ }
function Count: integer;
{ , }
function SymbolStr: string;
{ , }
property SymbType: TSymbKind read SymbInfo.SymbType;
{ }
property Lexem: TLexem read SymbInfo.LexOne;
202

. . . .

{ , }
property Items[i: integer]: TSymbol read GetItem; default;
{ , }
property Rule: integer read iRuleNum;
end;
TSymbStack = class(TList)
public { , }
destructor Destroy; override; { }
procedure Clear; override; { }
{ }
function GetSymbol(iIdx: integer): TSymbol;
{ }
function Push(lex: TLexem): TSymbol;
{ }
property Symbols[iIdx: integer]: TSymbol read GetSymbol;
default;
{ , }
function TopLexem: TLexem;
{ ,
}
function MakeTopSymb: TSymbol;
end;
{ , - }
function BuildSyntList(const listLex: TLexList;
symbStack: TSymbStack): TSymbol;
implementation
uses LexType, LexAuto;
constructor TSymbol.CreateLex(Lex: TLexem);
{ }
begin
inherited Create; { }
SymbInfo.SymbType:= SYMB_LEX;{ }
SymbInfo.LexOne:= Lex; { }
iRuleNum:= 0; { , 0 }
end;
constructor TSymbol.CreateSymb(iR{ },
iSymbN{ }: integer;
const SymbArr: TSymbArray{ });
{
}
var i: integer;
begin
inherited Create; { }
{ }
SymbInfo.SymbType:= SYMB_SYNT;
{ }
SymbInfo.LexList:= TList.Create;
{ }
for i:=iSymbN-1 downto 0 do
203

. . . .

SymbInfo.LexList.Add(SymbArr[i]);
iRuleNum:= iR; { }
end;
function TSymbol.GetItem(iIdx: integer): TSymbol;
{ }
begin Result:= TSymbol(SymbInfo.LexList[iIdx]) end;
function TSymbol.Count: integer;
{ , }
begin Result:= SymbInfo.LexList.Count; end;
function TSymbol.SymbolStr: string;
{ , }
begin { ,
}
if SymbType = SYMB_SYNT then
Result:= MakeSymbolStr(iRuleNum)
{ ,
}
else Result:= Lexem.LexInfoStr;
end;
destructor TSymbol.Destroy;
{ }
var i: integer;
begin
if SymbInfo.SymbType = SYMB_SYNT then
with SymbInfo.LexList do
begin { , }
{ }
for i:=Count-1 downto 0 do TSymbol(Items[i]). Free;
Free; { }
end;
inherited Destroy; { }
end;
destructor TSymbStack.Destroy;
{ }
begin
Clear; { }
inherited Destroy; { }
end;
procedure TSymbStack.Clear;
{ }
var i: integer;
begin { }
for i:=Count-1 downto 0 do TSymbol(Items[i]). Free;
inherited Clear; { }
end;
function TSymbStack.GetSymbol(iIdx: integer): TSymbol;
{ }
begin Result:= TSymbol(Items[iIdx]); end;
function TSymbStack.TopLexem: TLexem;
204

. . . .

{ , }
var i: integer;
begin
Result:= nil; { }
for i:=Count-1 downto 0 do{ }
if Symbols[i].SymbType = SYMB_LEX then
begin { }
Result:= Symbols[i].Lexem; { }
Break; { }
end;
end;
function TSymbStack.Push(lex: TLexem): TSymbol;
{ }
begin { }
Result:= TSymbol.CreateLex(lex);
Add(Result); { }
end;
function TSymbStack.MakeTopSymb: TSymbol;
{ , . :
nil ,
( ).}
var
symCur: TSymbol; { }
SymbArr: TSymbArray;{ }
i,iSymbN: integer;{ }
sRuleStr: string; { }
{ }
procedure AddToRule(const sStr: string;{ }
sym: TSymbol{. });
begin
symCur:= sym; { }
{ }
SymbArr[iSymbN]:= Symbols[i];
{ (!) }
sRuleStr:= sStr + sRuleStr;
Delete(i); { }
Inc(iSymbN); { }
end;
begin
Result:= nil; { }
iSymbN:= 0; { }
symCur:= nil; { }
sRuleStr:= ; { }
for i:=Count-1 downto 0 do{ }
begin { }
if Symbols[i].SymbType = SYMB_SYNT then
{ ,
, }
AddToRule(Symbols[i].SymbolStr,symCur)
205

. . . .

else { }
if symCur = nil then { }
{ }
AddToRule(LexTypeInfo(Symbols[i].Lexem.LexType),
Symbols[i])
else {
"=" }
if GramMatrix[Symbols[i].Lexem.LexType,
symCur.Lexem.LexType] = = then
{ }
AddToRule(LexTypeInfo(Symbols[i].Lexem.LexType),
Symbols[i])
else { , }
Break;
if iSymbN > RULE_LENGTH then Break; {
, }
end;
if iSymbN <> 0 then
begin { ,
,
}
for i:=1 to RULE_NUM do
if GramRules[i] = sRuleStr then{ ,}
begin { }
Result:= TSymbol.CreateSymb(i,iSymbN,SymbArr);
Add(Result); { . }
Break; { }
end;
{ ( ),
, }
if Result = nil then
for i:=0 to iSymbN-1 do SymbArr[i].Free;
end;
end;
function BuildSyntList(
const listLex: TLexList{ };
symbStack: TSymbStack{ }
): TSymbol;
{ , -.
:
( ),
;
, ,
, . }
var
i,iCnt: integer; { }
lexStop: TLexem; { }
lexTCur: TLexType; { }
cRule: char;{ }
206

. . . .

begin
Result:= nil; { }
iCnt:= listLex.Count-1; { }
{ }
lexStop:= TLexem.CreateInfo(' ',0,0,0);
try { }
symbStack.Push(lexStop);
i:= 0; { }
while i<=iCnt do { }
begin { }
{ }
lexTCur:= symbStack.TopLexem.LexType;
{ ,
, }
if (lexTCur = LEX_START)
and (listLex[i].LexType = LEX_START) then Break;
{
}
cRule:= GramMatrix[lexTCur,listLex[i].LexType];
{ .
,
}
cRule:= CorrectRule(cRule,lexTCur,
listLex[i].LexType,symbStack);
case cRule of
'<, =: { () }
begin { }
symbStack.Push(listLex[i]);
Inc(i); { }
end;
'>: { }
if symbStack.MakeTopSymb = nil then
begin { , }
{ }
Result:= TSymbol.CreateLex(listLex[i]);
Break; { }
end;
else { }
begin { ( )}
Result:= TSymbol.CreateLex(listLex[i]);
Break; { }
end;
end{case};
end{while};
if Result = nil then { }
begin{, 2 }
if symbStack.Count = 2 then
{ , }
Result:= symbStack[1]
207

. . . .

{ }
else Result:= TSymbol.CreateLex(listLex[iCnt]);
end;
finally { }
lexStop.Free;
end;
end;
end.

208

. . . .


3.8.
unit TrdType; {!!! !!!}
interface
{ }
const { }
NAME_PROG = 'MyCurs';
NAME_INPVAR = 'InpVar';
NAME_RESULT = 'Result';
NAME_FUNCT = 'CompileTest';
NAME_TYPE = 'integer';
type { ,
, :
CONST ;
SAME ;
NOP (No OPerations) . }
TTriadType = (TRD_IF,TRD_OR,TRD_XOR,TRD_AND,TRD_NOT,
TRD_LT,TRD_GT,TRD_EQ,TRD_NEQ,TRD_ADD,TRD_SUB,TRD_UMIN,
TRD_ASSIGN,TRD_JMP,TRD_CONST,TRD_SAME,TRD_NOP);
{ }
TTriadStr = array[TTriadType] of string;
const TriadStr: TTriadStr =('if','or','xor','and','not',
'<, >, =, <>, +, -, -,
':=,'jmp','C','same','nop');
{ , }
TriadLineSet: set of TTriadType =
[TRD_OR, TRD_XOR, TRD_AND, TRD_NOT, TRD_ADD, TRD_SUB,
TRD_LT, TRD_GT, TRD_EQ, TRD_NEQ, TRD_UMIN];
implementation
end.

209

. . . .



3.9.

unit TrdCalc; {!!! !!!}
interface
{ , }
uses TrdType;
{ }
function CalcTriad(Triad: TTriadType;
iOp1,iOp2: integer): integer;
implementation
function CalcTriad(Triad: TTriadType;
iOp1,iOp2: integer): integer;
{ }
begin
Result:= 0;
case Triad of
TRD_OR: Result:= (iOp1 or iOp2) and 1;
TRD_XOR: Result:= (iOp1 xor iOp2) and 1;
TRD_AND: Result:= (iOp1 and iOp2) and 1;
TRD_NOT: Result:= (not iOp1) and 1;
TRD_LT: if iOp1<iOp2 then Result:= 1
else Result:= 0;
TRD_GT: if iOp1>iOp2 then Result:= 1
else Result:= 0;
TRD_EQ: if iOp1=iOp2 then Result:= 1
else Result:= 0;
TRD_NEQ: if iOp1<>iOp2 then Result:= 1
else Result:= 0;
TRD_ADD: Result:= iOp1 + iOp2;
TRD_SUB: Result:= iOp1 iOp2;
TRD_UMIN: Result:= iOp2;
end;
end;
end.

210

. . . .


3.10.
unit Triads;
interface
{ , }
uses Classes, TblElem, LexElem, TrdType;
type
TTriad = class; { }
TOpType = (OP_CONST, OP_VAR, OP_LINK); { :
, , }
TOperand = record { }
case OpType: TOpType of { }
OP_CONST: (ConstVal: integer);{ }
OP_VAR: (VarLink: TVarInfo);{
}
OP_LINK: (TriadNum: integer);{ }
end;
TOpArray = array[1..2] of TOperand; { 2 }
TTriad = class(TObject)
private { }
TriadType: TTriadType; { }
Operands: TOpArray; { }
public
Info: longint; {
}
IsLinked: Boolean; { }
{ }
constructor Create(Typ: TTriadType; const Ops: TOpArray);
{ }
function GetOperand(iIdx: integer): TOperand;
procedure SetOperand(iIdx: integer; Op: TOperand);
{ }
function GetLink(iIdx: integer): integer;
procedure SetLink(iIdx: integer; TrdN: integer);
{ }
function GetOpType(iIdx: integer): TOpType;
procedure SetOpType(iIdx: integer; OpT: TOpType);
{ }
function GetConstVal(iIdx: integer): integer;
procedure SetConstVal(iIdx: integer; iVal: integer);
{ , }
property TrdType: TTriadType read TriadType;
property Opers[iIdx: integer]: TOperand read GetOperand
write SetOperand; default;
property Links[iIdx: integer]: integer read GetLink
211

. . . .

write SetLink;
property OpTypes[iIdx: integer]: TOpType read GetOpType
write SetOpType;
property Values[iIdx: integer]: integer read GetConstVal
write SetConstVal;
{ , }
function IsEqual(Trd1: TTriad): Boolean;
{ , }
function MakeString(i: integer): string;
end;
TTriadList = class(TList)
public { }
procedure Clear; override; { }
destructor Destroy; override;{ }
{
}
procedure WriteToList(list: TStrings);
{ }
procedure DelTriad(iIdx: integer);
{ }
function GetTriad(iIdx: integer): TTriad;
{ }
property Triads[iIdx: integer]: TTriad read GetTriad;
default;
end;
{ }
procedure DelTriadTypes(listTriad: TTriadList;
TrdType: TTriadType);
implementation
uses SysUtils, FncTree, LexType;
constructor TTriad.Create(Typ: TTriadType;
const Ops: TOpArray);
{ }
var i: integer;
begin
inherited Create; { }
TriadType:= Typ; { }
{ }
for i:=1 to 2 do Operands[i]:= Ops[i];
Info:= 0; { }
IsLinked:= False; { }
end;
function TTriad.GetOperand(iIdx: integer): TOperand;
{ }
begin Result:= Operands[iIdx]; end;
procedure TTriad.SetOperand(iIdx: integer; Op: TOperand);
{ }
begin Operands[iIdx]:= Op; end;
function TTriad.GetLink(iIdx: integer): integer;
212

. . . .

{ }
begin Result:= Operands[iIdx].TriadNum; end;
procedure TTriad.SetLink(iIdx: integer; TrdN: integer);
{ }
begin Operands[iIdx].TriadNum:= TrdN; end;
function TTriad.GetOpType(iIdx: integer): TOpType;
{ }
begin Result:= Operands[iIdx].OpType; end;
function TTriad.GetConstVal(iIdx: integer): integer;
{ }
begin Result:= Operands[iIdx].ConstVal; end;
procedure TTriad.SetConstVal(iIdx: integer; iVal: integer);
{ }
begin Operands[iIdx].ConstVal:= iVal; end;
procedure TTriad.SetOpType(iIdx: integer; OpT: TOpType);
{ }
begin Operands[iIdx].OpType:= OpT; end;
function IsEqualOp(const Op1,Op2: TOperand): Boolean;
{ }
begin { , }
Result:= (Op1.OpType = Op2.OpType);
if Result then { }
case Op1.OpType of
OP_CONST: Result:= (Op1.ConstVal = Op2.ConstVal);
OP_VAR: Result:= (Op1.VarLink = Op2.VarLink);
OP_LINK: Result:= (Op1.TriadNum = Op2.TriadNum);
end;
end;
function TTriad.IsEqual(Trd1: TTriad): Boolean;
{ , }
begin { , }
Result:= (TriadType = Trd1.TriadType) { }
and IsEqualOp(Operands[1],Trd1[1])
and IsEqualOp(Operands[2],Trd1[2]);
end;
function GetOperStr(Op: TOperand): string;
{ }
begin
case Op.OpType of
OP_CONST: Result:= IntToStr(Op.ConstVal);
OP_VAR: Result:= Op.VarLink.VarName;
OP_LINK: Result:= ^ + IntToStr(Op.TriadNum+1);
end{case};
end;
function TTriad.MakeString(i: integer): string;
begin
Result:= Format(%d: #9 %s (%s, %s),
[i+1,TriadStr[TriadType],
GetOperStr(Opers[1]), GetOperStr(Opers[2])]);
213

. . . .

end;
destructor TTriadList.Destroy;
{ }
begin
Clear; { }
inherited Destroy; { }
end;
procedure TTriadList.Clear;
{ }
var i: integer;
begin { }
for i:=Count-1 downto 0 do TTriad(Items[i]). Free;
inherited Clear; { }
end;
procedure TTriadList.DelTriad(iIdx: integer);
{ }
begin
if iIdx < Count-1 then { ,
( )}
TTriad(Items[iIdx+1]). IsLinked:=
TTriad(Items[iIdx+1]). IsLinked
or TTriad(Items[iIdx]). IsLinked;
TTriad(Items[iIdx]). Free; { }
Delete(iIdx); { }
end;
function TTriadList.GetTriad(iIdx: integer): TTriad;
{ }
begin Result:= TTriad(Items[iIdx]); end;
procedure TTriadList.WriteToList(list: TStrings);
{
}
var i,iCnt: integer;
begin
list.Clear; { }
iCnt:= Count-1;
for i:=0 to iCnt do { }
{
}
list.Add(TTriad(Items[i]). MakeString(i));
end;
procedure DelTriadTypes(listTriad: TTriadList;
TrdType: TTriadType);
{ }
var
i,j,iCnt,iDel: integer;
listNum: TList;
Trd: TTriad; { }
begin
iDel:= 0; { }
214

. . . .

iCnt:= listTriad.Count-1;
{ }
listNum:= TList.Create;
try
for i:=0 to iCnt do { }
begin { }
{ }
listNum.Add(TObject(iDel));
{ , }
if listTriad[i].TriadType = TrdType then Inc(iDel);
end;
for i:=iCnt downto 0 do { }
begin { }
Trd:= listTriad[i];
{ , }
if Trd.TriadType = TrdType then listTriad.DelTriad(i)
else { ,
}
for j:=1 to 2 do
if Trd[j].OpType = OP_LINK then {
, }
Trd.Links[j]:=
Trd.Links[j] integer(listNum[Trd.Links[j]]);
end;
finally listNum.Free; { }
end;
end;
end.

215

. . . .

,

3.11.
unit TrdOpt;
interface
{ , :
;
. }
uses Classes, TblElem, LexElem, TrdType, Triads;
type { ,
}
TConstInfo = class(TAddVarInfo)
protected
iConst: longint; { }
{ }
constructor Create(iInfo: longint);
public { }
function GetInfo(iIdx: integer): longint; override;
procedure SetInfo(iIdx: integer; iInf: longint);
override;
end;
{ ,
}
TDepInfo = class(TAddVarInfo)
protected
iDep: longint; { }
{ }
constructor Create(iInfo: longint);
public { }
function GetInfo(iIdx: integer): longint; override;
procedure SetInfo(iIdx: integer; iInfo: longint);
override;
end;
{ }
procedure OptimizeConst(listTriad: TTriadList);
{ }
procedure OptimizeSame(listTriad: TTriadList);
implementation
uses SysUtils, FncTree, LexType, TrdCalc;
constructor TConstInfo.Create(iInfo: longint);
{ }
begin
inherited Create; { }
iConst:= iInfo; { }
216

. . . .

end;
procedure TConstInfo.SetInfo(iIdx: integer; iInf: longint);
{ }
begin iConst:= iInfo; end;
function TConstInfo.GetInfo(iIdx: integer): longint;
{ }
begin Result:= iConst; end;
function TestOperConst(Op: TOperand; listTriad: TTriadList;
var iConst: integer): Boolean;
{ ,
iConst }
var pInfo: TConstInfo;
begin
Result:= False;
case Op.OpType of { }
OP_CONST: { , }
begin
iConst:= Op.ConstVal; Result:= True;
end;
OP_VAR: { , }
begin {
, }
pInfo:= TConstInfo(Op.VarLink.Info);
if pInfo <> nil then { ,}
begin { }
iConst:= pInfo[0]; Result:= True;
end;
end;
OP_LINK: { , }
begin { ,
CONST }
if listTriad[Op.TriadNum].TrdType = TRD_CONST
then begin
iConst:= listTriad[Op.TriadNum][1].ConstVal;
Result:= True;
end;
end;
end{case};
end;
procedure OptimizeConst(listTriad: TTriadList);
{ }
var
i,j,iCnt,iOp1,iOp2: integer;
Ops: TOpArray;
Trd: TTriad;
begin
{ }
ClearTreeInfo; { CONST }
Ops[1].OpType:= OP_CONST;
217

. . . .

Ops[2].OpType:= OP_CONST;
Ops[2].ConstVal:= 0;
iCnt:= listTriad.Count-1;
for i:=0 to iCnt do { }
begin { }
Trd:= listTriad[i];
if Trd.TrdType in TriadLineSet then
begin {
CONST, }
for j:=1 to 2 do
if (Trd[j].OpType = OP_LINK)
and (listTriad[Trd.Links[j]].TrdType = TRD_CONST)
then begin
Trd.OpTypes[j]:= OP_CONST;
Trd.Values[j]:=
listTriad[Trd.Links[j]][1].ConstVal;
end;
end
else
if Trd.TrdType = TRD_IF then
begin {
CONST, }
if (Trd[1].OpType = OP_LINK)
and (listTriad[Trd.Links[1]].TrdType = TRD_CONST)
then begin
Trd.OpTypes[1]:= OP_CONST;
Trd.Values[1]:=
listTriad[Trd.Links[1]][1].ConstVal;
end;
end
else
if Trd.TrdType = TRD_ASSIGN then
begin {
CONST, }
if (Trd[2].OpType = OP_LINK)
and (listTriad[Trd.Links[2]].TrdType = TRD_CONST)
then begin
Trd.OpTypes[2]:= OP_CONST;
Trd.Values[2]:=
listTriad[Trd.Links[2]][1].ConstVal;
end;
end;{ ,
}
if Trd.IsLinked then ClearTreeInfo;
if Trd.TrdType = TRD_ASSIGN then { }
begin { }
{ , }
if TestOperConst(Trd[2],listTriad,iOp2) then
{ }
218

. . . .

Trd[1].VarLink.Info:= TConstInfo.Create(iOp2);
end
else { , }
if Trd.TrdType in TriadLineSet then
begin { , }
if TestOperConst(Trd[1],listTriad,iOp1)
and TestOperConst(Trd[2],listTriad,iOp2) then
begin { , }
Ops[1].ConstVal:=
CalcTriad(Trd.TrdType,iOp1,iOp2);
{ CONST,
}
listTriad.Items[i]:= TTriad.Create(TRD_CONST,Ops);
{ , }
listTriad[i].IsLinked:= Trd.IsLinked;
Trd.Free; { }
end;
end;
end;
end;
constructor TDepInfo.Create(iInfo: longint);
{ }
begin
inherited Create; { }
iDep:= iInfo; { }
end;
procedure TDepInfo.SetInfo(iIdx: integer; iInfo: longint);
{ }
begin iDep:= iInfo; end;
function TDepInfo.GetInfo(iIdx: integer): longint;
{ }
begin Result:= iDep; end;
function CalcDepOp(listTriad: TTriadList;
Op: TOperand): longint;
{ }
begin
Result:= 0;
case Op.OpType of { }
OP_VAR: {
, , }
if Op.VarLink.Info <> nil then Result:=
Op.VarLink.Info.Info[0];
OP_LINK: { ,
}
Result:= listTriad[Op.TriadNum].Info;
end{case};
end;
function CalcDep(listTriad: TTriadList;
Trd: TTriad): longint;
219

. . . .

{ }
var iDepTmp: longint;
begin
Result:= CalcDepOp(listTriad,Trd[1]);
iDepTmp:= CalcDepOp(listTriad,Trd[2]);
{ ,
}
if iDepTmp > Result then Result:= iDepTmp+1
else Inc(Result);
Trd.Info:= Result;
end;
procedure OptimizeSame(listTriad: TTriadList);
{ }
var
i,j,iStart,iCnt,iNum: integer;
Ops: TOpArray;
Trd: TTriad;
begin { }
iStart:= 0;
ClearTreeInfo; {
}
Ops[1].OpType:= OP_LINK; { }
Ops[2].OpType:= OP_CONST; { SAME }
Ops[2].ConstVal:= 0;
iCnt:= listTriad.Count-1;
for i:=0 to iCnt do { }
begin { }
Trd:= listTriad[i];
if Trd.IsLinked then { , }
begin { }
ClearTreeInfo; { }
iStart:= i; { }
end;
for j:=1 to 2 do {
if Trd[j].OpType = OP_LINK then { SAME, }
begin { , }
iNum:= Trd[j].TriadNum;{ }
if listTriad[iNum].TrdType = TRD_SAME then
Trd.Links[j]:= listTriad[iNum].Links[1];
end;
if Trd.TrdType = TRD_ASSIGN then { }
begin {
}
Trd[1].VarLink.Info:= TDepInfo.Create(i+1);
end
else { }
if Trd.TrdType in TriadLineSet then
begin { }
CalcDep(listTriad,Trd);
220

. . . .

for j:=iStart to i-1 do { }


begin { }
if Trd.IsEqual(listTriad[j]) { }
and (Trd.Info = listTriad[j].Info) then
begin { , }
Ops[1].TriadNum:= j;
{ SAME,
}
listTriad.Items[i]:=
TTriad.Create(TRD_SAME,Ops);
listTriad[i].IsLinked:= Trd.IsLinked; {
, }
Trd.Free; { }
Break; { }
end;
end;
end{if};
end{for};
end;
end.

221

. . . .



3.12.
unit TrdMake; {!!! !!!}
interface
{ ,
}
uses LexElem, Triads, SyntSymb;
function MakeTriadList(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{
.
nil ,
, }
implementation
uses LexType, TrdType;
function GetLexem(symbOp: TSymbol): TLexem;
{ , , }
begin
case symbOp.Rule of
0: Result:= symbOp.Lexem; { !}
27,28: Result:= symbOp[0].Lexem; {
27 28, }
19,26: Result:= GetLexem(symbOp[1]) {
, ,
}
else Result:= nil; { }
end;
end;
function MakeTriadListNOP(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{

( NOP ) }
var
Opers: TOpArray; { }
iIns1,iIns2,iIns3: integer; {
}
function MakeOperand(
iOp{ },
iSymOp{ },
iMin{ },
iSymErr{ ,
}: integer;
222

. . . .

var iIns: integer{ }): TLexem;


{ }
var lexTmp: TLexem;
begin
lexTmp:= GetLexem(symbTop[iSymOp]); { , }
if lexTmp <> nil then { }
with lexTmp do { , }
begin { }
if LexType = LEX_VAR then
begin
if VarInfo.VarName = NAME_RESULT then
begin{, }
Result:= lexTmp;
Exit;
end; { ,
}
Opers[iOp].OpType:= OP_VAR;
Opers[iOp].VarLink:= VarInfo;
end
else
if LexType = LEX_CONST then
begin { , }
Opers[iOp].OpType:= OP_CONST;
Opers[iOp].ConstVal:= ConstVal;
end
else begin { , }
Result:= lexTmp; { }
Exit;
end;
iIns:= iMin; Result:= nil;
end
else { }
begin { }
Result:= MakeTriadListNOP(symbTop[iSymOp],listTriad);
if Result <> nil then Exit; { }
iIns:= listTriad.Count; { }
if iIns <= iMin then { }
begin { }
Result:= symbTop[iSymErr].Lexem;
Exit;
end;
Opers[iOp].OpType:= OP_LINK;{ }
Opers[iOp].TriadNum:= iIns-1; { }
end;
end;
function MakeOperation(
Trd: TTriadType{ }): TLexem;
{ }
begin { }
223

. . . .

Result:= MakeOperand(1{op},0{sym},listTriad.Count,
1{sym err},iIns1);
if Result <> nil then Exit; { }
{ }
Result:= MakeOperand(2{op},2{sym},iIns1,
1{sym err},iIns2);
if Result <> nil then Exit; { }
{ }
listTriad.Add(TTriad.Create(Trd,Opers));
end;
begin { }
case symbTop.Rule of { }
5:{'if(B)EelseE'} { }
begin {
( if(B)) }
Result:= MakeOperand(1{op},2{sym},listTriad.Count,
1{sym err},iIns1);
{ , }
if Result <> nil then Exit;
Opers[2].OpType:= OP_LINK; { }
Opers[2].TriadNum:= 0; { ,
}
{ IF }
listTriad.Add(TTriad.Create(TRD_IF,Opers));
{ ( (B)E) }
Result:= MakeOperand(2{op},4{sym},iIns1,
3{sym err},iIns2);
{ , }
if Result <> nil then Exit;
Opers[1].OpType:= OP_CONST; { }
Opers[1].ConstVal:= 1; { JMP,
(B)E}
Opers[2].OpType:= OP_LINK; { }
Opers[2].TriadNum:= 0; { ,
}
{ JMP }
listTriad.Add(TTriad.Create(TRD_JMP,Opers));
{ IF
(B)E }
listTriad[iIns1].Links[2]:= iIns2+1;
{ ( elseE) }
Result:= MakeOperand(2{op},6{sym},iIns2,
5{sym err},iIns3);
{ , }
if Result <> nil then Exit;
{ JMP
elseE }
listTriad[iIns2].Links[2]:= iIns3;
end;
224

. . . .

6:{'if(B)E'} { }
begin {
( if(B)) }
Result:= MakeOperand(1{op},2{sym},listTriad.Count,
1{sym err},iIns1);
{ , }
if Result <> nil then Exit;
Opers[2].OpType:= OP_LINK; { }
Opers[2].TriadNum:= 0; { ,
}
{ IF }
listTriad.Add(TTriad.Create(TRD_IF,Opers));
{ ( (B)E) }
Result:= MakeOperand(2{op},4{sym},iIns1,
3{sym err},iIns2);
{ , }
if Result <> nil then Exit;
{ IF
(B)E }
listTriad[iIns1].Links[2]:= iIns2;
end;
8:{'while(B)doE'} { while }
begin {
( while(B)) }
iIns3:= listTriad.Count;
Result:= MakeOperand(1{op},2{sym},iIns3,
1{sym err},iIns1);
{ , }
if Result <> nil then Exit;
Opers[2].OpType:= OP_LINK; { }
Opers[2].TriadNum:= 0; { ,
}
{ IF }
listTriad.Add(TTriad.Create(TRD_IF,Opers));
{ ( doE) }
Result:= MakeOperand(2{op},5{sym},iIns1,
4{sym err},iIns2);
{ , }
if Result <> nil then Exit;
Opers[1].OpType:= OP_CONST; { }
Opers[1].ConstVal:= 1; { JMP,
doE }
{ }
Opers[2].OpType:= OP_LINK;
Opers[2].TriadNum:= iIns3;
{ JMP }
listTriad.Add(TTriad.Create(TRD_JMP,Opers));
{ IF
doE }
225

. . . .

listTriad[iIns1].Links[2]:= iIns2+1;
end;
9:{'a:=E'} { }
begin { ,
}
if symbTop[0].Lexem.LexType <> LEX_VAR then
begin
Result:= symbTop[0].Lexem; Exit;
end; {
, }
if (symbTop[0].Lexem.VarName = NAME_INPVAR)
or (symbTop[0].Lexem.VarName = NAME_RESULT) then
begin
Result:= symbTop[0].Lexem; Exit;
end;
{ }
Opers[1].OpType:= OP_VAR;
Opers[1].VarLink:= symbTop[0].Lexem.VarInfo;
{ }
Result:= MakeOperand(2{op},2{sym},listTriad.Count,
1{sym err},iIns1);
{ , }
if Result <> nil then Exit;
{ }
listTriad.Add(TTriad.Create(TRD_ASSIGN,Opers));
end;
{ }
10:{'BorB'} Result:= MakeOperation(TRD_OR);
11:{'BxorB'} Result:= MakeOperation(TRD_XOR);
13:{'BandB'} Result:= MakeOperation(TRD_AND);
15:{'E<E'} Result:= MakeOperation(TRD_LT);
16:{'E>E'} Result:= MakeOperation(TRD_GT);
17:{'E=E'} Result:= MakeOperation(TRD_EQ);
18:{'E<>E'} Result:= MakeOperation(TRD_NEQ);
21:{'E-E'} Result:= MakeOperation(TRD_SUB);
22:{'E+E'} Result:= MakeOperation(TRD_ADD);
20:{not(B)}
begin { }
Result:= MakeOperand(1{op},2{sym},listTriad.Count,
1{sym err},iIns1);
{ , }
if Result <> nil then Exit;
Opers[2].OpType:= OP_CONST; { }
Opers[2].ConstVal:= 0; { NOT }
{ NOT }
listTriad.Add(TTriad.Create(TRD_NOT,Opers));
end;
24:{uminE}
begin { }
226

. . . .

Result:= MakeOperand(2{op},1{sym},listTriad.Count,
0{sym err},iIns1);
{ , }
if Result <> nil then Exit;
Opers[1].OpType:= OP_CONST; { }
Opers[1].ConstVal:= 0; { "-"
0 }
{ UMIN }
listTriad.Add(TTriad.Create(TRD_UMIN,Opers));
end;
{ ,
}
1,7,19,26:{'progEend.,'beginEend', (E), (B) }
Result:= MakeTriadListNOP(symbTop[1],listTriad);
3:{E;E }
begin { }
Result:= MakeTriadListNOP(symbTop[0],listTriad);
if Result <> nil then Exit;
Result:= MakeTriadListNOP(symbTop[2],listTriad);
end;
27,28: Result:= nil; { }
{
}
else Result:= MakeTriadListNOP(symbTop[0],listTriad);
end{case Rule};
end;
function MakeTriadList(symbTop: TSymbol;
listTriad: TTriadList): TLexem;
{
}
var
i: integer;
Opers: TOpArray;
Trd: TTriad;
begin { }
Result:= MakeTriadListNOP(symbTop,listTriad);
if Result = nil then { , }
with listTriad do
begin { NOP }
Opers[1].OpType:= OP_CONST;
Opers[1].ConstVal:= 0;
Opers[2].OpType:= OP_CONST;
Opers[2].ConstVal:= 0;
Add(TTriad.Create(TRD_NOP,Opers));
for i:=Count-1 downto 0 do
begin { }
Trd:= Triads[i];
if Trd.TrdType in [TRD_IF,TRD_JMP] then
begin { (IF JMP)
227

. . . .

,}
if Trd.OpTypes[2] = OP_LINK then
listTriad[Trd.Links[2]].IsLinked:= True;
{ }
end;
end;
end;
end;
end.

228

. . . .



3.13.
unit TrdAsm;
{!!! !!! }
interface
{
}
uses Classes, TrdType, Triads;
const { }
TEMP_VARNAME = _Tmp';
NUM_PROCREG = 6; { }
{
}
function MakeRegisters(listTriad: TTriadList): integer;
{ }
function MakeAsmCode(listTriad: TTriadList;
listCode: TStrings;
flagOpt: Boolean): integer;
implementation
uses SysUtils;
function MakeRegisters(listTriad: TTriadList): integer;
{
.
: }
var
i,j,iR,iCnt,iNum: integer;{ }
{ }
listReg: TList;
begin { }
listReg:= TList.Create;
Result:= 0;
if listReg <> nil then
try { }
for i:=listTriad.Count-1 downto 0 do
listTriad[i].Info:= 0;
{ . ! }
for i:=listTriad.Count-1 downto 0 do
for j:=1 to 2 do { (2) }
{ , IF
( ), ( ) }
if ((listTriad[i].TrdType in TriadLineSet)
or (listTriad[i].TrdType = TRD_IF) and (j = 1)
or (listTriad[i].TrdType = TRD_ASSIGN) and (j = 2))
229

. . . .

{ }
and (listTriad[i][j].OpType = OP_LINK) then
begin { , }
iNum:= listTriad[i][j].TriadNum;
{
}
if (listTriad[iNum].Info = 0) and (iNum <> i-1) then
begin { }
iCnt:= listReg.Count-1;
for iR:=0 to iCnt do
begin{ }
{
, }
if longint(listReg[iR]) >= i then
begin { }
listReg[iR]:= TObject(iNum);
{ iNum }
listTriad[iNum].Info:= iR+1;
Break; { }
end;
end; {
, }
if listTriad[iNum].Info = 0 then
begin { ,
iNum }
listReg.Add(TObject(iNum));
{ iNum }
listTriad[iNum].Info:= listReg.Count;
end;
end;
end;{ :
-1, }
Result:= listReg.Count (NUM_PROCREG-1);
finally listReg.Free;
end;
end;
function GetRegName(iInfo: integer): string;
{ }
begin
case iInfo of
0: Result:= 'eax';
1: Result:= 'ebx';
2: Result:= 'ecx';
3: Result:= 'edx';
4: Result:= 'esi';
5: Result:= 'edi';
{ ,
}
else Result:=
230

. . . .

Format(%s%d',[TEMP_VARNAME,iInfo-NUM_PROCREG]);
end{case};
end;
function GetOpName(i: integer; listTriad: TTriadList;
iOp: integer): string;
{
i ;
listTriad ;
iOp }
var iNum: integer; { }
Triad: TTriad; { }
begin
Triad:= listTriad[i]; { }
{ }
case Triad[iOp].OpType of
{ }
OP_CONST: Result:= IntToStr(Triad[iOp].ConstVal);
{ }
OP_VAR:
begin
Result:= Triad[iOp].VarLink.VarName;
{ ,
Result }
if Result = NAME_FUNCT then Result:= NAME_RESULT;
end; { }
else { }
begin { }
iNum:= Triad[iOp].TriadNum;
{ , }
if iNum = i-1 then Result:=
else
begin { , }
iNum:= listTriad[iNum].Info;
{ , }
if iNum = 0 then Result:=
{ }
else Result:= GetRegName(iNum);
end;
end;
end{case};
end;
function MakeMove(const sReg,{ }
sPrev,{ }
sVal{ eax}: string;
flagOpt: Boolean{ }): string;
{ , eax }
begin { eax
,
}
231

. . . .

if (Pos(Format(#9'mov'#9 %s,eax',[sReg]), sPrev) = 1)


or (sVal = sReg) then
begin
Result:= ; Exit;
end;
if flagOpt then { }
begin
if sReg = 0 then { = 0, }
begin{ 1 1 INC DEC}
if sVal = -1 then Result:= #9'inc'#9'eax'
else
if sVal = 1 then Result:= #9'dec'#9'eax'
else Result:= #9'xor'#9'eax,eax'
end { XOR}
else
if sReg = 1 then { = 1, }
begin{ 1 0 NEG INC}
if sVal = -1 then Result:= #9'neg'#9'eax'
else
if sVal = 0 then Result:= #9'inc'#9'eax'
else
Result:= #9'xor'#9'eax,eax'#13#10#9'inc'#9'eax';
end { : XOR INC }
else
if sReg = -1 then { = -1, }
begin{ 1 0 NEG DEC}
if sVal = 1 then Result:= #9'neg'#9'eax'
else
if sVal = 0 then Result:= #9'dec'#9'eax'
else
Result:= #9'xor'#9'eax,eax'#13#10#9'dec'#9'eax';
end { : XOR DEC }
{ eax MOV }
else Result:= Format(#9'mov'#9'eax,%s',[sReg]);
end { ,
eax MOV }
else Result:= Format(#9'mov'#9'eax,%s',[sReg]);
end;
function MakeOpcode(i: integer;{ }
listTriad: TTriadList;{ }
const sOp,sReg,{ }
sPrev,{ }
sVal{ eax}: string;
flagOpt: Boolean{ }): string;
{ , eax }
var Triad: TTriad;{ }
begin { }
Triad:= listTriad[i];
if flagOpt then { }
232

. . . .

begin
if sReg = 0 then { = 0 }
begin
case Triad.TrdType of
TRD_AND: { AND = 0 }
Result:= MakeMove(0 ,sPrev,sVal,flagOpt);
{ OR, "+" - }
TRD_OR,TRD_ADD,TRD_SUB: Result:= #9#9;
{ }
else Result:= Format(#9 %s'#9'eax,%s',[sOp,sReg]);
end{case};
end
else
if sReg = 1 then { = 1 }
begin
case Triad.TrdType of
TRD_OR: { OR = 1 }
Result:= MakeMove(1 ,sPrev,sVal,flagOpt);
{ AND }
TRD_AND: Result:= #9#9;
{ "+" INC }
TRD_ADD: Result:= #9'inc'#9'eax';
{ - DEC }
TRD_SUB: Result:= #9'dec'#9'eax';
{ }
else Result:= Format(#9 %s'#9'eax,%s',[sOp,sReg]);
end{case};
end
else
if sReg = -1 then { = -1 }
begin
case Triad.TrdType of
{ "+" DEC }
TRD_ADD: Result:= #9'dec'#9'eax';
{ - INC }
TRD_SUB: Result:= #9'inc'#9'eax';
{ }
else Result:= Format(#9 %s'#9'eax,%s',[sOp,sReg]);
end{case};
end { }
else Result:= Format(#9 %s'#9'eax,%s',[sOp,sReg]);
end { ,
}
else Result:= Format(#9 %s'#9'eax,%s',[sOp,sReg]);
{
}
Result:= Result + Format(#9 { %s },
[Triad.MakeString(i)]);
end;
233

. . . .

function MakeAsmCode(
listTriad: TTriadList;{ }
listCode: TStrings;{ }
flagOpt: Boolean{ }): integer;
{ }
var i,iCnt: integer;{ }
sR: string;{ }
sPrev,sVal: string;
{ eax}
procedure TakePrevAsm;
{ , eax
}
var j: integer;
begin
j:= listCode.Count;
if j > 0 then
begin
sPrev:= listCode[j-1];
sVal:= StrPas(PChar(listCode.Objects[j-1]));
end
else
begin
sPrev:= ; sVal:= ;
end;
end;
procedure MakeOper1(const sOp,{ }
sAddOp: string;{ }
iOp: integer{ });
{ }
var sReg{ }: string;
begin
TakePrevAsm; { eax}
{ }
sReg:= GetOpName(i,listTriad,iOp);
if sReg <> then { ,
eax ,}
begin { eax }
{ }
sReg:= MakeMove(sReg,sPrev,sVal,flagOpt);
if sReg <> then listCode.Add(sReg);
end; { }
listCode.Add(Format(#9 %s'#9'eax'#9 { %s },
[sOp,listTriad[i].MakeString(i)]));
if sAddOp <> then { ,
}
listCode.Add(Format(#9 %s'#9'eax,1,[sAddOp]));
if listTriad[i].Info <> 0 then {
begin { , }
sReg:= GetRegName(listTriad[i].Info);
234

. . . .

{ , eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg]),
TObject(PChar(sReg)));
end;
end;
procedure MakeOper2(const sOp,{ }
sAddOp: string{ });
{
}
var sReg1,sReg2{ }: string;
begin
TakePrevAsm; { eax}
{ }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ , ,
eax }
if (sReg1 = ) or (sReg1 = sVal) then
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt))
else { ,
eax }
if (sReg2 = ) or (sReg2 = sVal) then
begin
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg1,
sPrev,sVal,flagOpt));
{ ,
( "-") }
if sAddOp <> then
listCode.Add(Format(#9 %s'#9'eax',[sAddOp]));
end
else { , :
eax ;
.}
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(MakeOpCode(i,listTriad,sOp,sReg2,
sPrev,sVal,flagOpt));
end;
if listTriad[i].Info <> 0 then {
begin { , }
sReg1:= GetRegName(listTriad[i].Info);
{ , eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg1]),
TObject(PChar(sReg1)));
end;
235

. . . .

end;
procedure MakeCompare(const sOp: string
{ });
{ }
var sReg1,sReg2{ }: string;
begin
TakePrevAsm; { eax}
{ }
sReg1:= GetOpName(i,listTriad,1);
sReg2:= GetOpName(i,listTriad,2);
{ ,
eax eax }
if sReg1 = then
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]))
else { ,
eax eax }
if sReg2 = then
listCode.Add(Format(#9'cmp'#9 %s,eax'#9 { %s },
[sReg1,listTriad[i].MakeString(i)]))
else { , :
eax ;
eax . }
begin
sReg1:= MakeMove(sReg1,sPrev,sVal,flagOpt);
if sReg1 <> then listCode.Add(sReg1);
listCode.Add(Format(#9'cmp'#9'eax,%s'#9 { %s },
[sReg2,listTriad[i].MakeString(i)]));
end; { eax 1 0
}
listCode.Add(Format(#9'set%s'#9'al',[sOp]));
listCode.Add(#9'and'#9'eax,1); { }
if listTriad[i].Info <> 0 then {
begin { , }
sReg1:= GetRegName(listTriad[i].Info);
{ , eax }
listCode.AddObject(Format(#9'mov'#9 %s,eax',[sReg1]),
TObject(PChar(sReg1)));
end;
end;
begin { }
iCnt:= listTriad.Count-1; { }
for i:=0 to iCnt do
begin { }
{ ,
}
if listTriad[i].IsLinked then
236

. . . .

listCode.Add(Format(@M%d:,[i+1]));
{ }
case listTriad[i].TrdType of
{ IF }
TRD_IF: { , }
begin {( )}
if listTriad[i][1].OpType = OP_CONST then
begin {
, = 0,}
if listTriad[i][1].ConstVal = 0 then
listCode.Add(Format(#9'jmp'#9 @M%d'#9 { %s },
[listTriad[i][2].TriadNum+1,
listTriad[i].MakeString(i)]));
end { .}
else { }
begin { }
sR:= GetOpName(i,listTriad,1);
{ ,
eax
, }
if sR = then
{ Z, eax
, ,
IF ,
, }
else { eax }
listCode.Add(Format(#9'cmp'#9 %s,0,[sR]));
{ NOT Z }
listCode.Add(Format(#9'jnz'#9 @F%d'#9 { %s },
[i,listTriad[i].MakeString(i)]));
{ }
listCode.Add(Format(#9'jmp'#9 @M%d',
[listTriad[i][2].TriadNum+1]));
{ }
listCode.Add(Format(@F%d:,[i]));
end;
end;
{ }
TRD_OR: MakeOper2('or', );
TRD_XOR: MakeOper2('xor', );
TRD_AND: MakeOper2('and', );
{ NOT ( NOT(0)=FFFFFFFF,
: AND eax,1 }
TRD_NOT: MakeOper1('not','and',1);
{ }
TRD_LT: MakeCompare('l');
TRD_GT: MakeCompare('g');
TRD_EQ: MakeCompare('e');
TRD_NEQ: MakeCompare('ne');
237

. . . .

{ }
TRD_ADD: MakeOper2('add', );
TRD_SUB: MakeOper2('sub','neg');
{ }
TRD_UMIN: MakeOper1('neg', ,2);
TRD_ASSIGN: { }
begin { eax}
TakePrevAsm;
sR:= GetOpName(i,listTriad,2); { }
{ ,
eax }
if sR <> then
begin { }
sVal:= MakeMove(sR,sPrev,sVal,flagOpt);
if sVal <> then listCode.Add(sVal);
end; { eax
}
sVal:= listTriad[i][1].VarLink.VarName;
if sVal = NAME_FUNCT then sVal:= NAME_RESULT;
sVal:= Format(#9'mov'#9 %s,eax'#9 { %s },
[sVal,listTriad[i].MakeString(i)]);
{ , eax }
listCode.AddObject(sVal,TObject(PChar(sR)));
end;
{ }
TRD_JMP: listCode.Add(
Format(#9'jmp'#9 @M%d'#9 { %s },
[listTriad[i][2].TriadNum+1,
listTriad[i].MakeString(i)]));
{ NOP }
TRD_NOP: listCode.Add(Format(#9'nop'#9#9 { %s },
[listTriad[i].MakeString(i)]));
end{case};
end{for};
Result:= listCode.Count;
end;
end.

238

. . . .



3.14.
unit FormLab4;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls,
Forms, Dialogs, StdCtrls, ComCtrls, Grids, ExtCtrls,
LexElem, SyntSymb, Triads;
type { : ,
, , }
TErrType = (ERR_FILE,ERR_LEX,ERR_SYNT,ERR_TRIAD,ERR_NO);
TCursovForm = class(TForm) { }
PageControl1: TPageControl;
SheetFile: TTabSheet;
SheetLexems: TTabSheet;
BtnExit: TButton;
GroupText: TGroupBox;
ListIdents: TMemo;
EditFile: TEdit;
BtnFile: TButton;
BtnLoad: TButton;
FileOpenDlg: TOpenDialog;
GridLex: TStringGrid;
SheetSynt: TTabSheet;
TreeSynt: TTreeView;
SheetTriad: TTabSheet;
GroupTriadAll: TGroupBox;
Splitter1: TSplitter;
GroupTriadSame: TGroupBox;
Splitter2: TSplitter;
GroupTriadConst: TGroupBox;
ListTriadAll: TMemo;
ListTriadConst: TMemo;
ListTriadSame: TMemo;
CheckDel_C: TCheckBox;
CheckDelSame: TCheckBox;
SheetAsm: TTabSheet;
ListAsm: TMemo;
CheckAsm: TCheckBox;
procedure BtnLoadClick(Sender: TObject);
procedure BtnFileClick(Sender: TObject);
239

. . . .

procedure EditFileChange(Sender: TObject);


procedure BtnExitClick(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormClose(Sender: TObject;
var Action: TCloseAction);
private
listLex: TLexList; { }
symbStack: TSymbStack; { }
listTriad: TTriadList; { }
{ : , }
sInpFile,sOutFile,sErrFile: string;
{ }
procedure StartInfo(const sErrF: string);
{ }
procedure ProcessParams(
var flOptC,flOptSame,flOptAsm: Boolean);
{ }
procedure InitLexGrid;
{ }
procedure MakeTree(nodeTree: TTreeNode;
symbSynt: TSymbol);
{ }
procedure ErrInfo(const sErrF,sErr: string;
iPos,iLen: integer);
{ }
function CompRun(const sInF,sOutF,sErrF: string;
var symbRes: TSymbol; flTrd,flDelC,flDelSame,flOptC,
flOptSame,flOptAsm: Boolean): TErrType;
end;
var CursovForm: TCursovForm;
implementation
{$R *.DFM}
uses FncTree,LexType,LexAuto,TrdType,TrdMake,TrdAsm,TrdOpt;
procedure TCursovForm.InitLexGrid;
{ }
begin
with GridLex do
begin
RowCount:= 2; Cells[0,0]:= /';
Cells[1,0]:= ''; Cells[2,0]:= '';
Cells[0,1]:= ; Cells[1,1]:= ; Cells[2,1]:= ;
end;
end;
procedure TCursovForm.StartInfo(
const sErrF: string{ });
{ }
var i,iCnt: integer;{ }
sT: string;{ }
begin
240

. . . .

sErrFile:= sErrF; { }
{ }
ErrInfo(sErrFile,
Format( %s ,[DateTimeToStr(Now)]),0,0);
iCnt:= ParamCount; { }
sT:= ParamStr(0); { }
{ }
for i:=1 to iCnt do sT:= sT + + ParamStr(i);
{ }
ErrInfo(sErrFile,sT,0,0);
end;
procedure TCursovForm.ProcessParams(
var flOptC,flOptSame,flOptAsm: Boolean{});
{ }
var i,iCnt,iLen: integer; { }
sTmp: string; { }
{ }
listErr: TStringList;
begin { }
flOptC:= True; flOptSame:= True;
flOptAsm:= True;
{ }
listErr:= TStringList.Create;
try { }
iCnt:= ParamCount;
for i:=2 to iCnt do
begin { }
sTmp:= ParamStr(i); { }
iLen:= Length(sTmp); { }
{
- }
if (iLen < 3) or (sTmp[1] <> ) then
{ }
listErr.Add(Format(' %d: %s!
[i,sTmp]))
else {
( ) }
case sTmp[2] of
{ }
'a','A': flOptAsm:= (sTmp[3] = 1 );
{ }
'c','C': flOptC:= (sTmp[3] = 1 );
{ }
's','S': flOptSame:= (sTmp[3] = 1 );
{ }
'o','O': sOutFile:= System.Copy(sTmp,3,iLen-2);
{ }
'e','E': StartInfo(System.Copy(sTmp,3,iLen-2));
else { }
241

. . . .

{ }
listErr.Add(Format(' %d: %s!
[i,sTmp]));
end{case};
end{for};
{ ,
}
if sOutFile = then
sOutFile:= ChangeFileExt(sInpFile, asm');
if sErrFile = then
StartInfo(ChangeFileExt(sInpFile, err'));
iCnt:= listErr.Count-1; { }
{ }
for i:=0 to iCnt do ErrInfo(sErrFile,listErr[i],0,0)
finally listErr.Free; { }
end{try};
end;
procedure TCursovForm.FormCreate(Sender: TObject);
var flOptC,flOptSame,flOptAsm: Boolean;
symbRes: TSymbol;
iErr: TErrType;
begin
symbRes:= nil; sOutFile:= ; sErrFile:= ;
{ ,
, }
InitTreeVar;
listLex:= TLexList.Create;
symbStack:= TSymbStack.Create;
listTriad:= TTriadList.Create;
{ ,
}
if ParamCount > 0 then
begin { }
sInpFile:= ParamStr(1);
{ }
ProcessParams(flOptC,flOptSame,flOptAsm);
iErr:= CompRun({ }
sInpFile,sOutFile,sErrFile{ },
symbRes{ },
False{ },
flOptC{ "C"},
flOptSame{ SAME},
flOptC{ },
flOptSame{ },
flOptAsm{ });
{ , }
if iErr <> ERR_FILE then Self.Close;
end;
end;
242

. . . .

procedure TCursovForm.FormClose(Sender: TObject;


var Action: TCloseAction);
{ ,
, }
begin
listTriad.Free; symbStack.Free;
listLex.Free; ClearTreeVar;
Application.Terminate;
end;
procedure TCursovForm.EditFileChange(Sender: TObject);
begin { , }
BtnLoad.Enabled:= (EditFile.Text <> );
end;
procedure TCursovForm.BtnFileClick(Sender: TObject);
begin { }
if FileOpenDlg.Execute then
begin
EditFile.Text:= FileOpenDlg.FileName;
BtnLoad.Enabled:= (EditFile.Text <> );
end;
end;
procedure TCursovForm.ErrInfo(const sErrF,sErr: string;
iPos,iLen: integer);
{ }
var fileErr: TextFile; { }
begin { }
if sErrF <> then
try { }
AssignFile(fileErr,sErrF);
if FileExists(sErrF) then Append(fileErr)
else Rewrite(fileErr);
writeln(fileErr,sErr);
CloseFile(fileErr); { }
except { , }
MessageDlg(Format(' %s! #13#10
+ ' : %s![sErrF,sErr]),
mtError,[mbOk],0);
end { , }
else { }
begin { }
ListIdents.SelStart:= iPos;
ListIdents.SelLength:= iLen;
MessageDlg(sErr,mtWarning,[mbOk],0);{ }
ListIdents.SetFocus; { }
end;
end;
function TCursovForm.CompRun({ }
const sInF,{ }
sOutF,{ }
243

. . . .

sErrF{ }:string;
var symbRes: TSymbol;{ }
flTrd,{ }
flDelC,{ "C"}
flDelSame,{ SAME}
flOptC,{ }
flOptSame,{ }
flOptAsm{ }
: Boolean): TErrType;
var i,iCnt,iErr: integer; { }
lexTmp: TLexem; { . }
sVars,sAdd: string; { }
asmList: TStringList; { }
begin{ , }
listLex.Clear; symbStack.Clear; listTriad.Clear;
try { }
ListIdents.Lines.LoadFromFile(sInF);
except { }
Result:= ERR_FILE;
MessageDlg(' !mtError,[mbOk],0);
Exit; { }
end; { }
iErr:= MakeLexList(ListIdents.Lines,listLex);
if iErr<>0 then { }
begin { }
ErrInfo(sErrF,
Format(' %s %d!
[listLex[0].LexInfoStr,iErr]),
listLex[0].PosAll,listLex[0].PosNum);
Result:= ERR_LEX; { }
end
else { }
begin { }
with ListIdents do
listLex.Add(TLexem.CreateInfo(' ',
Length(Text), Lines.Count-1,0));
{
}
symbRes:= BuildSyntList(listLex,symbStack);
{ ,
, , }
if symbRes.SymbType = SYMB_LEX then
begin { }
ErrInfo(sErrF,
Format(' %d . %d!
[symbRes.Lexem.StrNum+1,symbRes.Lexem.PosNum]),
symbRes.Lexem.PosAll,0);
symbRes.Free; { }
symbRes:= nil;
244

. . . .

Result:= ERR_SYNT; { }
end
else {
}
begin { }
lexTmp:= MakeTriadList(symbRes,listTriad);
{ , ,
}
if lexTmp <> nil then
begin { }
ErrInfo(sErrF,
Format(' %d . %d!
[lexTmp.StrNum+1,lexTmp.PosNum]),
lexTmp.PosAll,0);
Result:= ERR_TRIAD; { }
end
else { , , }
begin
Result:= ERR_NO; { }
{ , }
if flTrd then
listTriad.WriteToList(ListTriadAll.Lines);
if flOptC then { , }
begin { }
OptimizeConst(listTriad);
{ , C }
if flDelC then
DelTriadTypes(listTriad,TRD_CONST);
end; { ,}
if flTrd then { }
listTriad.WriteToList(ListTriadConst.Lines);
if flOptSame then { ,
begin{ }
OptimizeSame(listTriad);
{ , SAME }
if flDelSame then
DelTriadTypes(listTriad,TRD_SAME);
end; { ,}
if flTrd then { }
listTriad.WriteToList(ListTriadSame.Lines);
{ }
iCnt:= MakeRegisters(listTriad);
{ }
asmList:= TStringList.Create;
try
with asmList do
begin
Clear; { }
{ }
245

. . . .

Add(Format('program %s;,[NAME_PROG]));
{ }
sVars:= IdentList(, ,NAME_INPVAR,NAME_FUNCT);
if sVars <> then
begin{ ,}
Add( ); { }
Add('var'); { }
Add(Format(%s: %s;,[sVars,NAME_TYPE]));
end;
Add( );
{ }
Add(Format('function %0:s(%1:s: %2:s): %2:s;
+ stdcall;,
[NAME_FUNCT,NAME_INPVAR,NAME_TYPE]));
if iCnt > 0 then { }
begin { }
Add('var'); { ,}
sVars:= ; { .}
for i:=0 to iCnt do
begin
sAdd:= Format(%s%d',[TEMP_VARNAME,i]);
if sVars = then sVars:= sAdd
else sVars:= sVars +, + sAdd;
end;
Add(Format(%s: %s;,[sVars,NAME_TYPE]));
end;
Add('begin'); { }
Add(asm'); { , }
Add(#9'pushad'#9#9 { ,});
MakeAsmCode(listTriad,asmList,flOptAsm);
Add(#9'popad'#9#9 { ,});
Add(end;);
Add('end;);
Add( ); { }
Add(Format('var %s: %s;,
[NAME_INPVAR,NAME_TYPE]));
Add( );
Add('begin'); { }
Add(Format(readln(%s);,[NAME_INPVAR]));
Add(Format(writeln(%s(%s));,
[NAME_FUNCT,NAME_INPVAR]));
Add(readln;);
Add('end.);
end{with}; { , }
if flTrd then { }
ListAsm.Lines.AddStrings(asmList);
if sOutF <> then { . ,}
try { }
asmList.SaveToFile(sOutF);
246

. . . .

except Result:= ERR_FILE;


end;
finally asmList.Free; { }
end{try}; { }
end;
end;
end;
end;
procedure TCursovForm.BtnLoadClick(Sender: TObject);
{ }
var i,iCnt: integer; { }
iRes: TErrType; { }
symbRes: TSymbol; { }
nodeTree: TTreeNode; { }
begin
symbRes:= nil; { }
InitLexGrid; { }
TreeSynt.Items.Clear; { }
iRes:= CompRun({ }
EditFile.Text, , ,{ }
symbRes{ },
True{ },
CheckDel_C.Checked { "C"},
CheckDelSame.Checked { SAME},
True { },
True { },
CheckAsm.Checked { });
if iRes > ERR_LEX then { ,}
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;
end;
if (iRes > ERR_SYNT) and (symbRes <> nil) then
{ ,}
begin { }
{ }
nodeTree:= TreeSynt.Items.Add(nil,symbRes.SymbolStr);
MakeTree(nodeTree,symbRes); { }
nodeTree.Expand(True); { }
247

. . . .

{ }
TreeSynt.Selected:= nodeTree;
end;
if iRes > ERR_TRIAD then { }
begin { , }
MessageDlg(' !
mtInformation,[mbOk],0);
PageControl1.ActivePageIndex:= 4;
end;
end;
procedure TCursovForm.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 TCursovForm.BtnExitClick(Sender: TObject);
{ }
begin
Self.Close;
end;
end.


, - , FormLab4.dfm CURSOV.

248

. . . .

4


1.
4.1.
prog
if ((InpVar > 31) or InpVar<0) CompileTest:= 0
else
if (InpVar=0) CompileTest:= 1
else
begin
i:= InpVar;
Fact:= 1;
while (i<>-1) do
begin
j:= I-1;
Sum:= Fact;
while (not (j=0)) do
begin
Sum:= Sum + Fact;
j:= j-(-1);
end;
Fact:= Sum;
i:= i 1;
end;
CompileTest:= Fact;
end;
end.

4.2.
program MyCurs;
var
Fact,i,j,Sum: integer;
function CompileTest(InpVar: integer): integer; stdcall;
begin
asm
pushad { }
mov eax,InpVar
cmp eax,31 { 1: > (InpVar, 31) }
setg al
249

. . . .

and eax,1
mov ebx,eax
mov eax,InpVar
cmp eax,0 { 2: < (InpVar, 0) }
setl al
and eax,1
or eax,ebx { 3: or (^1, ^2) }
jnz @F3 { 4: if (^3, ^7) }
jmp @M7
@F3:
xor eax,eax
mov Result,eax { 5::= (CompileTest, 0) }
jmp @M31 { 6: jmp (1, ^31) }
@M7:
mov eax,InpVar
cmp eax,0 { 7: = (InpVar, 0) }
sete al
and eax,1
jnz @F7 { 8: if (^7, ^11) }
jmp @M11
@F7:
xor eax,eax
inc eax
mov Result,eax { 9::= (CompileTest, 1) }
jmp @M31 { 10: jmp (1, ^31) }
@M11:
mov eax,InpVar
mov i,eax { 11::= (i, InpVar) }
xor eax,eax
inc eax
mov Fact,eax { 12::= (Fact, 1) }
@M13:
mov eax,i
cmp eax,1 { 13: <> (i, 1) }
setne al
and eax,1
jnz @F13 { 14: if (^13, ^30) }
jmp @M30
@F13:
mov eax,i
dec eax { 15: (i, 1) }
mov j,eax { 16::= (j, ^15) }
mov eax,Fact
mov Sum,eax { 17::= (Sum, Fact) }
@M18:
mov eax,j
cmp eax,0 { 18: = (j, 0) }
sete al
and eax,1
250

. . . .

not eax { 19: not (^18, 0) }


and eax,1
jnz @F19 { 20: if (^19, ^26) }
jmp @M26
@F19:
mov eax,Sum
add eax,Fact { 21: + (Sum, Fact) }
mov Sum,eax { 22::= (Sum, ^21) }
mov eax,j
dec eax { 23: (j, 1) }
mov j,eax { 24::= (j, ^23) }
jmp @M18 { 25: jmp (1, ^18) }
@M26:
mov eax,Sum
mov Fact,eax { 26::= (Fact, Sum) }
mov eax,i
dec eax { 27: (i, 1) }
mov i,eax { 28::= (i, ^27) }
jmp @M13 { 29: jmp (1, ^13) }
@M30:
mov eax,Fact
mov Result,eax { 30::= (CompileTest, Fact) }
@M31:
nop { 31: nop (0, 0) }
popad { }
end;
end;
var InpVar: integer;
begin
readln(InpVar);
writeln(CompileTest(InpVar));
readln;
end.

251

. . . .

2.
4.3.
prog
D:= 0;
B:= 1;
C:= 1;
A:= C + InpVar;
D:= C+B+234;
C:= A + B + C;
D:= ((C) +(A+B)) (InpVar + 1) + (A+B);
E:= (D 22) (A + B);
CompileTest:= 0;
if (a<b or a<c xor(e=0 xor(d=0
and (b<c or (a<c and (c<>e or not(b=0)))))))
a:=0 else a:=1;
if (InpVar > 0 or -1 <> InpVar)
while (a<1) do a:=a+(b+1)
else CompileTest:= InpVar+1;
end.

4.4.
program MyCurs;
var
A,B,C,D,E: integer;
function CompileTest(InpVar: integer): integer; stdcall;
var
_Tmp0,_Tmp1: integer;
begin
asm
pushad { }
mov eax,0
mov D,eax { 1::= (D, 0) }
mov eax,1
mov B,eax { 2::= (B, 1) }
mov C,eax { 3::= (C, 1) }
add eax,InpVar { 4: + (C, InpVar) }
mov A,eax { 5::= (A, ^4) }
mov eax,C
add eax,B { 6: + (C, B) }
add eax,234 { 7: + (^6, 234) }
mov D,eax { 8::= (D, ^7) }
mov eax,A
add eax,B { 9: + (A, B) }
252

. . . .

add eax,C { 10: + (^9, C) }


mov C,eax { 11::= (C, ^10) }
mov eax,A
add eax,B { 12: + (A, B) }
add eax,C { 13: + (C, ^12) }
mov ebx,eax
mov eax,InpVar
add eax,1 { 14: + (InpVar, 1) }
sub eax,ebx { 15: (^13, ^14) }
neg eax
mov ebx,eax
mov eax,A
add eax,B { 16: + (A, B) }
add eax,ebx { 17: + (^15, ^16) }
mov D,eax { 18::= (D, ^17) }
sub eax,22 { 19: (D, 22) }
mov ebx,eax
mov eax,A
add eax,B { 20: + (A, B) }
sub eax,ebx { 21: (^19, ^20) }
neg eax
mov E,eax { 22::= (E, ^21) }
mov eax,0
mov Result,eax { 23::= (CompileTest, 0) }
mov eax,A
cmp eax,B { 24: < (A, B) }
setl al
and eax,1
mov ebx,eax
mov eax,A
cmp eax,C { 25: < (A, C) }
setl al
and eax,1
or eax,ebx { 26: or (^24, ^25) }
mov ebx,eax
mov eax,E
cmp eax,0 { 27: = (E, 0) }
sete al
and eax,1
mov ecx,eax
mov eax,D
cmp eax,0 { 28: = (D, 0) }
sete al
and eax,1
mov edx,eax
mov eax,B
cmp eax,C { 29: < (B, C) }
setl al
and eax,1
253

. . . .

mov esi,eax
mov eax,A
cmp eax,C { 30: < (A, C) }
setl al
and eax,1
mov edi,eax
mov eax,C
cmp eax,E { 31: <> (C, E) }
setne al
and eax,1
mov _Tmp0,eax
mov eax,B
cmp eax,0 { 32: = (B, 0) }
sete al
and eax,1
not eax { 33: not (^32, 0) }
and eax,1
or eax,_Tmp0 { 34: or (^31, ^33) }
and eax,edi { 35: and (^30, ^34) }
or eax,esi { 36: or (^29, ^35) }
and eax,edx { 37: and (^28, ^36) }
xor eax,ecx { 38: xor (^27, ^37) }
xor eax,ebx { 39: xor (^26, ^38) }
jnz @F39 { 40: if (^39, ^43) }
jmp @M43
@F39:
mov eax,0
mov A,eax { 41::= (A, 0) }
jmp @M44 { 42: jmp (1, ^44) }
@M43:
mov eax,1
mov A,eax { 43::= (A, 1) }
@M44:
mov eax,InpVar
cmp eax,0 { 44: > (InpVar, 0) }
setg al
and eax,1
mov ebx,eax
mov eax,1
neg eax { 45: (0, 1) }
cmp eax,InpVar { 46: <> (^45, InpVar) }
setne al
and eax,1
or eax,ebx { 47: or (^44, ^46) }
jnz @F47 { 48: if (^47, ^56) }
jmp @M56
@F47:
@M49:
mov eax,A
254

. . . .

cmp eax,1 { 49: < (A, 1) }


setl al
and eax,1
jnz @F49 { 50: if (^49, ^55) }
jmp @M55
@F49:
mov eax,B
add eax,1 { 51: + (B, 1) }
add eax,A { 52: + (A, ^51) }
mov A,eax { 53::= (A, ^52) }
jmp @M49 { 54: jmp (1, ^49) }
@M55:
jmp @M58 { 55: jmp (1, ^58) }
@M56:
mov eax,InpVar
add eax,1 { 56: + (InpVar, 1) }
mov Result,eax { 57::= (CompileTest, ^56) }
@M58:
nop { 58: nop (0, 0) }
popad { }
end;
end;
var InpVar: integer;
begin
readln(InpVar);
writeln(CompileTest(InpVar));
readln;
end.

4.5.
program MyCurs;
var
A,B,C,D,E: integer;
function CompileTest(InpVar: integer): integer; stdcall;
begin
asm
pushad { }
xor eax,eax
mov D,eax { 1::= (D, 0) }
inc eax
mov B,eax { 2::= (B, 1) }
mov C,eax { 3::= (C, 1) }
add eax,InpVar { 4: + (C, InpVar) }
mov A,eax { 5::= (A, ^4) }
mov eax,236
mov D,eax { 6::= (D, 236) }
mov eax,A
add eax,B { 7: + (A, B) }
255

. . . .

mov ebx,eax
add eax,C { 8: + (^7, C) }
mov C,eax { 9::= (C, ^8) }
add eax,ebx { 10: + (C, ^7) }
mov ecx,eax
mov eax,InpVar
inc eax { 11: + (InpVar, 1) }
sub eax,ecx { 12: (^10, ^11) }
neg eax
add eax,ebx { 13: + (^12, ^7) }
mov D,eax { 14::= (D, ^13) }
mov eax,214
sub eax,ebx { 15: (214, ^7) }
mov E,eax { 16::= (E, ^15) }
xor eax,eax
mov Result,eax { 17::= (CompileTest, 0) }
mov eax,A
cmp eax,B { 18: < (A, B) }
setl al
and eax,1
mov ebx,eax
mov eax,A
cmp eax,C { 19: < (A, C) }
setl al
and eax,1
mov edx,eax
or eax,ebx { 20: or (^18, ^19) }
mov ebx,eax
mov eax,E
cmp eax,0 { 21: = (E, 0) }
sete al
and eax,1
mov ecx,eax
mov eax,C
cmp eax,E { 22: <> (C, E) }
setne al
and eax,1
xor eax,eax
inc eax { 23: or (^22, 1) }
and eax,edx { 24: and (^19, ^23) }
{ 25: or (0, ^24) }
xor eax,eax { 26: and (0, ^25) }
xor eax,ecx { 27: xor (^21, ^26) }
xor eax,ebx { 28: xor (^20, ^27) }
jnz @F28 { 29: if (^28, ^32) }
jmp @M32
@F28:
xor eax,eax
mov A,eax { 30::= (A, 0) }
256

. . . .

jmp @M33 { 31: jmp (1, ^33) }


@M32:
xor eax,eax
inc eax
mov A,eax { 32::= (A, 1) }
@M33:
mov eax,InpVar
cmp eax,0 { 33: > (InpVar, 0) }
setg al
and eax,1
mov ebx,eax
xor eax,eax
dec eax
cmp eax,InpVar { 34: <> (-1, InpVar) }
setne al
and eax,1
or eax,ebx { 35: or (^33, ^34) }
jnz @F35 { 36: if (^35, ^44) }
jmp @M44
@F35:
@M37:
mov eax,A
cmp eax,1 { 37: < (A, 1) }
setl al
and eax,1
jnz @F37 { 38: if (^37, ^43) }
jmp @M43
@F37:
mov eax,B
inc eax { 39: + (B, 1) }
add eax,A { 40: + (A, ^39) }
mov A,eax { 41::= (A, ^40) }
jmp @M37 { 42: jmp (1, ^37) }
@M43:
jmp @M46 { 43: jmp (1, ^46) }
@M44:
mov eax,InpVar
inc eax { 44: + (InpVar, 1) }
mov Result,eax { 45::= (CompileTest, ^44) }
@M46:
nop { 46: nop (0, 0) }
popad { }
end;
end;
var InpVar: integer;
begin
readln(InpVar);
writeln(CompileTest(InpVar));
readln;
257

. . . .

end.

258

. . . .


1. ., . , . .:
, 1978. . 1, 612 . . 2, 487 .
2. ., ., . : , :
. . .: , 2003. 768 .
3. . ., . . . .: ,
2002. 734 .
4. . ., . ., . . .
: . . .: , 2000. 256 .
5. . . : . 2- . .: ,
2004. 416 .
6. . ., . . . .: , 2002.
544 .
7. . . : . .:
, 2003. 396 .

259

. . . .


8. . . . . .: , 1998. 109 .
9. . . . (HELP) Delphi 5 Object Pascal. .:
, 2000. 32 .
10. . . : . . :
, 1997. 84 .
11. . . : , , . .: , 2001.
304 .
12. . . . .: -, 1999. 342 .
13. . ., . . C C++. .: -, 1996.
288 .
14. . UNIX. .: , 1986. 463 .
15. . ., . ., . . . . .: , 1990. 31 .
16. . ., . .
. .: , 1991. 78 .
17. . ., . . .
. .: -, 1999. 62 .
18. . .
.: , 1975. 544 .
19. . . : . . : , 1999.
80 .
20. . UNIX System V. Release 4.2. . .: -,
1995. 287 .
21. . ., . . : . : - , 1999. 48 .
22. . ., . ., . . . .: , 1993. 26 .
23. . Delphi 4. . : , 1998.
24. . . Delphi: . .: , 2001 684 .
25. . ., . . C++: . .: , 2002.
480 .
26. . . : . .: , 2003. 208 .
27. ., . UNIX . .:
, 1992. 420 .
28. . Delphi 5 . .: , 2001.
29. . . . .: , 1979.
483 .
30. . . - . .: -
, 1995. 174 .
31. ., . Turbo Pascal. .: , 2000.
32. . . C/C++: . .: , 2001.
33. . . : . : -
, 1998. . 2. 51 .
34. ., . : . .:
, 2001.
260

. . . .

35. ., . UNIX Linux: . .: , 1999. 297 .


36. ., - . UNIX: . .: , 2000. 384 .
37. . ., . . Pascal: . . .: :
, 2000. 205 .
38. . . . .: , 1997.
171 .
39. . ++. .: , 1991. 348 .
40. . . : . . : ,
1995. 105 .
41. . . . .: , 1999. 288 .
42. . . : . .
.: , 1996. 65 .
43. . .
UNIX . .: - , 1999. 191 .
44. . Assembler: . . .: , 2000. 622 .

261