xref: /original-bsd/usr.bin/pascal/src/yylex.c (revision 1403a0cd)
1 /* Copyright (c) 1979 Regents of the University of California */
2 
3 #ifndef lint
4 static char sccsid[] = "@(#)yylex.c 2.1 02/08/84";
5 #endif
6 
7 #include "whoami.h"
8 #include "0.h"
9 #include "tree_ty.h"	/* must be included for yy.h */
10 #include "yy.h"
11 
12 /*
13  * Scanner
14  */
15 int	yylacnt;
16 
17 #define	YYLASIZ	10
18 
19 struct	yytok Yla[YYLASIZ];
20 
21 unyylex(y)
22 	struct yytok *y;
23 {
24 
25 	if (yylacnt == YYLASIZ)
26 		panic("unyylex");
27 	copy((char *) &Yla[yylacnt], (char *) y, sizeof Yla[0]);
28 	yylacnt++;
29 
30 }
31 
32 yylex()
33 {
34 	register c;
35 	register int **ip;
36 	register char *cp;
37 	int f;
38 	char delim;
39 
40 	if (yylacnt != 0) {
41 		yylacnt--;
42 		copy((char *) &Y, (char *) &Yla[yylacnt], sizeof Y);
43 		return (yychar);
44 	}
45 	if (c = yysavc)
46 		yysavc = 0;
47 	else
48 		c = readch();
49 #ifdef PXP
50 	yytokcnt++;
51 #endif
52 
53 next:
54 	/*
55 	 * skip white space
56 	 */
57 #ifdef PXP
58 	yywhcnt = 0;
59 #endif
60 	while (c == ' ' || c == '\t') {
61 #ifdef PXP
62 		if (c == '\t')
63 			yywhcnt++;
64 		yywhcnt++;
65 #endif
66 		c = readch();
67 	}
68 	yyecol = yycol;
69 	yyeline = yyline;
70 	yyefile = filename;
71 	yyeseqid = yyseqid;
72 	yyseekp = yylinpt;
73 	cp = token;
74 	yylval = yyline;
75 	switch (c) {
76 		case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': case 'g':
77 		case 'h': case 'i': case 'j': case 'k': case 'l': case 'm': case 'n':
78 		case 'o': case 'p': case 'q': case 'r': case 's': case 't': case 'u':
79 		case 'v': case 'w': case 'x': case 'y': case 'z':
80 		case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': case 'G':
81 		case 'H': case 'I': case 'J': case 'K': case 'L': case 'M': case 'N':
82 		case 'O': case 'P': case 'Q': case 'R': case 'S': case 'T': case 'U':
83 		case 'V': case 'W': case 'X': case 'Y': case 'Z':
84 			do {
85 				*cp++ = c;
86 				c = readch();
87 			} while (alph(c) || digit(c));
88 			*cp = 0;
89 			if (opt('s'))
90 				for (cp = token; *cp; cp++)
91 					if (*cp >= 'A' && *cp <= 'Z') {
92 						*cp |= ' ';
93 					}
94 			yysavc = c;
95 			ip = (int **) hash((char *) 0, 1);
96 			if (*ip < (int *) yykey || *ip >= (int *) lastkey) {
97 				yylval = (int) *ip;
98 				return (YID);
99 			}
100 			yylval = yyline;
101 			/*
102 			 * For keywords
103 			 * the lexical token
104 			 * is magically retrieved
105 			 * from the keyword table.
106 			 */
107 			return ((*ip)[1]);
108 		case '0': case '1': case '2': case '3': case '4':
109 		case '5': case '6': case '7': case '8': case '9':
110 			f = 0;
111 			do {
112 				*cp++ = c;
113 				c = readch();
114 			} while (digit(c));
115 			if (c == 'b' || c == 'B') {
116 				/*
117 				 * nonstandard - octal constants
118 				 */
119 				if (opt('s')) {
120 					standard();
121 					yerror("Octal constants are non-standard");
122 				}
123 				*cp = 0;
124 				yylval = copystr(token);
125 				return (YBINT);
126 			}
127 			if (c == '.') {
128 				c = readch();
129 				if (c == '.') {
130 					*cp = 0;
131 					yysavc = YDOTDOT;
132 					yylval = copystr(token);
133 					return (YINT);
134 				}
135 infpnumb:
136 				f++;
137 				*cp++ = '.';
138 				if (!digit(c)) {
139 					yyset();
140 					recovered();
141 					yerror("Digits required after decimal point");
142 					*cp++ = '0';
143 				} else
144 					while (digit(c)) {
145 						*cp++ = c;
146 						c = readch();
147 					}
148 			}
149 			if (c == 'e' || c == 'E') {
150 				f++;
151 				*cp++ = c;
152 				if ((c = yysavc) == 0)
153 					c = readch();
154 				if (c == '+' || c == '-') {
155 					*cp++ = c;
156 					c = readch();
157 				}
158 				if (!digit(c)) {
159 					yyset();
160 					yerror("Digits required in exponent");
161 					*cp++ = '0';
162 				} else
163 					while (digit(c)) {
164 						*cp++ = c;
165 						c = readch();
166 					}
167 			}
168 			*cp = 0;
169 			yysavc = c;
170 			yylval = copystr(token);
171 			if (f)
172 				return (YNUMB);
173 			return (YINT);
174 		case '"':
175 		case '`':
176 		case '#':
177 			if (!any(bufp + 1, c))
178 				goto illch;
179 			if (!dquote) {
180 				recovered();
181 				dquote++;
182 				yerror("Character/string delimiter is '");
183 			}
184 		case '\'':
185 			delim = c;
186 			do {
187 				do {
188 					c = readch();
189 					if (c == '\n') {
190 						yerror("Unmatched %c for string", (char *) delim);
191 						if (cp == token)
192 							*cp++ = ' ', cp++;
193 						break;
194 					}
195 					*cp++ = c;
196 				} while (c != delim);
197 				c = readch();
198 			} while (c == delim);
199 			*--cp = 0;
200 			if (cp == token) {
201 				yerror("Null string not allowed");
202 				*cp++ = ' ';
203 				*cp++ = 0;
204 			}
205 			yysavc = c;
206 			yylval = copystr(token);
207 			return (YSTRING);
208 		case '.':
209 			c = readch();
210 			if (c == '.')
211 				return (YDOTDOT);
212 			if (digit(c)) {
213 				recovered();
214 				yerror("Digits required before decimal point");
215 				*cp++ = '0';
216 				goto infpnumb;
217 			}
218 			yysavc = c;
219 			return ('.');
220 		case '{':
221 			/*
222 			 * { ... } comment
223 			 */
224 #ifdef PXP
225 			getcm(c);
226 #endif
227 #ifdef PI
228 			c = options();
229 			while (c != '}') {
230 				if (c <= 0)
231 					goto nonterm;
232 				if (c == '{') {
233 					warning();
234 					yyset();
235 					yerror("{ in a { ... } comment");
236 				}
237 				c = readch();
238 			}
239 #endif
240 			c = readch();
241 			goto next;
242 		case '(':
243 			if ((c = readch()) == '*') {
244 				/*
245 				 * (* ... *) comment
246 				 */
247 #ifdef PXP
248 				getcm(c);
249 				c = readch();
250 				goto next;
251 #endif
252 #ifdef PI
253 				c = options();
254 				for (;;) {
255 					if (c < 0) {
256 nonterm:
257 						yerror("Comment does not terminate - QUIT");
258 						pexit(ERRS);
259 					}
260 					if (c == '(' && (c = readch()) == '*') {
261 						warning();
262 						yyset();
263 						yerror("(* in a (* ... *) comment");
264 					}
265 					if (c == '*') {
266 						if ((c = readch()) != ')')
267 							continue;
268 						c = readch();
269 						goto next;
270 					}
271 					c = readch();
272 				}
273 #endif
274 			}
275 			yysavc = c;
276 			c = '(';
277 		case ';':
278 		case ',':
279 		case ':':
280 		case '=':
281 		case '*':
282 		case '+':
283 		case '/':
284 		case '-':
285 		case ')':
286 		case '[':
287 		case ']':
288 		case '<':
289 		case '>':
290 		case '^':
291 			return (c);
292 		case '~':
293 		case '|':
294 		case '&':
295 			if ( opt('s') ) {
296 			    yyset();
297 			    standard();
298 			    yerror("%c is non-standard", (char *) c);
299 			}
300 			return c;
301 		default:
302 			switch (c) {
303 				case YDOTDOT:
304 					return (c);
305 				case '\n':
306 					c = readch();
307 #ifdef PXP
308 					yytokcnt++;
309 #endif
310 					goto next;
311 				case '\f':
312 					c = readch();
313 					goto next;
314 			}
315 			if (c <= 0)
316 				return (YEOF);
317 illch:
318 			do
319 				yysavc = readch();
320 			while (yysavc == c);
321 			yylval = c;
322 			return (YILLCH);
323 	}
324 }
325 
326 yyset()
327 {
328 
329 	yyecol = yycol;
330 	yyeline = yyline;
331 	yyefile = filename;
332 	yyseekp = yylinpt;
333 }
334 
335 /*
336  * Setuflg trims the current
337  * input line to at most 72 chars
338  * for the u option.
339  */
340 setuflg()
341 {
342 
343 	if (charbuf[71] != '\n') {
344 		charbuf[72] = '\n';
345 		charbuf[73] = 0;
346 	}
347 }
348