-
Notifications
You must be signed in to change notification settings - Fork 88
/
gz.l
208 lines (200 loc) · 3.71 KB
/
gz.l
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
// example to scan (un)compressed C/C++ files using zlib and std:istream
// streams do not support UTF-16/32 normalization to UTF-8 though!!
//
// usage:
// $ gzip somefile.c
// $ ./gz somefile.c.gz
%top{
#include <cstdio>
#include <streambuf>
#include <cstring>
#include <zlib.h>
#ifndef Z_BUF_LEN
#define Z_BUF_LEN (65536)
#endif
%}
%include "cdefs.l"
%option nodefault
%option fast
%%
{WHITESPACE}
{ILCOMMENT}
{MLCOMMENT}
{DIRECTIVE} out() << "DIRECTIVE " << str() << std::endl;
{NAME} out() << "NAME " << str() << std::endl;
{UFLT} out() << "FLOAT " << str() << std::endl;
{UINT} out() << "INT " << str() << std::endl;
{CHAR} out() << "CHAR " << str() << std::endl;
{STRING} out() << "STRING " << str() << std::endl;
"{"|"<%" |
"}"|"%>" |
"["|"<:" |
"]"|":>" |
"(" |
")" |
"+=" |
"++" |
"+" |
"-=" |
"--" |
"->*" |
"->" |
"-" |
"==" |
"=" |
"<=" |
"<<=" |
"<<" |
"<" |
">=" |
">>=" |
">>" |
">" |
"!=" |
"!" |
"," |
";" |
"..." |
".*" |
"." |
"^=" |
"^" |
"~" |
"*=" |
"*" |
"/=" |
"/" |
"%=" |
"%" |
"&=" |
"&&" |
"&" |
"|=" |
"||" |
"|" |
"::" |
":" |
"?" out() << "PUNCT " << str() << std::endl;
. out() << "*** ERROR at line " << lineno() << std::endl;
%%
// a std::streambuf class to produce a decompressed stream from a compressed
// file or uncompressed file, using Zlib's gzdopen, gzread, gzclose
class zstreambuf : public std::streambuf {
public:
zstreambuf(FILE *file)
:
cur_(),
len_()
{
int fd = dup(fileno(file));
if (fd >= 0 && (gzfile_ = gzdopen(fd, "r")) != Z_NULL)
gzbuffer(gzfile_, Z_BUF_LEN);
else if (fd >= 0)
close(fd);
}
virtual ~zstreambuf()
{
if (gzfile_ != Z_NULL)
gzclose_r(gzfile_);
}
protected:
int_type underflow()
{
return cur_ < len_ ? buf_[cur_] : peek();
}
int_type uflow()
{
return cur_ < len_ ? buf_[cur_++] : read();
}
std::streamsize showmanyc()
{
return gzfile_ == Z_NULL ? -1 : 0;
}
std::streamsize xsgetn(char *s, std::streamsize n)
{
if (gzfile_ == Z_NULL)
return 0;
std::streamsize k = n;
while (k > 0)
{
if (cur_ >= len_)
if (peek() == traits_type::eof())
return n - k;
if (k <= len_ - cur_)
{
memcpy(s, buf_ + cur_, k);
cur_ += k;
return n;
}
memcpy(s, buf_ + cur_, len_ - cur_);
s += len_ - cur_;
k -= len_ - cur_;
cur_ = len_;
}
return n;
}
int_type peek()
{
if (gzfile_ == Z_NULL)
return traits_type::eof();
cur_ = 0;
len_ = gzread(gzfile_, buf_, Z_BUF_LEN);
if (len_ <= 0)
{
finish();
return traits_type::eof();
}
return traits_type::to_int_type(buf_[cur_]);
}
int_type read()
{
if (gzfile_ == Z_NULL)
return traits_type::eof();
cur_ = 0;
len_ = gzread(gzfile_, buf_, Z_BUF_LEN);
if (len_ <= 0)
{
finish();
return traits_type::eof();
}
return traits_type::to_int_type(buf_[cur_++]);
}
void finish()
{
if (!gzeof(gzfile_))
{
int err;
gzerror(gzfile_, &err);
if (err == Z_ERRNO)
perror("zlib error");
else
fprintf(stderr, "zlib decompression error\n");
}
gzclose_r(gzfile_);
gzfile_ = Z_NULL;
len_ = 0;
}
gzFile gzfile_;
unsigned char buf_[Z_BUF_LEN];
std::streamsize cur_;
std::streamsize len_;
};
int main(int argc, char **argv)
{
FILE *file = stdin;
if (argc > 1)
{
file = fopen(argv[1], "rb");
if (!file)
{
perror("Cannot open file for reading\n");
exit(EXIT_FAILURE);
}
}
zstreambuf streambuf(file);
std::istream stream(&streambuf);
Lexer lexer(&stream);
lexer.lex();
if (file != stdin)
fclose(file);
}