|
|
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.