自己动手用java写编译器 课时5 输入系统代码实现

缘起

《自己动手用java写编译器》 课时5 实现上一节讲解的输入系统原理的代码

分析

其实我挺怀疑视频讲师的是不是写java出身的——不能写出这么丑的java代码呀(手动笑哭),简直和培训班初级阶段的学生写的代码没什么区别~

我用C++实现(虽然鄙人只是一个java码农). 我觉得完全可以理解了课时4中讲解的思想之后实现出来.而不需要狂啃他的代码.

其实整个缓冲区可以理解为在stdin或者文件流的基础上做了一层封装. 一开始缓冲区的状态是(和【1】不同,我们这里没有所谓的endBuf, 即缓冲区的逻辑结束地址,也就是没有【1】中说的隔离带)

则第一次调用getWord方法的时候,因为next>DANGER, 所以第一次调用getWord就会触发flush操作. 后面调用getWord,则一旦触发了flush操作之后(next>DANGER), 就会平移[pMark, END)到整个缓冲区的头部并且再次从底层输入流读入字符填满整个缓冲区(到END为止或者底层输入流耗尽)

项目结构如下(用的vs2010)

5份文件,作用如下

  1. inputsystem.cpp 纯一个调用测试用的.
  2. Buffer.h 是我们的缓冲区
  3. SourceHandler.h 是底层输入流的处理器接口
  4. FileHandler.h 是底层输入流为文件的接口实现类
  5. StdHandler.h 是底层输入流为标准输入流的接口实现类

类图比较简单,UML就不画了.

贴代码如下

inputsystem.cpp

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include "stdafx.h"
#include "Buffer.h"
#include <iostream>
/************************************************************************/
/* 输入系统 */
/************************************************************************/

int main()
{
Buffer buffer;
//buffer.setStd(); // 设置从控制台标准流读取数据
buffer.setFile(); // 设置从文件读取数据
string word;
while((word = buffer.getWord())!="")
{
cout << "当前读取的单词: " << word << endl; // 打印当前单词
cout << "上一个单词: " << buffer.getPreviousWord() << endl; // 读取并打印上一个单词
}
return 0;
}

Buffer.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
/************************************************************************/
/* 缓冲区 */
/************************************************************************/
#include "SourceHandler.h"
#include <iostream>
#include <string>
#include "StdHandler.h"
#include "FileHandler.h"

using namespace std;

class Buffer
{
public:
Buffer():pMark(END),sMark(END),eMark(END),lineno(1),next(END),pLength(0), length(0){} // 注意, 这里首先将pMark、sMark、eMark、next都指向END, 这样就会在第一次getWord的时候就触发flush

~Buffer(){};

string getWord() // 读取一个单词
{
pMark = sMark;
pLength = eMark - sMark; // 现在的变从前了.
if (next > DANGER) // 看看此时准备读取的时候,需不需要flush
{
flush();
}
while(buf[next]==' '|| buf[next]=='\t' || buf[next] == '\n') // 如果是空格、tab、换行符,则就要不断的往后读取
{
if (buf[next] == '\n') // 碰到换行符, 则行数+1
{
lineno++;
}
next++;
}
sMark = next; // 开始读取
while(next<END && buf[next] && buf[next]!=' '&&buf[next]!='\t'&&buf[next]!='\n')next++; // 不能到达缓冲区的末尾, 也不能为\0, 也不能是空白字符
eMark = next; // 则 [sMark, eMark) 就是当前读取的单词
return string(buf+sMark, eMark-sMark); // 返回当前读取的字符串
}

string getPreviousWord() // 读取上一个单词
{
return string(buf + pMark, pLength);
}

void setStd() // 设置为Std读取
{
handler = (SourceHandler *)new StdHandler();
}

void setFile() // 设置为从文件读取
{
handler = (SourceHandler *)new FileHandler();
}

private:

bool flush() // 将缓冲区的 [pMark, END)位置的字符全部复制移动到缓冲区的头部, 并且将后续END-pMark位置开始继续从源中读取字符
{
memcpy(tmpBuf, buf + pMark, END-pMark); // 将buf[pMark,END)拷贝到tmpBuf的头部
int numOfCopy = END-pMark; // 拷贝过去的字符数量
memcpy(buf, tmpBuf, END-pMark); // 通过tmpBuf的中转
pMark = 0;
sMark = pLength;
eMark = sMark + length;
next = eMark;
return handler->fillBuf(buf, numOfCopy, END-eMark); // 填满buf的剩余空间(结果只有2个, 要么填满了, 要么输入源耗尽, 即EOF)
}

static const int MAXLOOK = 16; // lookAhead最多往后16个字符.
static const int MAXLEX = 1024; // 分词之后最多每个分词是1024个字符
static const int BUFFSIZE = (MAXLEX * 3 ) + (2 * MAXLOOK); // 缓冲区大小
static const int END = BUFFSIZE; // 缓冲区的结束位置
static const int DANGER = END - MAXLOOK; // 危险区域(超出即要执行flush操作)

int pMark; //上一次读取单词的起始位置
int sMark; // 当前读取的单词的起始位置
int eMark; // 当前读取的单词的结束位置+1
int pLength; // 上一个单词的长度
int length; // 当前单词的长度
int lineno; // 行号
int next; // 从next开始读取字符

SourceHandler *handler; // 源处理器
char buf[BUFFSIZE]; // 缓冲区
char tmpBuf[BUFFSIZE]; // 临时数组, 用于临时存储需要搬运的字符,注意, 不可以直接从buf搬运到buf, 会有问题,这个在java的System.arrayCopy中讲过了. 注意, 这个不要放进
};

SourceHandler.h

1
2
3
4
5
6
7
8
9
10
11
12
13
/************************************************************************/
/* 源处理器接口 */
/************************************************************************/

class SourceHandler
{
public:
SourceHandler() {};

virtual ~SourceHandler(){} // 对析构函数进行动态绑定

virtual bool fillBuf(char *buf, int startPos, int len) {return false;}; // 往buf[startPos..]开始填充len个字符,len对于buf的合法性由调用方保证
};

StdHandler.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/************************************************************************/
/* 控制台标准输入源处理器 */
/************************************************************************/
#include <stdio.h>

class StdHandler:SourceHandler
{
public:
bool fillBuf(char *buf, int startPos, int len) // len对于buf的合法性由调用方保证
{
char c;
while(len-- && ~scanf("%c", &c)) // 只要还有字符并且还没读取到len个字符, 就要继续读取
{
buf[startPos++] = c;
}
if (len) buf[startPos] = 0; // 如果没读取完len的话, 则以\0为休止符填充
return !len; // 如果len为0, 表示满足了要求, 如果不为0, 表示已经到了底层输入流的末尾
}
};

FileHandler.h

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
/************************************************************************/
/* 文件源处理器 */
/************************************************************************/
#include <iostream>
#include <fstream>
using namespace std;

class FileHandler:SourceHandler
{
public:
FileHandler()
{
fin.open("d:/data.in"); // 只读方式打开文件d:\data.in
}
~FileHandler()
{
fin.close();
}
bool fillBuf(char *buf, int startPos, int len) // len对于buf的合法性由调用方保证
{
while(len--)
{
fin.read(buffer, 1);
if (!fin.gcount()) // 如果没有数据读入的话
{
break;
}
buf[startPos++] = buffer[0];
}
if (len) buf[startPos] = 0;
return !len; // 如果len个字符都读取完毕, 则len=0, 从而返回true
}

private:
ifstream fin;
char buffer[1]; // 用于接收从文件中读取的字符
};

测试数据见附件【1】

参考

【1】https://yfsyfs.github.io/2019/07/21/%E8%87%AA%E5%B7%B1%E5%8A%A8%E6%89%8B%E7%94%A8java%E5%86%99%E7%BC%96%E8%AF%91%E5%99%A8-%E8%AF%BE%E6%97%B64-%E8%BE%93%E5%85%A5%E7%B3%BB%E7%BB%9F%E5%8F%8A%E5%88%86%E8%AF%8D%E7%B3%BB%E7%BB%9F%E6%A6%82%E8%BF%B0/

附件

data.in

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
ddk
u
ndoltrk
kxwcikvy
m
lb
tokg
atdxrxb
u
yhnkev
tfgine
m
z
qgsxw
pubfwjyht
jfnnic
hvjgf
kxvj
amlhmr
goa
vopugyin
vmrhrjddbz
cti
ur
xdezsa
ylhobvpbye
bgdklh
ylnrtmuil
mvh
f
vuzxocvlz
msynlyyau
wceooh
zixwx
yelkrjhm
ujkxrriyl
d
ockq
pzbz
vkaesz
abru
e
xwcjcfabu
fkxjkeo
y
l
l
hlzlquzsf
h
wrtasgba
jqxm
doikfioybu
eeiqko
pxwqj
yalofjq
elna
kwpnmybd
nd
hxczink
tbsfavja
czwdltpytq
buvzmlposi
pz
wpyacmtqy
lwwomuico
zncsurdb
vibzspyt
n
y
hzyhme
gbb
qczilpu
rd
cwpud
g
m
lelsw
govw
oimbhbgr
lzqvbrmfkc
mlusui
zw
ylvuz
ahlhytomom
p
ihaybvrui
x
fer
xshihfcpyh
fqfh
adxfltf
exmiesoww
ivellrgb
aye
vdun
pjabrbbd
yimnvogsfk
ndpfk
wgpuhui
zfzrxe
nacxktm
njx
ftb
thmtuyz
mhp
sm
hsjvuusxo
hjbjscq
jpjphpwg
kbturs
ecwzxw
ty
eeajrtw
jknurdu
abu
vygtlq
crtrtngk
jrvdnkfr
ycokxgho
wofjpngx
aozf
bsmxjkrjer
hocnu
o
kciiqiqprv
rvvcj
fnwyqxufs
m
nkm
igvcnvy
iu
qqbtj
gwrzyx
vvqsx
wllwl
kp
yqmrzugr
uinpkmdkdq
xmapzsu
satv
hak
xxcgedoyfi
uxfply
srvgfstre
dw
jvmnhrnqu
m
i
kcrxho
ircrwzxii
mtuiu
xj
maulufwd
zxoap
jdpfliiihl
mh
uunttdfr
tdkt
nvsszvwul
fugxofe
wp
ozqcat
y
b
aarxlg
vmybqkkw
ejhgr
q
jzc
wtcqga
gcvcipege
vbm
gxt
v
dhizacjipx
ef
lkxn
kqkloolt
oibkhf
w
t
yngxplhmv
rgwlpsx
gqllflxq
gyvlxonmo
qzwcmgjw
i
pihku
i
r
rdvyq
bzggfqpc
rwray
wkbgezjmu
jdktlfnhv
gv
mjnvi
unqhbsas
mzisrvxeu
jrpcxrp
dzxtncczei
zxxjztdi
miyyblbal
jhtoas
itknw
mwxpjhbe
czhzjqy
q
cxqiymtsu
orriltnrrb
mwgppxix
mise
crbwp
vlswqvjam
krplvccxn
jqy
l
jvrkjzq
qnjxginss
k
ttir
zhmymkizoh
slfpyravev
kyzocb
mruraa
aczdqfsyyg
vfivpwl
mrmcrqlz
avjyds
dfc
jhndvohmp
hp
spvpqpl
gzobhj
vd
tffuud
ajeimm
yfzrjvt
gprgxax
clgkuaqt
gbs
ihaiten
pdleicqqg
nexl
ubkvnydws
lcg
ygkb
o
c
r
knelyrfnxn
rpnwyagc
jbspihx
qlcsfdcz
fmyhrbcov
rx
ziuurf
qa
p
bamh
t
uzppifs
seisv
zbmwsquf
eknsjw
waqegqfv
ltvugti
yutryswqw
eiryfnbnjy
ntweqorcjy
psim
uixo
aolvgk
dqishhlp
bqohnab
n
btvsnuzb
a
xhc
qx
gdyeexhxfj
r
btxqou
invttvq
e
pdmwk
gqkrehh
khqdsqa
faxh
uyuiz
x
haqr
y
xhuk
bnivitw
trdimy
xvpzngvzsp
s
etfktv
paa
tbzpfyymtu
bm
yhtd
zm
wjsreqjxmy
qsyk
p
smlf
rnujhqdln
qalq
ypyq
qntbhzcg
qhnvaamnw
avvaavs
cunyfzbrex
ut
lnya
qyfy
tchtebg
opkuzj
gn
s
hvfed
ds
qyyil
wfjtxoy
tgdsoan
vgej
uxst
crxycyokf
m
lxbzo
wjejtg
tdj
gutyiulr
ydzar
nuteoon
koeaew
uyhiucm
ax
mryecq
aiafyeqj
gsygadxw
bc
a
qatgj
mon
ebzfv
jsm
czkgurvph
hzuenuuzda
fwlbemll
aqvr
vbpelv
uoqrjlp
mmlotamxza
nkoqacjakm
fizgs
cbd
elvkto
nmsnjmwx
zkor
tdrk
mfq
cjaxgqrtl
xk
vf
itybo
usps
bphmzy
ykjtkcd
vpwzldcfbf
beguvw
ccoc
fuucladke
pb
sfvvmws
yxyaz
vrdegc
xpxwxrqml
dyy
qtwwxy
tqof
hco
ewfhq
txg
jlkkisrcm
h
gqmthzurmx
gmgp
nk
urdujzv
fbbghevs
zl
fqzwhnst
vgjyxqw
dxnmha
dngvzr
upwzn
g
d
moizhuxnks
iljxczyl
xqklcthk
qmhza
qpu
yyawcjk
wwlxxr
b
vtrbp
immoslj
dsxvo
jgmimo
pbeafn
miw
kncjyxsykc
sgtvljcct
wslus
ghnjqlj
zpuqrcuteq
brn
eadc
dihqh
qtlog
rv
wwrl
enb
fkmqgk
iahrvaal
sgh
xpbnicc
vclp
jzybeq
fkdh
hffvc
qlvebqabea
huoqb
dbejk
u
mqkgcjb
ounqhe
neilyq
zrhkvce
hgdf
caclfqf
rupnqe
rsntt
kzu
doihen
huypztwel
elstvxdgn
fenlnje
cgnj
utulcwrmos
zrll
huatrxlmpo
tm
rmk
dmrjz
axqpcizk
ryc
qdtfnpvntb
nuwpesu
oou
h
hjoi
eqjvytsrdr
qsjco
cdy
cwjwkzxdmx
pjjqtask
sauparcnqz
i
kxbdrzwf
v
ttnuohfl
qbhfcsc