0 | |
-module(sbeezg_parser).
|
1 | |
-define(THIS_MODULE, sbeezg_parser).
|
2 | |
-export([parse/1, parse_and_scan/1, format_error/1]).
|
3 | |
|
4 | |
new_name({name,{atom,Line,Name}}=A) ->
|
5 | |
case get(A) of
|
6 | |
defn ->
|
7 | |
return_error(0, io_lib:format("Name '~w' already defined", [Name]));
|
8 | |
_ ->
|
9 | |
put(A, defn)
|
10 | |
end.
|
11 | |
|
12 | |
existing_name({name,{atom,Line,Name}}=A) ->
|
13 | |
case get(A) of
|
14 | |
undefined ->
|
15 | |
return_error(0, io_lib:format("Name '~w' is not yet defined", [Name]));
|
16 | |
_ ->
|
17 | |
ok
|
18 | |
end.
|
19 | |
|
20 | |
%%% END of sbeezg_parser.yrl %%%
|
21 | |
|
22 | |
%% ``The contents of this file are subject to the Erlang Public License,
|
23 | |
%% Version 1.1, (the "License"); you may not use this file except in
|
24 | |
%% compliance with the License. You should have received a copy of the
|
25 | |
%% Erlang Public License along with this software. If not, it can be
|
26 | |
%% retrieved via the world wide web at http://www.erlang.org/.
|
27 | |
%%
|
28 | |
%% Software distributed under the License is distributed on an "AS IS"
|
29 | |
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
|
30 | |
%% the License for the specific language governing rights and limitations
|
31 | |
%% under the License.
|
32 | |
%%
|
33 | |
%% The Initial Developer of the Original Code is Ericsson Utvecklings AB.
|
34 | |
%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings
|
35 | |
%% AB. All Rights Reserved.''
|
36 | |
%%
|
37 | |
%% $Id$
|
38 | |
%%
|
39 | |
|
40 | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
41 | |
% The parser generator will insert appropriate declarations before this line.%
|
42 | |
|
43 | |
parse(Tokens) ->
|
44 | |
case catch yeccpars1(Tokens, false, 0, [], []) of
|
45 | |
error ->
|
46 | |
Errorline =
|
47 | |
if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
|
48 | |
{error,
|
49 | |
{Errorline, ?THIS_MODULE, "syntax error at or after this line."}};
|
50 | |
Other ->
|
51 | |
Other
|
52 | |
end.
|
53 | |
|
54 | |
parse_and_scan({Mod, Fun, Args}) ->
|
55 | |
case apply(Mod, Fun, Args) of
|
56 | |
{eof, _} ->
|
57 | |
{ok, eof};
|
58 | |
{error, Descriptor, _} ->
|
59 | |
{error, Descriptor};
|
60 | |
{ok, Tokens, _} ->
|
61 | |
yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
|
62 | |
end.
|
63 | |
|
64 | |
format_error(Message) ->
|
65 | |
case io_lib:deep_char_list(Message) of
|
66 | |
true ->
|
67 | |
Message;
|
68 | |
_ ->
|
69 | |
io_lib:write(Message)
|
70 | |
end.
|
71 | |
|
72 | |
% To be used in grammar files to throw an error message to the parser toplevel.
|
73 | |
% Doesn't have to be exported!
|
74 | |
return_error(Line, Message) ->
|
75 | |
throw({error, {Line, ?THIS_MODULE, Message}}).
|
76 | |
|
77 | |
|
78 | |
% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
|
79 | |
yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
|
80 | |
yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
|
81 | |
Tokenizer);
|
82 | |
yeccpars1([], {M, F, A}, State, States, Vstack) ->
|
83 | |
case catch apply(M, F, A) of
|
84 | |
{eof, Endline} ->
|
85 | |
{error, {Endline, ?THIS_MODULE, "end_of_file"}};
|
86 | |
{error, Descriptor, Endline} ->
|
87 | |
{error, Descriptor};
|
88 | |
{'EXIT', Reason} ->
|
89 | |
{error, {0, ?THIS_MODULE, Reason}};
|
90 | |
{ok, Tokens, Endline} ->
|
91 | |
case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
|
92 | |
error ->
|
93 | |
Errorline = element(2, hd(Tokens)),
|
94 | |
{error, {Errorline, ?THIS_MODULE,
|
95 | |
"syntax error at or after this line."}};
|
96 | |
Other ->
|
97 | |
Other
|
98 | |
end
|
99 | |
end;
|
100 | |
yeccpars1([], false, State, States, Vstack) ->
|
101 | |
yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
|
102 | |
|
103 | |
% For internal use only.
|
104 | |
yeccerror(Token) ->
|
105 | |
{error,
|
106 | |
{element(2, Token), ?THIS_MODULE,
|
107 | |
["syntax error before: ", yecctoken2string(Token)]}}.
|
108 | |
|
109 | |
yecctoken2string({atom, _, A}) -> io_lib:write(A);
|
110 | |
yecctoken2string({integer,_,N}) -> io_lib:write(N);
|
111 | |
yecctoken2string({float,_,F}) -> io_lib:write(F);
|
112 | |
yecctoken2string({char,_,C}) -> io_lib:write_char(C);
|
113 | |
yecctoken2string({var,_,V}) -> io_lib:format('~s', [V]);
|
114 | |
yecctoken2string({string,_,S}) -> io_lib:write_string(S);
|
115 | |
yecctoken2string({reserved_symbol, _, A}) -> io_lib:format('~w', [A]);
|
116 | |
yecctoken2string({Cat, _, Val}) -> io_lib:format('~w', [Val]);
|
117 | |
|
118 | |
yecctoken2string({'dot', _}) -> io_lib:format('~w', ['.']);
|
119 | |
yecctoken2string({'$end', _}) ->
|
120 | |
[];
|
121 | |
yecctoken2string({Other, _}) when atom(Other) ->
|
122 | |
io_lib:format('~w', [Other]);
|
123 | |
yecctoken2string(Other) ->
|
124 | |
io_lib:write(Other).
|
125 | |
|
126 | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|
127 | |
|
128 | |
|
129 | |
yeccpars2(0, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
130 | |
yeccpars1(__Ts, __Tzr, 3, [0 | __Ss], [__T | __Stack]);
|
131 | |
yeccpars2(0, _, _, _, __T, _, _) ->
|
132 | |
yeccerror(__T);
|
133 | |
yeccpars2(1, '$end', _, __Stack, _, _, _) ->
|
134 | |
{ok, hd(__Stack)};
|
135 | |
yeccpars2(1, _, _, _, __T, _, _) ->
|
136 | |
yeccerror(__T);
|
137 | |
yeccpars2(2, ';', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
138 | |
yeccpars1(__Ts, __Tzr, 27, [2 | __Ss], [__T | __Stack]);
|
139 | |
yeccpars2(2, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
140 | |
__Val = {alist,__1,nil},
|
141 | |
yeccpars2(yeccgoto(alist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
142 | |
yeccpars2(3, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
143 | |
__Val = {name,__1},
|
144 | |
yeccpars2(yeccgoto(name, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
145 | |
yeccpars2(4, '=', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
146 | |
yeccpars1(__Ts, __Tzr, 5, [4 | __Ss], [__T | __Stack]);
|
147 | |
yeccpars2(4, _, _, _, __T, _, _) ->
|
148 | |
yeccerror(__T);
|
149 | |
yeccpars2(5, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
150 | |
yeccpars1(__Ts, __Tzr, 3, [5 | __Ss], [__T | __Stack]);
|
151 | |
yeccpars2(5, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
152 | |
yeccpars1(__Ts, __Tzr, 7, [5 | __Ss], [__T | __Stack]);
|
153 | |
yeccpars2(5, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
154 | |
yeccpars1(__Ts, __Tzr, 6, [5 | __Ss], [__T | __Stack]);
|
155 | |
yeccpars2(5, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
156 | |
yeccpars1(__Ts, __Tzr, 10, [5 | __Ss], [__T | __Stack]);
|
157 | |
yeccpars2(5, _, _, _, __T, _, _) ->
|
158 | |
yeccerror(__T);
|
159 | |
yeccpars2(6, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
160 | |
yeccpars1(__Ts, __Tzr, 26, [6 | __Ss], [__T | __Stack]);
|
161 | |
yeccpars2(6, _, _, _, __T, _, _) ->
|
162 | |
yeccerror(__T);
|
163 | |
yeccpars2(7, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
164 | |
__Val = {lit,__1},
|
165 | |
yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
166 | |
yeccpars2(8, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
167 | |
__Val = begin
|
168 | |
existing_name(__1), __1
|
169 | |
end,
|
170 | |
yeccpars2(yeccgoto(val, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
171 | |
yeccpars2(9, '(', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
172 | |
yeccpars1(__Ts, __Tzr, 20, [9 | __Ss], [__T | __Stack]);
|
173 | |
yeccpars2(9, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
174 | |
__Val = begin
|
175 | |
new_name(__1), {assign,__1,__3}
|
176 | |
end,
|
177 | |
__Nss = lists:nthtail(2, __Ss),
|
178 | |
yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
179 | |
yeccpars2(10, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
180 | |
yeccpars1(__Ts, __Tzr, 3, [10 | __Ss], [__T | __Stack]);
|
181 | |
yeccpars2(10, _, _, _, __T, _, _) ->
|
182 | |
yeccerror(__T);
|
183 | |
yeccpars2(11, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
184 | |
yeccpars1(__Ts, __Tzr, 18, [11 | __Ss], [__T | __Stack]);
|
185 | |
yeccpars2(11, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
186 | |
__Val = begin
|
187 | |
new_name(__1), {nlist,__1,nil}
|
188 | |
end,
|
189 | |
yeccpars2(yeccgoto(nlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
190 | |
yeccpars2(12, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
191 | |
yeccpars1(__Ts, __Tzr, 13, [12 | __Ss], [__T | __Stack]);
|
192 | |
yeccpars2(12, _, _, _, __T, _, _) ->
|
193 | |
yeccerror(__T);
|
194 | |
yeccpars2(13, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
195 | |
yeccpars1(__Ts, __Tzr, 3, [13 | __Ss], [__T | __Stack]);
|
196 | |
yeccpars2(13, _, _, _, __T, _, _) ->
|
197 | |
yeccerror(__T);
|
198 | |
yeccpars2(14, '|', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
199 | |
yeccpars1(__Ts, __Tzr, 15, [14 | __Ss], [__T | __Stack]);
|
200 | |
yeccpars2(14, _, _, _, __T, _, _) ->
|
201 | |
yeccerror(__T);
|
202 | |
yeccpars2(15, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
203 | |
yeccpars1(__Ts, __Tzr, 3, [15 | __Ss], [__T | __Stack]);
|
204 | |
yeccpars2(15, _, _, _, __T, _, _) ->
|
205 | |
yeccerror(__T);
|
206 | |
yeccpars2(16, '}', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
207 | |
yeccpars1(__Ts, __Tzr, 17, [16 | __Ss], [__T | __Stack]);
|
208 | |
yeccpars2(16, _, _, _, __T, _, _) ->
|
209 | |
yeccerror(__T);
|
210 | |
yeccpars2(17, __Cat, __Ss, [__7,__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
211 | |
__Val = {lambda,__2,__4,__6},
|
212 | |
__Nss = lists:nthtail(6, __Ss),
|
213 | |
yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
214 | |
yeccpars2(18, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
215 | |
yeccpars1(__Ts, __Tzr, 3, [18 | __Ss], [__T | __Stack]);
|
216 | |
yeccpars2(18, _, _, _, __T, _, _) ->
|
217 | |
yeccerror(__T);
|
218 | |
yeccpars2(19, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
219 | |
__Val = begin
|
220 | |
new_name(__1), {nlist,__1,__3}
|
221 | |
end,
|
222 | |
__Nss = lists:nthtail(2, __Ss),
|
223 | |
yeccpars2(yeccgoto(nlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
224 | |
yeccpars2(20, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
225 | |
yeccpars1(__Ts, __Tzr, 3, [20 | __Ss], [__T | __Stack]);
|
226 | |
yeccpars2(20, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
227 | |
yeccpars1(__Ts, __Tzr, 7, [20 | __Ss], [__T | __Stack]);
|
228 | |
yeccpars2(20, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
229 | |
yeccpars1(__Ts, __Tzr, 6, [20 | __Ss], [__T | __Stack]);
|
230 | |
yeccpars2(20, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
231 | |
yeccpars1(__Ts, __Tzr, 10, [20 | __Ss], [__T | __Stack]);
|
232 | |
yeccpars2(20, _, _, _, __T, _, _) ->
|
233 | |
yeccerror(__T);
|
234 | |
yeccpars2(21, ',', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
235 | |
yeccpars1(__Ts, __Tzr, 24, [21 | __Ss], [__T | __Stack]);
|
236 | |
yeccpars2(21, __Cat, __Ss, [__1|__Stack], __T, __Ts, __Tzr) ->
|
237 | |
__Val = {vlist,__1,nil},
|
238 | |
yeccpars2(yeccgoto(vlist, hd(__Ss)), __Cat, __Ss, [__Val | __Stack], __T, __Ts, __Tzr);
|
239 | |
yeccpars2(22, ')', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
240 | |
yeccpars1(__Ts, __Tzr, 23, [22 | __Ss], [__T | __Stack]);
|
241 | |
yeccpars2(22, _, _, _, __T, _, _) ->
|
242 | |
yeccerror(__T);
|
243 | |
yeccpars2(23, __Cat, __Ss, [__6,__5,__4,__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
244 | |
__Val = begin
|
245 | |
new_name(__1), {assign,__1,__3,__5}
|
246 | |
end,
|
247 | |
__Nss = lists:nthtail(5, __Ss),
|
248 | |
yeccpars2(yeccgoto(appl, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
249 | |
yeccpars2(24, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
250 | |
yeccpars1(__Ts, __Tzr, 3, [24 | __Ss], [__T | __Stack]);
|
251 | |
yeccpars2(24, integer, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
252 | |
yeccpars1(__Ts, __Tzr, 7, [24 | __Ss], [__T | __Stack]);
|
253 | |
yeccpars2(24, '*', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
254 | |
yeccpars1(__Ts, __Tzr, 6, [24 | __Ss], [__T | __Stack]);
|
255 | |
yeccpars2(24, '{', __Ss, __Stack, __T, __Ts, __Tzr) ->
|
256 | |
yeccpars1(__Ts, __Tzr, 10, [24 | __Ss], [__T | __Stack]);
|
257 | |
yeccpars2(24, _, _, _, __T, _, _) ->
|
258 | |
yeccerror(__T);
|
259 | |
yeccpars2(25, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
260 | |
__Val = {vlist,__1,__3},
|
261 | |
__Nss = lists:nthtail(2, __Ss),
|
262 | |
yeccpars2(yeccgoto(vlist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
263 | |
yeccpars2(26, __Cat, __Ss, [__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
264 | |
__Val = {lit,__2},
|
265 | |
__Nss = lists:nthtail(1, __Ss),
|
266 | |
yeccpars2(yeccgoto(val, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
267 | |
yeccpars2(27, atom, __Ss, __Stack, __T, __Ts, __Tzr) ->
|
268 | |
yeccpars1(__Ts, __Tzr, 3, [27 | __Ss], [__T | __Stack]);
|
269 | |
yeccpars2(27, _, _, _, __T, _, _) ->
|
270 | |
yeccerror(__T);
|
271 | |
yeccpars2(28, __Cat, __Ss, [__3,__2,__1|__Stack], __T, __Ts, __Tzr) ->
|
272 | |
__Val = {alist,__1,__3},
|
273 | |
__Nss = lists:nthtail(2, __Ss),
|
274 | |
yeccpars2(yeccgoto(alist, hd(__Nss)), __Cat, __Nss, [__Val | __Stack], __T, __Ts, __Tzr);
|
275 | |
yeccpars2(__Other, _, _, _, _, _, _) ->
|
276 | |
exit({parser, __Other, missing_state_in_action_table}).
|
277 | |
|
278 | |
yeccgoto(alist, 0) ->
|
279 | |
1;
|
280 | |
yeccgoto(alist, 13) ->
|
281 | |
14;
|
282 | |
yeccgoto(alist, 27) ->
|
283 | |
28;
|
284 | |
yeccgoto(appl, 0) ->
|
285 | |
2;
|
286 | |
yeccgoto(appl, 13) ->
|
287 | |
2;
|
288 | |
yeccgoto(appl, 27) ->
|
289 | |
2;
|
290 | |
yeccgoto(name, 0) ->
|
291 | |
4;
|
292 | |
yeccgoto(name, 5) ->
|
293 | |
8;
|
294 | |
yeccgoto(name, 10) ->
|
295 | |
11;
|
296 | |
yeccgoto(name, 13) ->
|
297 | |
4;
|
298 | |
yeccgoto(name, 15) ->
|
299 | |
16;
|
300 | |
yeccgoto(name, 18) ->
|
301 | |
11;
|
302 | |
yeccgoto(name, 20) ->
|
303 | |
8;
|
304 | |
yeccgoto(name, 24) ->
|
305 | |
8;
|
306 | |
yeccgoto(name, 27) ->
|
307 | |
4;
|
308 | |
yeccgoto(nlist, 10) ->
|
309 | |
12;
|
310 | |
yeccgoto(nlist, 18) ->
|
311 | |
19;
|
312 | |
yeccgoto(val, 5) ->
|
313 | |
9;
|
314 | |
yeccgoto(val, 20) ->
|
315 | |
21;
|
316 | |
yeccgoto(val, 24) ->
|
317 | |
21;
|
318 | |
yeccgoto(vlist, 20) ->
|
319 | |
22;
|
320 | |
yeccgoto(vlist, 24) ->
|
321 | |
25;
|
322 | |
yeccgoto(__Symbol, __State) ->
|
323 | |
exit({__Symbol, __State, missing_in_goto_table}).
|
324 | |
|
325 | |
|