|
|
1.1 ! root 1: ! 2: %{ ! 3: /* ! 4: token.lm ! 5: ! 6: This file defines the tokens that the Expression grammar is built on. To ! 7: fully understand this file, you will need to understand lex. The basic ! 8: idea is that lex scans a text stream and breaks that stream up into tokens ! 9: which are then fed to the grammar (defined in yacc). Whitespace is ignored ! 10: so the grammar is just fed a steady stream of significant tokens. ! 11: */ ! 12: ! 13: /* ! 14: * These are the routines lex calls to get another character as it parses. ! 15: * By default they are macros which read from stdin. We toss the default ! 16: * macro definitions and supply our own versions of these, which will feed ! 17: * lex characters from the expression string we are parsing. ! 18: */ ! 19: #undef input ! 20: #undef unput ! 21: #undef output ! 22: static int input(); ! 23: static void unput(char c); ! 24: static void output(char c); ! 25: ! 26: #import <stdlib.h> ! 27: #import <string.h> ! 28: #import <math.h> ! 29: #import "exprDefs.h" ! 30: #import "y.tab.h" ! 31: ! 32: /* global which holds the string we are parsing */ ! 33: static const char *CurrText; ! 34: ! 35: /* glue to get rid of compiler warnings */ ! 36: extern yylook(), yyback(); ! 37: static int yywrap(); ! 38: %} ! 39: ! 40: DIGIT ([0-9]) ! 41: EXP ([Ee][+-]?[0-9]+) ! 42: ! 43: %% ! 44: ! 45: ! 46: [ \t\n]+ { /* whitespace - we ignore it */ ! 47: ; ! 48: } ! 49: ! 50: {DIGIT}+ { /* an integer */ ! 51: yylval.integer = atoi(yytext); ! 52: return INTEGER; ! 53: } ! 54: ! 55: (({DIGIT}+"."{DIGIT}*{EXP}?)|([+-]?{DIGIT}*"."{DIGIT}+{EXP}?)|({DIGIT}+{EXP})) { /* a float */ ! 56: yylval.real = atof(yytext); ! 57: return NUMBER; ! 58: } ! 59: ! 60: {DIGIT}+"#"[a-zA-Z0-9]+ { /* a radix number */ ! 61: int radix; ! 62: register int mult = 1; ! 63: register char *c, *stop; ! 64: register unsigned int accum = 0; ! 65: register int charVal; ! 66: ! 67: sscanf( yytext, "%d#", &radix ); ! 68: for( stop = yytext; *stop++ != '#'; ); /* skip the pound sign */ ! 69: for( c = yytext+yyleng-1; c >= stop; c--, mult *= radix ) { ! 70: if( *c >= '0' && *c <= '9' ) ! 71: charVal = *c - '0'; ! 72: else if( *c >= 'A' && *c <= 'Z' ) ! 73: charVal = *c - 'A' + 10; ! 74: else ! 75: charVal = *c - 'a' + 10; ! 76: accum += mult * charVal; ! 77: } ! 78: yylval.real = accum; ! 79: return NUMBER; ! 80: } ! 81: ! 82: pi { /* the constant pi */ ! 83: yylval.real = M_PI; ! 84: return NUMBER; ! 85: } ! 86: ! 87: e { /* the constant e */ ! 88: yylval.real = M_E; ! 89: return NUMBER; ! 90: } ! 91: ! 92: [-+*/%^(),] { /* a single char that must be recognized */ ! 93: return yytext[0]; ! 94: } ! 95: ! 96: [A-Za-z_][A-Za-z_0-9]* { /* an identifier */ ! 97: yylval.string = NXZoneMalloc(NXDefaultMallocZone(), yyleng+1); ! 98: bcopy(yytext, yylval.string, yyleng); ! 99: yylval.string[yyleng] = '\0'; ! 100: return IDENTIFIER; ! 101: } ! 102: ! 103: . { /* other garbage chars (last rule is the default) */ ! 104: yylval.character = yytext[0]; ! 105: return BADCHAR; ! 106: } ! 107: ! 108: ! 109: %% ! 110: ! 111: /* inits the global string to the one we will parse */ ! 112: void _EXPPrepareToScan(const char *text) { ! 113: CurrText = text; ! 114: } ! 115: ! 116: /* tells lex there's really no more input when we're done */ ! 117: static int yywrap() { ! 118: return 1; ! 119: } ! 120: ! 121: /* returns the next char of the string we're parsing */ ! 122: static int input() { ! 123: return *CurrText++; ! 124: } ! 125: ! 126: /* lets lex back up one char in the string we're parsing */ ! 127: static void unput(char c) { ! 128: --CurrText; ! 129: } ! 130: ! 131: /* called by lex when it wants to output a char. This should never happen. */ ! 132: static void output(char c) { ! 133: fprintf(stderr, "lex output function called with char '%c'\n", c); ! 134: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.