%x Comment QuotedString %{ /* * %a 21000 * %n 1000 * %o 42000 * %p 3500 * * Mike Markowski (mm@arl.mil) * March 16, 1998 * * Note: keyword() is stupid. A better keyword search can * be easily implemented, but wasn't for lack of time... * * Another note: real numbers are not flexible enough. Currently, * at least one digit must follow a decimal point. I.e., * 1.0 is legal, but 1. is not. However, both 0.5 and .5 are ok. */ /* * Get rid of lex default macros input() and unput() since we want to * use trickier things. Our versions are redefined in lexInput.c. * If you're not using AT&T lex, this will probably have to be changed. *** #undef input *** #undef unput */ #include #include #include #include "y.tab.h" int kw, /* Keyword (string) token type (int). */ lineno = 1; void yyerror(); %} ws [ \t\f]+ nl \n int [0-9]+ dreal ([0-9]*"."[0-9]+) ereal ([0-9]*"."[0-9]+[eE][+-]?[0-9]+) real {dreal}|{ereal}|{int} id [_a-zA-Z]+[_0-9a-zA-Z]* comment ^#.*$ %% {comment} | {ws} ; {nl} { lineno++; } {real} { sscanf(yytext, "%lf", &(yylval.number)); return NUMBER; } {id} { if (kw = keyword(yytext)) return kw; else { yylval.string = strdup(yytext); return STRING; }; } "\"" { BEGIN QuotedString; } [^"\\] { yymore(); } "\\" { yymore(); yyleng--; } "\"" { BEGIN INITIAL; yytext[yyleng-1] = '\0'; yylval.string = strdup(yytext); return STRING; } "/*" { BEGIN Comment; } . | {nl} /* Eat comment. */ ; "*/" { BEGIN INITIAL; } "{" | "}" | ";" | "(" | ")" | "," | "*" | "+" | "-" | "/" | "%" | ":" | "^" { return yytext[0]; } . { yyerror(yytext); } %% struct keyword { char *name; /* String itself. */ int tokenType, /* Its token type. */ len; /* Strlen(name). */ }; static struct keyword keywords[] = { "anchor", ANCHOR, 6, "at", AT, 2, "attributes", ATTRIBUTES, 10, "back", BACK, 4, "bottom", BOTTOM, 6, "center", CENTER, 6, "circular", CIRCULAR, 8, "cm", CM, 2, "color", COLOR, 5, "cursor", CURSOR, 6, "e", E, 1, "eng", ENG, 3, "equation", EQUATION, 8, "false", FALSE, 5, "filename", FILENAME, 8, "fold", FOLD, 4, "font", FONT, 4, "format", FORMAT, 6, "fp", FP, 2, "front", FRONT, 5, "gap", GAP, 3, "inch", INCH, 4, "inches", INCHES, 6, "label", LABEL, 5, "left", LEFT, 4, "length", LENGTH, 6, "line", LINE, 4, "material", MATERIAL, 8, "min", MIN, 3, "mm", MM, 2, "more", MORE, 4, "notation", NOTATION, 8, "numberline", NUMBERLINE, 10, "on", ON, 2, "only", ONLY, 4, "pi", PI, 2, "position", POSITION, 8, "range", RANGE, 5, "reducer", REDUCER, 7, "right", RIGHT, 5, "scale", SCALE, 5, "scientific", SCIENTIFIC, 10, "segment", SEGMENT, 7, "slide", SLIDE, 5, "sliderule", SLIDERULE, 9, "stator", STATOR, 6, "step", STEP, 4, "straight", STRAIGHT, 8, "symbol", SYMBOL, 6, "text", TEXT, 4, "thickness", THICKNESS, 9, "ticks", TICKS, 5, "to", TO, 2, "top", TOP, 3, "true", TRUE, 4, "width", WIDTH, 5, "zoom", ZOOM, 4, "sin", FN, 3, "cos", FN, 3, "tan", FN, 3, "log", FN, 3, "ln", FN, 3, (char *) 0, 0, 0 }; /* * k e y w o r d ( ) * * See if string value matches a keyword. First check lengths (quick, * simple, possible match). If same, only then do all out strcmp(). * * Note: This could be sped up if I took the time to write something * better than a sequential search! */ int keyword(char * s) { struct keyword *ptr = keywords; int len; len = strlen(s); while (ptr->len != 0) if (len == ptr->len && !strcmp(ptr->name, s)) { if (ptr->tokenType == FN) yylval.string = strdup(yytext); return ptr->tokenType; /* Keyword match. */ } else ptr++; return 0; /* No keyword match. */ } /* * y y e r r o r ( ) */ void yyerror(char * str) { printf("line %d: %s (yytext='%s')\n", lineno, str, yytext); }