xref: /inferno-os/lib/yaccpar (revision 46439007cf417cbd9ac8049bb4122c890097a0fa)
1
2YYSys: module
3{
4	FD: adt
5	{
6		fd:	int;
7	};
8	fildes:		fn(fd: int): ref FD;
9	fprint:		fn(fd: ref FD, s: string, *): int;
10};
11
12yysys: YYSys;
13yystderr: ref YYSys->FD;
14
15YYFLAG: con -1000;
16
17# parser for yacc output
18
19yytokname(yyc: int): string
20{
21	if(yyc > 0 && yyc <= len yytoknames && yytoknames[yyc-1] != nil)
22		return yytoknames[yyc-1];
23	return "<"+string yyc+">";
24}
25
26yystatname(yys: int): string
27{
28	if(yys >= 0 && yys < len yystates && yystates[yys] != nil)
29		return yystates[yys];
30	return "<"+string yys+">\n";
31}
32
33yylex1(yylex: ref YYLEX): int
34{
35	c : int;
36	yychar := yylex.lex();
37	if(yychar <= 0)
38		c = yytok1[0];
39	else if(yychar < len yytok1)
40		c = yytok1[yychar];
41	else if(yychar >= YYPRIVATE && yychar < YYPRIVATE+len yytok2)
42		c = yytok2[yychar-YYPRIVATE];
43	else{
44		n := len yytok3;
45		c = 0;
46		for(i := 0; i < n; i+=2) {
47			if(yytok3[i+0] == yychar) {
48				c = yytok3[i+1];
49				break;
50			}
51		}
52		if(c == 0)
53			c = yytok2[1];	# unknown char
54	}
55	if(yydebug >= 3)
56		yysys->fprint(yystderr, "lex %.4ux %s\n", yychar, yytokname(c));
57	return c;
58}
59
60YYS: adt
61{
62	yyv: YYSTYPE;
63	yys: int;
64};
65
66yyparse(yylex: ref YYLEX): int
67{
68	if(yydebug >= 1 && yysys == nil) {
69		yysys = load YYSys "$Sys";
70		yystderr = yysys->fildes(2);
71	}
72
73	yys := array[YYMAXDEPTH] of YYS;
74
75	yyval: YYSTYPE;
76	yystate := 0;
77	yychar := -1;
78	yynerrs := 0;		# number of errors
79	yyerrflag := 0;		# error recovery flag
80	yyp := -1;
81	yyn := 0;
82
83yystack:
84	for(;;){
85		# put a state and value onto the stack
86		if(yydebug >= 4)
87			yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
88
89		yyp++;
90		if(yyp >= len yys)
91			yys = (array[len yys * 2] of YYS)[0:] = yys;
92		yys[yyp].yys = yystate;
93		yys[yyp].yyv = yyval;
94
95		for(;;){
96			yyn = yypact[yystate];
97			if(yyn > YYFLAG) {	# simple state
98				if(yychar < 0)
99					yychar = yylex1(yylex);
100				yyn += yychar;
101				if(yyn >= 0 && yyn < YYLAST) {
102					yyn = yyact[yyn];
103					if(yychk[yyn] == yychar) { # valid shift
104						yychar = -1;
105						yyp++;
106						if(yyp >= len yys)
107							yys = (array[len yys * 2] of YYS)[0:] = yys;
108						yystate = yyn;
109						yys[yyp].yys = yystate;
110						yys[yyp].yyv = yylex.lval;
111						if(yyerrflag > 0)
112							yyerrflag--;
113						if(yydebug >= 4)
114							yysys->fprint(yystderr, "char %s in %s", yytokname(yychar), yystatname(yystate));
115						continue;
116					}
117				}
118			}
119
120			# default state action
121			yyn = yydef[yystate];
122			if(yyn == -2) {
123				if(yychar < 0)
124					yychar = yylex1(yylex);
125
126				# look through exception table
127				for(yyxi:=0;; yyxi+=2)
128					if(yyexca[yyxi] == -1 && yyexca[yyxi+1] == yystate)
129						break;
130				for(yyxi += 2;; yyxi += 2) {
131					yyn = yyexca[yyxi];
132					if(yyn < 0 || yyn == yychar)
133						break;
134				}
135				yyn = yyexca[yyxi+1];
136				if(yyn < 0){
137					yyn = 0;
138					break yystack;
139				}
140			}
141
142			if(yyn != 0)
143				break;
144
145			# error ... attempt to resume parsing
146			if(yyerrflag == 0) { # brand new error
147				yylex.error("syntax error");
148				yynerrs++;
149				if(yydebug >= 1) {
150					yysys->fprint(yystderr, "%s", yystatname(yystate));
151					yysys->fprint(yystderr, "saw %s\n", yytokname(yychar));
152				}
153			}
154
155			if(yyerrflag != 3) { # incompletely recovered error ... try again
156				yyerrflag = 3;
157
158				# find a state where "error" is a legal shift action
159				while(yyp >= 0) {
160					yyn = yypact[yys[yyp].yys] + YYERRCODE;
161					if(yyn >= 0 && yyn < YYLAST) {
162						yystate = yyact[yyn];  # simulate a shift of "error"
163						if(yychk[yystate] == YYERRCODE)
164							continue yystack;
165					}
166
167					# the current yyp has no shift onn "error", pop stack
168					if(yydebug >= 2)
169						yysys->fprint(yystderr, "error recovery pops state %d, uncovers %d\n",
170							yys[yyp].yys, yys[yyp-1].yys );
171					yyp--;
172				}
173				# there is no state on the stack with an error shift ... abort
174				yyn = 1;
175				break yystack;
176			}
177
178			# no shift yet; clobber input char
179			if(yydebug >= 2)
180				yysys->fprint(yystderr, "error recovery discards %s\n", yytokname(yychar));
181			if(yychar == YYEOFCODE) {
182				yyn = 1;
183				break yystack;
184			}
185			yychar = -1;
186			# try again in the same state
187		}
188
189		# reduction by production yyn
190		if(yydebug >= 2)
191			yysys->fprint(yystderr, "reduce %d in:\n\t%s", yyn, yystatname(yystate));
192
193		yypt := yyp;
194		yyp -= yyr2[yyn];
195#		yyval = yys[yyp+1].yyv;
196		yym := yyn;
197
198		# consult goto table to find next state
199		yyn = yyr1[yyn];
200		yyg := yypgo[yyn];
201		yyj := yyg + yys[yyp].yys + 1;
202
203		if(yyj >= YYLAST || yychk[yystate=yyact[yyj]] != -yyn)
204			yystate = yyact[yyg];
205		case yym {
206			$A
207		}
208	}
209
210	return yyn;
211}
212