%{ /*- * Lexical analyzer for yacc date parser and calculator * * caller must define and point at a buffer loaded with string to be analyzed: * char *sp; * * J. A. Rupley, Tucson, Arizona */ #include #include #include #include "jul_greg.h" #include "y.tab.h" /* yacc defines */ /* * OLD = ATT LEX REDEFINITION OF INPUT() FOR READ OF SP=STRING INPUT VARIABLE * for gnu bison/yacc replace with definiton of YY_INPUT * * #undef input() * #undef unput(c) * #define input() (isupper(yytchar=(*sp++))?tolower(yytchar):yytchar) * #define unput(c) sp-- */ /* * redefine YY_INPUT * from oreilly book by levine et al - lex/yacc... * from comp.lang.c post * From: Garrett Wollman (wollman@emily.uvm.edu) * Subject: Re: using lex with strings, not files * Date: 1991-05-13 02:05:37 PST * * the inline code reading sp by character works * block read inline code works also..... used it */ #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ { \ int c = '*', n; \ for ( n = 0; n < max_size && \ (c = *sp) != '\0' && c != '\n'; ++n, ++sp) \ { \ buf[n] = (char) tolower(c); \ } \ /* if ( c == '\n' || c == '\0' ) \ */ \ if ( c == '\n' ) \ buf[++n] = '\n'; \ result = n; \ } #if 0 #undef YY_INPUT #define YY_INPUT(buf,result,max_size) \ { \ int c = '*', n; \ printf("YY_INPUT enter: c=%c, n=%d, *sp=\"%d\", sp=%d, sp=\"%s\", buf=\"%s\"\n", c, n, *sp, sp, sp, buf); \ for ( n = 0; n < max_size && \ (c = *sp) != '\0' && c != '\n'; ++n, ++sp) \ { \ buf[n] = (char) tolower(c); \ printf("YY_INPUT loop: c=%c, n=%d, *sp=\"%d\", sp=%d, sp=\"%s\", buf=\"%s\"\n", c, n, *sp, sp, sp, buf); \ } \ result = n; \ printf("YY_INPUT exit: c=%c, n=%d, *sp=\"%d\", sp=%d, sp=\"%s\", buf=\"%s\"\n", c, n, *sp, sp, sp, buf); \ } */ /* if ( c == '\n' || c == '\0' ) \ */ \ /* if ( c == '\n' ) \ */ \ /* buf[n++] = (char) '\n'; \ */ \ #endif #if 0 #undef YY_INPUT /* #define YY_INPUT(buf, result, max) input_from_sp(buf, result, max) \ */ #define YY_INPUT(buf, result, max) \ { \ int len = strlen(sp); \ result = 0; \ if (len) strncpy(buf, sp, result=MIN(len, max - 1)); \ buf[result] = '\0'; \ sp += result; \ /* printf("buf on input=\"%s\"\nwith # char read=%d and length=%d\n", buf, * strlen(buf), result); \ */ \ /* printf("contents of sp=\"%c\",%d\n", *sp, *sp); \ */ \ } #endif void input_from_sp ( ); extern char *sp; extern int day_map[], month_map[]; %} W [ \t\n"()] NW [^ \t\n"()] NWP [^ \t\n"(),/.] P [,/.] M (jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]* WD (mon?|tue?|wed?|thu?|fri?|sat?|sun?) WDD {WD}|{WD}[a-z]*day U d|w|m|y|day|week|month|year D [+-]?[0-9]+ %% {M}/{W} { yylval.val = month_map[(yytext[1] + yytext[2]) & 0x1f]; return MONTH; } {WDD}/{W} { yylval.val = day_map[(yytext[0] & 7) + (yytext[1] & 4)]; return DAY; } {D}/({W}|{P}) { #define GREGORIAN 2299161 /* julian date for gregorian epoch */ long atol(); if ((yylval.julian = atol(yytext)) >= GREGORIAN) return JULIAN; /* assume large numbers are julian */ else { yylval.val = yylval.julian; return NUMBER; } } {U}/{W} {yylval.val = yytext[0]; return UNIT;} (today|now)/{W} {yylval.val = yytext[0]; return TODAY;} {P} {yylval.val = yytext[0]; return PUNC;} -/{W} {yylval.val = yytext[0]; return MINUS;} {W}+ ; {NWP}+ {fprintf(stderr, "\nlexical error: %s\n", yytext); return ERROR;} %% /* void input_from_sp(buf, result, max) char *buf; int result, max_size; { int len = strlen(sp); if (len) strncpy(buf, sp, result=MIN(len, max - 1)); buf[result] = '\0'; sp += result; printf("buf on input=\"%s\"\nwith # char read=%d and length=%d\n", buf, strlen(buf), result); printf("contents of sp=\"%c\",%d\n", *sp, *sp); } */ int yywrap() { return 1; } /*- * Month and weekday hashing is from the tws library, * found in the ``phoon'' distribution, * from comp.sources.unix, volume 8, 1987: * * 01B 15nov86 JP Thouroughly hacked by Jef Poskanzer. * 01A ??????? MTR Original version from the MH 6.5 distribution, courtesy * of Marshall Rose. */ /*- * Table to convert month names to numeric month. We use the * fact that the low order 5 bits of the sum of the 2nd & 3rd * characters of the name is a hash with no collisions for the 12 * valid month names. (The mask to 5 bits maps any combination of * upper and lower case into the same hash value). * Jan = 1; * * hash function: * (c2 + c3) & 0x1f */ static int month_map[] = { 0, 7, /* 1 - Jul */ 4, /* 2 - Apr */ 6, /* 3 - Jun */ 0, 11, /* 5 - Nov */ 0, 2, /* 7 - Feb */ 12, /* 8 - Dec */ 0, 0, 0, 0, 0, 0, 1, /*15 - Jan */ 0, 0, 0, 3, /*19 - Mar */ 0, 9, /*21 - Sep */ 0, 10, /*23 - Oct */ 0, 0, 5, /*26 - May */ 0, 8, /*28 - Aug */ }; /*- * Same trick for day-of-week; Sun = 0; * * hash function: * (c1 & 7) + (c2 & 4) */ static int day_map[] = { 0, 0, 0, 6, /* 3 - Sat */ 4, /* 4 - Thu */ 0, 5, /* 6 - Fri */ 0, /* 7 - Sun */ 2, /* 8 - Tue */ 1 /* 9 - Mon */, 0, 3, /*11 - Wed */ };