grep.y - 9base - revived minimalist port of Plan 9 userland to Unix | |
git clone git://git.suckless.org/9base | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
grep.y (2815B) | |
--- | |
1 %{ | |
2 #include "grep.h" | |
3 %} | |
4 | |
5 %union | |
6 { | |
7 int val; | |
8 char* str; | |
9 Re2 re; | |
10 } | |
11 | |
12 %type <re> expr prog | |
13 %type <re> expr0 expr1 expr2 expr3 expr4 | |
14 %token <str> LCLASS | |
15 %token <val> LCHAR | |
16 %token LLPAREN LRPAREN LALT LSTAR LPLUS LQUES | |
17 %token LBEGIN LEND LDOT LBAD LNEWLINE | |
18 %% | |
19 | |
20 prog: | |
21 expr newlines | |
22 { | |
23 $$.beg = ral(Tend); | |
24 $$.end = $$.beg; | |
25 $$ = re2cat(re2star(re2or(re2char(0x00, '\n'-1), re2char… | |
26 $$ = re2cat($1, $$); | |
27 $$ = re2cat(re2star(re2char(0x00, 0xff)), $$); | |
28 topre = $$; | |
29 } | |
30 | |
31 expr: | |
32 expr0 | |
33 | expr newlines expr0 | |
34 { | |
35 $$ = re2or($1, $3); | |
36 } | |
37 | |
38 expr0: | |
39 expr1 | |
40 | LSTAR { literal = 1; } expr1 | |
41 { | |
42 $$ = $3; | |
43 } | |
44 | |
45 expr1: | |
46 expr2 | |
47 | expr1 LALT expr2 | |
48 { | |
49 $$ = re2or($1, $3); | |
50 } | |
51 | |
52 expr2: | |
53 expr3 | |
54 | expr2 expr3 | |
55 { | |
56 $$ = re2cat($1, $2); | |
57 } | |
58 | |
59 expr3: | |
60 expr4 | |
61 | expr3 LSTAR | |
62 { | |
63 $$ = re2star($1); | |
64 } | |
65 | expr3 LPLUS | |
66 { | |
67 $$.beg = ral(Talt); | |
68 patchnext($1.end, $$.beg); | |
69 $$.beg->u.alt = $1.beg; | |
70 $$.end = $$.beg; | |
71 $$.beg = $1.beg; | |
72 } | |
73 | expr3 LQUES | |
74 { | |
75 $$.beg = ral(Talt); | |
76 $$.beg->u.alt = $1.beg; | |
77 $$.end = $1.end; | |
78 appendnext($$.end, $$.beg); | |
79 } | |
80 | |
81 expr4: | |
82 LCHAR | |
83 { | |
84 $$.beg = ral(Tclass); | |
85 $$.beg->u.x.lo = $1; | |
86 $$.beg->u.x.hi = $1; | |
87 $$.end = $$.beg; | |
88 } | |
89 | LBEGIN | |
90 { | |
91 $$.beg = ral(Tbegin); | |
92 $$.end = $$.beg; | |
93 } | |
94 | LEND | |
95 { | |
96 $$.beg = ral(Tend); | |
97 $$.end = $$.beg; | |
98 } | |
99 | LDOT | |
100 { | |
101 $$ = re2class("^\n"); | |
102 } | |
103 | LCLASS | |
104 { | |
105 $$ = re2class($1); | |
106 } | |
107 | LLPAREN expr1 LRPAREN | |
108 { | |
109 $$ = $2; | |
110 } | |
111 | |
112 newlines: | |
113 LNEWLINE | |
114 | newlines LNEWLINE | |
115 %% | |
116 | |
117 void | |
118 yyerror(char *e, ...) | |
119 { | |
120 if(filename) | |
121 fprint(2, "grep: %s:%ld: %s\n", filename, lineno, e); | |
122 else | |
123 fprint(2, "grep: %s\n", e); | |
124 exits("syntax"); | |
125 } | |
126 | |
127 int | |
128 yylex(void) | |
129 { | |
130 char *q, *eq; | |
131 int c, s; | |
132 | |
133 if(peekc) { | |
134 s = peekc; | |
135 peekc = 0; | |
136 return s; | |
137 } | |
138 c = getrec(); | |
139 if(literal) { | |
140 if(c != 0 && c != '\n') { | |
141 yylval.val = c; | |
142 return LCHAR; | |
143 } | |
144 literal = 0; | |
145 } | |
146 switch(c) { | |
147 default: | |
148 yylval.val = c; | |
149 s = LCHAR; | |
150 break; | |
151 case '\\': | |
152 c = getrec(); | |
153 yylval.val = c; | |
154 s = LCHAR; | |
155 if(c == '\n') | |
156 s = LNEWLINE; | |
157 break; | |
158 case '[': | |
159 goto getclass; | |
160 case '(': | |
161 s = LLPAREN; | |
162 break; | |
163 case ')': | |
164 s = LRPAREN; | |
165 break; | |
166 case '|': | |
167 s = LALT; | |
168 break; | |
169 case '*': | |
170 s = LSTAR; | |
171 break; | |
172 case '+': | |
173 s = LPLUS; | |
174 break; | |
175 case '?': | |
176 s = LQUES; | |
177 break; | |
178 case '^': | |
179 s = LBEGIN; | |
180 break; | |
181 case '$': | |
182 s = LEND; | |
183 break; | |
184 case '.': | |
185 s = LDOT; | |
186 break; | |
187 case 0: | |
188 peekc = -1; | |
189 case '\n': | |
190 s = LNEWLINE; | |
191 break; | |
192 } | |
193 return s; | |
194 | |
195 getclass: | |
196 q = u.string; | |
197 eq = q + nelem(u.string) - 5; | |
198 c = getrec(); | |
199 if(c == '^') { | |
200 q[0] = '^'; | |
201 q[1] = '\n'; | |
202 q[2] = '-'; | |
203 q[3] = '\n'; | |
204 q += 4; | |
205 c = getrec(); | |
206 } | |
207 for(;;) { | |
208 if(q >= eq) | |
209 error("class too long"); | |
210 if(c == ']' || c == 0) | |
211 break; | |
212 if(c == '\\') { | |
213 *q++ = c; | |
214 c = getrec(); | |
215 if(c == 0) | |
216 break; | |
217 } | |
218 *q++ = c; | |
219 c = getrec(); | |
220 } | |
221 *q = 0; | |
222 if(c == 0) | |
223 return LBAD; | |
224 yylval.str = u.string; | |
225 return LCLASS; | |
226 } |