| %Start A str def thru sh |
| |
| %{ |
| #undef input |
| #undef unput |
| #include <stdio.h> |
| #include <stdlib.h> |
| #include <ctype.h> |
| #include "grap.h" |
| #include "y.tab.h" |
| |
| int yyback(int *, int); |
| int yylook(void); |
| int yywrap(void); |
| void shell_init(void), shell_exec(void), shell_text(char *); |
| |
| #define CADD cbuf[clen++] = yytext[0]; \ |
| if (clen >= CBUFLEN-1) { \ |
| ERROR "string too long" WARNING; BEGIN A; } |
| #define CBUFLEN 1500 |
| char cbuf[CBUFLEN]; |
| int clen, cflag; |
| int c, delim, shcnt; |
| %} |
| |
| A [a-zA-Z_] |
| B [a-zA-Z0-9_] |
| D [0-9] |
| WS [ \t] |
| |
| %% |
| if (yybgin-yysvec-1 == 0) { /* witchcraft */ |
| BEGIN A; |
| } |
| |
| <A>{WS} ; |
| <A>"\\"\n ; |
| <A>\n return(ST); |
| <A>";" return(ST); |
| |
| <A>line return(yylval.i = LINE); |
| <A>arrow { yylval.i = ARROW; return(LINE); } |
| <A>circle return(yylval.i = CIRCLE); |
| <A>frame return(FRAME); |
| <A>tick(s)? return(TICKS); |
| <A>grid(line)?(s)? return(GRID); |
| <A>coord(s)? return(COORD); |
| <A>log return(LOG); |
| <A>exp return(EXP); |
| <A>sin return(SIN); |
| <A>cos return(COS); |
| <A>atan2 return(ATAN2); |
| <A>sqrt return(SQRT); |
| <A>rand return(RAND); |
| <A>max return(MAX); |
| <A>min return(MIN); |
| <A>int return(INT); |
| <A>print return(PRINT); |
| <A>sprintf return(SPRINTF); |
| <A>pic{WS}.* { yylval.p = tostring(yytext+3); return(PIC); } |
| <A>graph{WS}.* { yylval.p = tostring(yytext+5); return(GRAPH); } |
| |
| <A>for return(FOR); |
| <A>^Endfor\n { endfor(); } |
| <A>do { yylval.p = delimstr("loop body"); BEGIN A; return(DOSTR); } |
| |
| <A>copy|include { return(COPY); } |
| <A>thru|through { BEGIN thru; return(THRU); } |
| <thru>{WS}+ ; |
| <thru>{A}{B}*|. { yylval.op = copythru(yytext); BEGIN A; return(DEFNAME); } |
| <A>until return(UNTIL); |
| |
| <A>if return(IF); |
| <A>then { yylval.p = delimstr("then part"); BEGIN A; return(THEN); } |
| <A>else { yylval.p = delimstr("else part"); BEGIN A; return(ELSE); } |
| |
| <A>next return(NEXT); |
| <A>draw return(yylval.i = DRAW); |
| <A>new return(yylval.i = NEW); |
| <A>plot return(yylval.i = PLOT); |
| <A>label(s)? return(LABEL); |
| <A>x return(X); |
| <A>y return(Y); |
| |
| <A>top { yylval.i = TOP; return SIDE; } |
| <A>bot(tom)? { yylval.i = BOT; return SIDE; } |
| <A>left { yylval.i = LEFT; return SIDE; } |
| <A>right { yylval.i = RIGHT; return SIDE; } |
| <A>up return(yylval.i = UP); |
| <A>down return(yylval.i = DOWN); |
| <A>across return(yylval.i = ACROSS); |
| <A>height|ht return(yylval.i = HEIGHT); |
| <A>wid(th)? return(yylval.i = WIDTH); |
| <A>rad(ius)? return(yylval.i = RADIUS); |
| <A>invis return(yylval.i = INVIS); |
| <A>dot(ted) return(yylval.i = DOT); |
| <A>dash(ed) return(yylval.i = DASH); |
| <A>solid return(yylval.i = SOLID); |
| |
| <A>ljust { yylval.i = LJUST; return JUST; } |
| <A>rjust { yylval.i = RJUST; return JUST; } |
| <A>above { yylval.i = ABOVE; return JUST; } |
| <A>below { yylval.i = BELOW; return JUST; } |
| <A>size return(yylval.i = SIZE); |
| |
| <A>from return(yylval.i = FROM); |
| <A>to return(yylval.i = TO); |
| <A>by|step return(yylval.i = BY); |
| <A>at return(yylval.i = AT); |
| <A>with return(yylval.i = WITH); |
| <A>in return(yylval.i = IN); |
| <A>out return(yylval.i = OUT); |
| <A>off return(yylval.i = OFF); |
| |
| <A>sh{WS}+ { BEGIN sh; |
| if ((delim = input()) == '{') { |
| shcnt = 1; |
| delim = '}'; |
| } |
| shell_init(); |
| } |
| <sh>{A}{B}* { |
| int c; |
| Obj *p; |
| if (yytext[0] == delim) { |
| shell_exec(); |
| BEGIN A; |
| } else { |
| p = lookup(yytext, 0); |
| if (p != NULL && p->type == DEFNAME) { |
| c = input(); |
| unput(c); |
| if (c == '(') |
| dodef(p); |
| else |
| pbstr(p->val); |
| } else |
| shell_text(yytext); |
| } |
| } |
| <sh>"{" { shcnt++; shell_text(yytext); } |
| <sh>"}" { if (delim != '}' || --shcnt > 0) |
| shell_text(yytext); |
| else { |
| shell_exec(); |
| BEGIN A; |
| } |
| } |
| <sh>.|\n { if (yytext[0] == delim) { |
| shell_exec(); |
| BEGIN A; |
| } else |
| shell_text(yytext); |
| } |
| |
| <A>define{WS}+ { BEGIN def; } |
| <def>{A}{B}* { definition(yytext); BEGIN A; } |
| |
| <A>({D}+("."?){D}*|"."{D}+)((e|E)("+"|-)?{D}+)?i? { |
| yylval.f = atof(yytext); return(NUMBER); } |
| |
| <A>^"."[^0-9].* { if (yytext[1] == 'G' && yytext[2] == '2') { |
| yylval.i = yytext[2]; |
| return(EOF); |
| } else { |
| yylval.p = tostring(yytext); |
| return(PIC); |
| } |
| } |
| |
| <A>{A}{B}* { |
| int c; |
| Obj *p; |
| p = lookup(yytext, 1); |
| if (p->type == DEFNAME) { |
| c = input(); |
| unput(c); |
| if (c == '(') /* it's name(...) */ |
| dodef(p); |
| else /* no argument list */ |
| pbstr(p->val); |
| } else { |
| yylval.op = p; |
| return p->type; /* NAME or VARNAME */ |
| } |
| } |
| |
| <A>"==" return(EQ); |
| <A>">=" return(GE); |
| <A>"<=" return(LE); |
| <A>"!=" return(NE); |
| <A>">" return(GT); |
| <A>"<" return(LT); |
| <A>"&&" return(AND); |
| <A>"||" return(OR); |
| <A>"!" return(NOT); |
| |
| <A>\" { BEGIN str; clen = 0; } |
| |
| <A>#.* ; |
| |
| <A>. { yylval.i = yytext[0]; return(yytext[0]); } |
| |
| <str>\" { BEGIN A; cbuf[clen] = 0; |
| yylval.p = tostring(cbuf); return(STRING); } |
| <str>\n { ERROR "newline in string" WARNING; BEGIN A; return(ST); } |
| <str>"\\\"" { cbuf[clen++] = '\\'; cbuf[clen++] = '"'; } |
| <str>"\\\\" { cbuf[clen++] = '\\'; cbuf[clen++] = '\\'; } |
| <str>. { CADD; } |
| |
| %% |