1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
%%
%% %CopyrightBegin%
%%
%% Copyright Ericsson AB 1997-2009. All Rights Reserved.
%%
%% Licensed under the Apache License, Version 2.0 (the "License");
%% you may not use this file except in compliance with the License.
%% You may obtain a copy of the License at
%%
%% http://www.apache.org/licenses/LICENSE-2.0
%%
%% Unless required by applicable law or agreed to in writing, software
%% distributed under the License is distributed on an "AS IS" BASIS,
%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
%% See the License for the specific language governing permissions and
%% limitations under the License.
%%
%% %CopyrightEnd%
%%
%%
-export([parse/1, parse_and_scan/1, format_error/1]).
-import(lists, [reverse/1]).
-ifdef(JAM).
-compile([{parse_transform,jam_yecc_pj},pj]).
-endif.
-include("icforms.hrl").
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% The parser generator will insert appropriate declarations before this line.%
parse(Tokens) ->
case catch yeccpars1(Tokens, false, 0, [], []) of
error ->
Errorline =
if Tokens == [] -> 0; true -> element(2, hd(Tokens)) end,
{error,
{Errorline, ?MODULE, "syntax error at or after this line."}};
Other ->
Other
end.
parse_and_scan({Mod, Fun, Args}) ->
case apply(Mod, Fun, Args) of
{eof, _} ->
{ok, eof};
{error, Descriptor, _} ->
{error, Descriptor};
{ok, Tokens, _} ->
yeccpars1(Tokens, {Mod, Fun, Args}, 0, [], [])
end.
format_error(Message) ->
case io_lib:deep_char_list(Message) of
true ->
Message;
_ ->
io_lib:write(Message)
end.
% To be used in grammar files to throw an error message to the parser toplevel.
% Doesn't have to be exported!
return_error(Line, Message) ->
throw({error, {Line, ?MODULE, Message}}).
% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!
yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) ->
yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens,
Tokenizer);
yeccpars1([], {M, F, A}, State, States, Vstack) ->
case catch apply(M, F, A) of
{eof, Endline} ->
{error, {Endline, ?MODULE, "end_of_file"}};
{error, Descriptor, _Endline} ->
{error, Descriptor};
{'EXIT', Reason} ->
{error, {0, ?MODULE, Reason}};
{ok, Tokens, _Endline} ->
case catch yeccpars1(Tokens, {M, F, A}, State, States, Vstack) of
error ->
Errorline = element(2, hd(Tokens)),
{error, {Errorline, ?MODULE,
"syntax error at or after this line."}};
Other ->
Other
end
end;
yeccpars1([], false, State, States, Vstack) ->
yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
% For internal use only.
yeccerror(Token) ->
{error,
{element(2, Token), ?MODULE,
["syntax error before: ", yecctoken2string(Token)]}}.
yecctoken2string({atom, _, A}) -> io_lib:write(A);
yecctoken2string({integer,_,N}) -> io_lib:write(N);
yecctoken2string({float,_,F}) -> io_lib:write(F);
yecctoken2string({char,_,C}) -> io_lib:write_char(C);
yecctoken2string({var,_,V}) -> io_lib:format("~s", [V]);
yecctoken2string({string,_,S}) -> io_lib:write_string(S);
yecctoken2string({reserved_symbol, _, A}) -> io_lib:format("~w", [A]);
yecctoken2string({'dot', _}) -> "'.'";
yecctoken2string({'$end', _}) ->
[];
yecctoken2string({Other, _}) when is_atom(Other) ->
io_lib:format("~w", [Other]);
yecctoken2string({_, _, Other}) when is_list(Other) andalso is_number(hd(Other)) ->
Other;
yecctoken2string({_, _, Other}) ->
io_lib:format("~p", [Other]);
yecctoken2string(Other) ->
io_lib:write(Other).
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
|