| 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 } |