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