| 1 | %term xxif 300 xxelse 301 xxwhile 302 xxrept 303 xxdo 304 xxrb 305 xxpred 306 |
| 2 | %term xxident 307 xxle 308 xxge 309 xxne 310 xxnum 311 xxcom 312 |
| 3 | %term xxstring 313 xxexplist 314 xxidpar 315 xxelseif 316 xxlb 318 xxend 319 |
| 4 | %term xxcase 320 xxswitch 321 xxuntil 322 xxdefault 323 |
| 5 | %term xxeq 324 |
| 6 | |
| 7 | %left '|' |
| 8 | %left '&' |
| 9 | %left '!' |
| 10 | %binary '<' '>' xxeq xxne xxge xxle |
| 11 | %left '+' '-' |
| 12 | %left '*' '/' |
| 13 | %left xxuminus |
| 14 | %right '^' |
| 15 | |
| 16 | %{ |
| 17 | #include "b.h" |
| 18 | #include <stdio.h> |
| 19 | %} |
| 20 | |
| 21 | %% |
| 22 | %{ |
| 23 | struct node *t; |
| 24 | %} |
| 25 | |
| 26 | |
| 27 | allprog: prog xxnew |
| 28 | ; |
| 29 | |
| 30 | prog: stat |
| 31 | | prog stat |
| 32 | ; |
| 33 | |
| 34 | stat: iftok pred nlevel elsetok nlevel |
| 35 | | iftok pred nlevel |
| 36 | | xxtab whtok pred nlevel |
| 37 | | xxtab rpttok nlevel optuntil |
| 38 | | xxtab dotok nlevel |
| 39 | | xxtab swtok oppred pindent lbtok caseseq xxtab rbtok mindent |
| 40 | | xxtab fstok |
| 41 | | lbtok prog xxtab rbtok |
| 42 | | lbtok rbtok |
| 43 | | labtok stat |
| 44 | | xxnl comtok stat |
| 45 | | error |
| 46 | ; |
| 47 | |
| 48 | |
| 49 | xxtab: = { |
| 50 | if (!xxlablast) tab(xxindent); |
| 51 | xxlablast = 0; |
| 52 | } |
| 53 | |
| 54 | xxnl: = newline(); |
| 55 | xxnew: = putout('\n',"\n"); |
| 56 | nlevel: pindent stat mindent; |
| 57 | pindent: = |
| 58 | { |
| 59 | if (xxstack[xxstind] != xxlb) |
| 60 | ++xxindent; |
| 61 | }; |
| 62 | mindent: = |
| 63 | {if (xxstack[xxstind] != xxlb && xxstack[xxstind] != xxelseif) |
| 64 | --xxindent; |
| 65 | pop(); |
| 66 | }; |
| 67 | caseseq: casetok caseseq |
| 68 | | casetok |
| 69 | ; |
| 70 | |
| 71 | casetok: xxtab xxctok predlist pindent prog mindent |
| 72 | | xxtab xxctok predlist pindent mindent |
| 73 | | xxtab deftok pindent prog mindent |
| 74 | | xxnl comtok casetok |
| 75 | ; |
| 76 | |
| 77 | xxctok: xxcase = {putout(xxcase,"case "); free ($1); push(xxcase); } |
| 78 | |
| 79 | |
| 80 | deftok: xxdefault ':' = { |
| 81 | putout(xxcase,"default"); |
| 82 | free($1); |
| 83 | putout(':',":"); |
| 84 | free($2); |
| 85 | push(xxcase); |
| 86 | } |
| 87 | swtok: xxswitch = {putout(xxswitch,"switch"); free($1); push(xxswitch); } |
| 88 | |
| 89 | fstok: xxend = { |
| 90 | free($1); |
| 91 | putout(xxident,"end"); |
| 92 | putout('\n',"\n"); |
| 93 | putout('\n',"\n"); |
| 94 | putout('\n',"\n"); |
| 95 | } |
| 96 | | xxident = { |
| 97 | putout(xxident,$1); |
| 98 | free($1); |
| 99 | newflag = 1; |
| 100 | forst(); |
| 101 | newflag = 0; |
| 102 | }; |
| 103 | |
| 104 | |
| 105 | |
| 106 | identtok: xxident '(' explist ')' = { |
| 107 | xxt = addroot($1,xxident,0,0); |
| 108 | $$ = addroot("",xxidpar,xxt,$3); |
| 109 | } |
| 110 | |
| 111 | | xxident = $$ = addroot($1,xxident,0,0); |
| 112 | ; |
| 113 | |
| 114 | predlist: explist ':' = { |
| 115 | yield($1,0); |
| 116 | putout(':',":"); |
| 117 | freetree($1); |
| 118 | } |
| 119 | explist: expr ',' explist = $$ = addroot($2,xxexplist,checkneg($1,0),$3); |
| 120 | | expr = $$ = checkneg($1,0); |
| 121 | ; |
| 122 | |
| 123 | |
| 124 | oppred: pred |
| 125 | | |
| 126 | ; |
| 127 | |
| 128 | pred: '(' expr ')' = { t = checkneg($2,0); |
| 129 | yield(t,100); freetree(t); }; |
| 130 | |
| 131 | expr: '(' expr ')' = $$ = $2; |
| 132 | | '-' expr %prec xxuminus = $$ = addroot($1,xxuminus,$2,0); |
| 133 | | '!' expr = $$ = addroot($1,'!',$2,0); |
| 134 | | expr '+' expr = $$ = addroot($2,'+',$1,$3); |
| 135 | | expr '-' expr = $$ = addroot($2,'-',$1,$3); |
| 136 | | expr '*' expr = $$ = addroot($2,'*',$1,$3); |
| 137 | | expr '/' expr = $$ = addroot($2,'/',$1,$3); |
| 138 | | expr '^' expr = $$ = addroot($2,'^',$1,$3); |
| 139 | | expr '|' expr = $$ = addroot($2,'|',$1,$3); |
| 140 | | expr '&' expr = $$ = addroot($2,'&',$1,$3); |
| 141 | | expr '>' expr = $$ = addroot($2,'>',$1,$3); |
| 142 | | expr '<' expr = $$ = addroot($2,'<',$1,$3); |
| 143 | | expr xxeq expr = $$ = addroot($2,xxeq,$1,$3); |
| 144 | | expr xxle expr = $$ = addroot($2,xxle,$1,$3); |
| 145 | | expr xxge expr = $$ = addroot($2,xxge,$1,$3); |
| 146 | | expr xxne expr = $$ = addroot($2,xxne,$1,$3); |
| 147 | | identtok = $$ = $1; |
| 148 | | xxnum = $$ = addroot($1,xxnum,0,0); |
| 149 | | xxstring = $$ = addroot($1,xxstring,0,0); |
| 150 | ; |
| 151 | |
| 152 | iftok: xxif = |
| 153 | { |
| 154 | if (xxstack[xxstind] == xxelse && !xxlablast) |
| 155 | { |
| 156 | --xxindent; |
| 157 | xxstack[xxstind] = xxelseif; |
| 158 | putout(' '," "); |
| 159 | } |
| 160 | else |
| 161 | { |
| 162 | if (!xxlablast) |
| 163 | tab(xxindent); |
| 164 | xxlablast = 0; |
| 165 | } |
| 166 | putout(xxif,"if"); |
| 167 | free($1); |
| 168 | push(xxif); |
| 169 | } |
| 170 | elsetok: xxelse = |
| 171 | { |
| 172 | tab(xxindent); |
| 173 | putout(xxelse,"else"); |
| 174 | free($1); |
| 175 | push(xxelse); |
| 176 | } |
| 177 | whtok: xxwhile = { |
| 178 | putout(xxwhile,"while"); |
| 179 | free($1); |
| 180 | push(xxwhile); |
| 181 | } |
| 182 | rpttok: xxrept = { |
| 183 | putout(xxrept,"repeat"); |
| 184 | free($1); |
| 185 | push(xxrept); |
| 186 | } |
| 187 | optuntil: xxtab unttok pred |
| 188 | | |
| 189 | ; |
| 190 | |
| 191 | unttok: xxuntil = { |
| 192 | putout('\t',"\t"); |
| 193 | putout(xxuntil,"until"); |
| 194 | free($1); |
| 195 | } |
| 196 | dotok: dopart opdotok |
| 197 | ; |
| 198 | dopart: xxdo identtok '=' expr ',' expr = |
| 199 | {push(xxdo); |
| 200 | putout(xxdo,"do"); |
| 201 | free($1); |
| 202 | puttree($2); |
| 203 | putout('=',"="); |
| 204 | free($3); |
| 205 | puttree($4); |
| 206 | putout(',',","); |
| 207 | free($5); |
| 208 | puttree($6); |
| 209 | } |
| 210 | opdotok: ',' expr = { |
| 211 | putout(',',","); |
| 212 | puttree($2); |
| 213 | } |
| 214 | | ; |
| 215 | lbtok: '{' = { |
| 216 | putout('{'," {"); |
| 217 | push(xxlb); |
| 218 | } |
| 219 | rbtok: '}' = { putout('}',"}"); pop(); } |
| 220 | labtok: xxnum = { |
| 221 | tab(xxindent); |
| 222 | putout(xxnum,$1); |
| 223 | putout(' '," "); |
| 224 | xxlablast = 1; |
| 225 | } |
| 226 | comtok: xxcom = { putout(xxcom,$1); free($1); xxlablast = 0; } |
| 227 | | comtok xxcom = { putout ('\n',"\n"); putout(xxcom,$2); free($2); xxlablast = 0; }; |
| 228 | %% |
| 229 | #define ASSERT(X,Y) if (!(X)) error("struct bug: assertion 'X' invalid in routine Y","",""); |
| 230 | |
| 231 | yyerror(s) |
| 232 | char *s; |
| 233 | { |
| 234 | extern int yychar; |
| 235 | fprintf(stderr,"\n%s",s); |
| 236 | fprintf(stderr," in beautifying, output line %d,",xxlineno + 1); |
| 237 | fprintf(stderr," on input: "); |
| 238 | switch (yychar) { |
| 239 | case '\t': fprintf(stderr,"\\t\n"); return; |
| 240 | case '\n': fprintf(stderr,"\\n\n"); return; |
| 241 | case '\0': fprintf(stderr,"$end\n"); return; |
| 242 | default: fprintf(stderr,"%c\n",yychar); return; |
| 243 | } |
| 244 | } |
| 245 | |
| 246 | yyinit(argc, argv) /* initialize pushdown store */ |
| 247 | int argc; |
| 248 | char *argv[]; |
| 249 | { |
| 250 | xxindent = 0; |
| 251 | xxbpertab = 8; |
| 252 | xxmaxchars = 120; |
| 253 | } |
| 254 | |
| 255 | |
| 256 | #include <signal.h> |
| 257 | main() |
| 258 | { |
| 259 | int exit(); |
| 260 | if ( signal(SIGINT, SIG_IGN) != SIG_IGN) |
| 261 | signal(SIGINT, exit); |
| 262 | yyinit(); |
| 263 | yyparse(); |
| 264 | } |
| 265 | |
| 266 | |
| 267 | putout(type,string) /* output string with proper indentation */ |
| 268 | int type; |
| 269 | char *string; |
| 270 | { |
| 271 | static int lasttype; |
| 272 | if ( (lasttype != 0) && (lasttype != '\n') && (lasttype != ' ') && (lasttype != '\t') && (type == xxcom)) |
| 273 | accum("\t"); |
| 274 | else if (lasttype == xxcom && type != '\n') |
| 275 | tab(xxindent); |
| 276 | else |
| 277 | if (lasttype == xxif || |
| 278 | lasttype == xxwhile || |
| 279 | lasttype == xxdo || |
| 280 | type == '=' || |
| 281 | lasttype == '=' || |
| 282 | (lasttype == xxident && (type == xxident || type == xxnum) ) || |
| 283 | (lasttype == xxnum && type == xxnum) ) |
| 284 | accum(" "); |
| 285 | accum(string); |
| 286 | lasttype = type; |
| 287 | } |
| 288 | |
| 289 | |
| 290 | accum(token) /* fill output buffer, generate continuation lines */ |
| 291 | char *token; |
| 292 | { |
| 293 | static char *buffer; |
| 294 | static int lstatus,llen,bufind; |
| 295 | int tstatus,tlen,i; |
| 296 | |
| 297 | #define NEW 0 |
| 298 | #define MID 1 |
| 299 | #define CONT 2 |
| 300 | |
| 301 | if (buffer == 0) |
| 302 | { |
| 303 | buffer = malloc(xxmaxchars); |
| 304 | if (buffer == 0) error("malloc out of space","",""); |
| 305 | } |
| 306 | tlen = slength(token); |
| 307 | if (tlen == 0) return; |
| 308 | for (i = 0; i < tlen; ++i) |
| 309 | ASSERT(token[i] != '\n' || tlen == 1,accum); |
| 310 | switch(token[tlen-1]) |
| 311 | { |
| 312 | case '\n': tstatus = NEW; |
| 313 | break; |
| 314 | case '+': |
| 315 | case '-': |
| 316 | case '*': |
| 317 | case ',': |
| 318 | case '|': |
| 319 | case '&': |
| 320 | case '(': tstatus = CONT; |
| 321 | break; |
| 322 | default: tstatus = MID; |
| 323 | } |
| 324 | if (llen + bufind + tlen > xxmaxchars && lstatus == CONT && tstatus != NEW) |
| 325 | { |
| 326 | putchar('\n'); |
| 327 | ++xxlineno; |
| 328 | for (i = 0; i < xxindent; ++i) |
| 329 | putchar('\t'); |
| 330 | putchar(' ');putchar(' '); |
| 331 | llen = 2 + xxindent * xxbpertab; |
| 332 | lstatus = NEW; |
| 333 | } |
| 334 | if (lstatus == CONT && tstatus == MID) |
| 335 | { /* store in buffer in case need \n after last CONT char */ |
| 336 | ASSERT(bufind + tlen < xxmaxchars,accum); |
| 337 | for (i = 0; i < tlen; ++i) |
| 338 | buffer[bufind++] = token[i]; |
| 339 | } |
| 340 | else |
| 341 | { |
| 342 | for (i = 0; i < bufind; ++i) |
| 343 | putchar(buffer[i]); |
| 344 | llen += bufind; |
| 345 | bufind = 0; |
| 346 | for (i = 0; i < tlen; ++i) |
| 347 | putchar(token[i]); |
| 348 | if (tstatus == NEW) ++xxlineno; |
| 349 | llen = (tstatus == NEW) ? 0 : llen + tlen; |
| 350 | lstatus = tstatus; |
| 351 | } |
| 352 | } |
| 353 | |
| 354 | tab(n) |
| 355 | int n; |
| 356 | { |
| 357 | int i; |
| 358 | newline(); |
| 359 | for ( i = 0; i < n; ++i) |
| 360 | putout('\t',"\t"); |
| 361 | } |
| 362 | |
| 363 | newline() |
| 364 | { |
| 365 | static int already; |
| 366 | if (already) |
| 367 | putout('\n',"\n"); |
| 368 | else |
| 369 | already = 1; |
| 370 | } |
| 371 | |
| 372 | error(mess1, mess2, mess3) |
| 373 | char *mess1, *mess2, *mess3; |
| 374 | { |
| 375 | fprintf(stderr,"\nerror in beautifying, output line %d: %s %s %s \n", |
| 376 | xxlineno, mess1, mess2, mess3); |
| 377 | exit(1); |
| 378 | } |
| 379 | |
| 380 | |
| 381 | |
| 382 | |
| 383 | |
| 384 | |
| 385 | |
| 386 | push(type) |
| 387 | int type; |
| 388 | { |
| 389 | if (++xxstind > xxtop) |
| 390 | error("nesting too deep, stack overflow","",""); |
| 391 | xxstack[xxstind] = type; |
| 392 | } |
| 393 | |
| 394 | pop() |
| 395 | { |
| 396 | if (xxstind <= 0) |
| 397 | error("stack exhausted, can't be popped as requested","",""); |
| 398 | --xxstind; |
| 399 | } |
| 400 | |
| 401 | |
| 402 | forst() |
| 403 | { |
| 404 | while( (xxval = yylex()) != '\n') |
| 405 | { |
| 406 | putout(xxval, yylval); |
| 407 | free(yylval); |
| 408 | } |
| 409 | free(yylval); |
| 410 | } |