|
|
1.1 root 1: /* Copyright Bell Telephone Laboratories Whippany, N.J.
2:
3: * /////////////////////////////////////
4: * /////////////////////////////////////
5: * ////////////// class.c //////////////
6: * /// J. P. Hawkins WH X4610 8C-001 ///
7: * ///// Fri Aug 24 16:52:56 1979 //////
8: * /////////////////////////////////////
9: * /////////////////////////////////////
10: *
11: * ALGEBRAIC EXPRESSION FIELD and OPERATOR CLASSIFIER
12: * and SYNTAX CHECKER
13: * (LEXICAL analyzer of sorts)
14: *
15: * MOD,J.P.Hawkins,31-JAN-81 to recognize string variables and strings
16: * MOD,J.P.Hawkins,17-FEB-81 to recognize string functions
17: *
18: * calling format:
19: *
20: * field class (or error) = class(&sptr, field);
21: *
22: * where the ADDRESS of the Pointer sptr MUST be passed
23: * the input string pointer will be MODIFIED and
24: * LEFT at a point after the field just parsed
25: *
26: * field = pointer to txtbuf where a null terminated copy
27: * of the field just parsed will be left
28: *
29: * error code = negative of class
30: * (i.e. a certain type field was attempted
31: * but something illegal happened
32: */
33: /* "@(#) class.c: V 1.4 3/1/81" */
34: #include "bas.h"
35: #define cpychr() {*fptr++ = **sptr ; *sptr += 1; }
36: /*
37: * the legdlm(X) test implies that those fields as checked by class
38: * may have the defined limited char values following the field
39: * the chars 1 through 37(8) are keywords (defined in bed.c) which
40: * replace "goto","go to","then","to","step","<=","=<","<",">=","=>",">"
41: * "=" or "<>" which is done at input time to compact the code and to
42: * simplify run time tests for these combinations
43: */
44: #define legdlm(X) ((any(X," ^*+/-)") || (X>='\0' && X <= '\37')))
45: /*
46: #define skip00() {while(**sptr == ' ' || **sptr == '\t') *sptr +=1;}
47: */
48: #define skip00() {} /* skip00 does nothing */
49: class(sptr, field)
50: char **sptr; /* input string pointer */
51: char *field; /* pointer to output field */
52: {
53: char *fptr; /* output field pointer */
54: int pcnt; /* parenthesis best counter */
55: #ifdef STRINGS
56: int strflg; /* string function flag */
57: #endif
58: pcnt = 0; /* init paren nest counter */
59: fptr = field; /* init output field pointer */
60: skip00(); /* skip leading blanks and tabs */
61: /*
62: * QUOTED LITERAL STRING?
63: */
64: #ifdef STRINGS
65: if(**sptr == '"') /* if beginning of string */
66: {
67: *sptr += 1; /* bump past 1st quote */
68: while(!(**sptr == '"' || **sptr == '\0'))
69: cpychr();
70: if(**sptr == '"')
71: {
72: *sptr += 1; /* bump past end delimiter */
73: *fptr = '\0'; /* null terminate */
74: return(STCLASS); /* LITERAL STRING CLASS */
75: }
76: return(-STCLASS); /* unbalanced quotes */
77: }
78: #endif
79: if(alpha(**sptr)) /* if 1st char is alpha */
80: {
81: cpychr(); /* copy first alpha */
82: if(alpha(**sptr)) /* if second alpha it must be func */
83: {
84: /*
85: * copy until first non-alphanumeric
86: * this must be a FUNCTION FIELD.
87: * The first non-alpha numeric must be a '('
88: */
89: while(alpha(**sptr) || num(**sptr))
90: cpychr();
91: #ifdef STRINGS
92: strflg = 0;
93: if(**sptr == '$') /* string function? */
94: {
95: strflg = 1; /* yes */
96: cpychr();
97: }
98: #endif
99:
100: if(**sptr == '(') /* func name followed by '(' */
101: {
102: pcnt = 1; /* count first nest deep */
103: cpychr(); /* copy initial '(' */
104: /*
105: * scan stuff inside of parens.
106: * parens must be balanced to terminate
107: * function field.
108: */
109: while(pcnt > 0 && **sptr != 0)
110: {
111: switch(**sptr){
112: case '(':
113: pcnt += 1;
114: break;
115: case ')':
116: pcnt -= 1;
117: break;
118: default:
119: break;
120: }
121: cpychr();
122: }
123: if(**sptr == 0 && pcnt != 0)
124: {
125: *fptr='\0';
126: /*
127: * line terminates before
128: * function defined.
129: */
130: #ifdef STRINGS
131: if(strflg)
132: return(-SFCLASS);
133: else
134: #endif
135: return(-FNCLASS);
136: }
137: if(legdlm(**sptr))
138: {
139: *fptr = '\0'; /* null term */
140: /*
141: * Return function class code
142: */
143: #ifdef STRINGS
144: if(strflg)
145: return(SFCLASS);
146: else
147: #endif
148: return(FNCLASS);
149: }
150: else /* illegal delim */
151: return(-FNCLASS);
152: }
153: else
154: {
155: return(-FNCLASS); /* function def without
156: '(' */
157: }
158: }
159: else /* VARIABLE OR VARIABLE ARRAY FIELD */
160: {
161: if(num(**sptr))
162: cpychr(); /* cpy numeric part of var name */
163: #ifdef STRINGS
164: strflg = 0;
165: if(**sptr == '$') /* string function? */
166: {
167: strflg = 1; /* yes */
168: cpychr();
169: }
170: #endif
171: if(**sptr == '(') /* array paren? */
172: {
173: pcnt = 1; /* init paren count */
174: cpychr(); /* copy 1st paren */
175: /*
176: * scan stuff inside of parens.
177: * parens must be balanced to terminate
178: * function field.
179: */
180: while(pcnt > 0 && **sptr != 0)
181: {
182: switch(**sptr){
183: case '(':
184: pcnt += 1;
185: break;
186: case ')':
187: pcnt -= 1;
188: break;
189: default:
190: break;
191: }
192: cpychr();
193: }
194: if(**sptr == 0 && pcnt != 0)
195: {
196: *fptr='\0';
197: /*
198: * line terminates before array
199: * defined
200: */
201: #ifdef STRINGS
202: if(strflg)
203: return(-SACLASS);
204: else
205: #endif
206: return(-VACLASS);
207: }
208: if(legdlm(**sptr))
209: {
210: *fptr = '\0'; /* null term */
211: #ifdef STRINGS
212: if(strflg)
213: return(SACLASS);
214: else
215: #endif
216: return(VACLASS);
217: }
218: else
219: {
220: *fptr = '\0';
221: /* ill delim */
222: #ifdef STRINGS
223: if(strflg)
224: return(-SACLASS);
225: else
226: #endif
227: return(-VACLASS);
228: }
229: }
230: else /* VARIABLE NAME FIELD */
231: {
232: if(legdlm(**sptr)) /* legal delimiter */
233: {
234: *fptr = '\0'; /* null term */
235: #ifdef STRINGS
236: if(strflg)
237: return(SVCLASS);
238: else
239: #endif
240: return(VRCLASS);
241: }
242: else
243: {
244: #ifdef STRINGS
245: if(strflg)
246: return(-SVCLASS);
247: else
248: #endif
249: return(-VRCLASS); /* ill delim */
250: }
251: }
252: }
253: }
254: else /* EITHER NUMERIC OR OPERATOR FIELD */
255: {
256: if(num(**sptr) || **sptr == '.')
257: {
258: cpychr(); /* copy 1st dig of num */
259: while(num(**sptr)) /* copy all consec dig */
260: cpychr();
261: if(**sptr == '.') /* embedded '.' is allowed */
262: {
263: cpychr(); /* copy '.' */
264: while(num(**sptr)) /* get digits following
265: decimal point */
266: cpychr();
267: }
268: if(**sptr == 'e' || **sptr == 'E')
269: {
270: cpychr();
271: /*
272: * HANDLE EXPONENTIAL NOTATION TYPE
273: */
274: if(**sptr == '+' || **sptr == '-')
275: {
276: cpychr();
277: if(num(**sptr))
278: {
279: /* copy exponent */
280: while(num(**sptr))
281: cpychr();
282: }
283: else
284: {
285: return(-NMCLASS);
286: }
287: }
288: else
289: {
290: return(-NMCLASS);
291: }
292: }
293: if(legdlm(**sptr)) /* check for legal delim */
294: {
295: *fptr = '\0'; /* null term */
296: return(NMCLASS); /* numeric */
297: }
298: else
299: return(-NMCLASS); /* ill delim */
300: }
301: else /* OPERATOR FIELD */
302: {
303: if(any(**sptr, "^*/+-()"))
304: {
305: cpychr(); /* copy the operator */
306: *fptr = '\0'; /* term with null */
307: return(OPCLASS); /* operator */
308: }
309: else
310: return(-OPCLASS); /* illegal delim */
311: }
312: }
313: }
314: /*
315: *
316: * //////// TRUE IF ANY CHARS IN STRING as MATCH c ////////
317: */
318: any(c, as)
319: int c;
320: char *as;
321: {
322: register char *s;
323:
324: s = as;
325: while(*s)
326: if(*s++ == c)
327: return(1);
328: return(0);
329: }
330:
331: /*
332: * //// TRUE IF ALPHA lower case ////
333: */
334: alpha(c)
335: char c;
336: {
337: if(c >= 'a' && c <= 'z')
338: return(1);
339: else
340: return(0);
341: }
342:
343: /*
344: * //// TRUE IF NUMERIC ////
345: */
346: num(c)
347: char c;
348: {
349: if(c >= '0' && c <= '9')
350: return(1);
351: else
352: return(0);
353: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.