ref: 5a51e900dd113a1a5f2d2a0e8bac067fbc7da3ae
dir: /sys/src/cmd/grap/grapl.lx/
%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" extern struct symtab symtab[]; 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", cbuf 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; } %%