aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjörn Gustavsson <[email protected]>2014-12-03 12:46:49 +0100
committerBjörn Gustavsson <[email protected]>2015-01-12 12:22:57 +0100
commit4247459eded419b9e693cfbfaf8746f4f6f60d2c (patch)
treedbd004fc09bee65de8142d02a90522d16a6e57b6
parentb718f376519c89c60805b26efb54b4c4b5b8b908 (diff)
downloadotp-4247459eded419b9e693cfbfaf8746f4f6f60d2c.tar.gz
otp-4247459eded419b9e693cfbfaf8746f4f6f60d2c.tar.bz2
otp-4247459eded419b9e693cfbfaf8746f4f6f60d2c.zip
asn1ct, asn1ct_parser2: Refactor the upper levels of error handling
Responsibilities for parse error handling were split between asn1ct and asn1ct_parser2 in a confusing way. Let asn1ct_parser2 return structured_error tuples in the same way as the check pass.
-rw-r--r--lib/asn1/src/asn1ct.erl63
-rw-r--r--lib/asn1/src/asn1ct_parser2.erl84
2 files changed, 61 insertions, 86 deletions
diff --git a/lib/asn1/src/asn1ct.erl b/lib/asn1/src/asn1ct.erl
index cd7900f919..a26d63c97d 100644
--- a/lib/asn1/src/asn1ct.erl
+++ b/lib/asn1/src/asn1ct.erl
@@ -167,46 +167,26 @@ set_scan_parse_pass(#st{files=Files}=St) ->
{error,St#st{error=Error}}
end.
-set_scan_parse_pass_1([F|Fs], St) ->
+set_scan_parse_pass_1([F|Fs], #st{file=File}=St) ->
case asn1ct_tok:file(F) of
{error,Error} ->
throw(Error);
Tokens when is_list(Tokens) ->
- case catch asn1ct_parser2:parse(Tokens) of
+ case asn1ct_parser2:parse(File, Tokens) of
{ok,M} ->
[M|set_scan_parse_pass_1(Fs, St)];
- {error,ErrorTerm} ->
- throw(handle_parse_error(ErrorTerm, St))
+ {error,Errors} ->
+ throw(Errors)
end
end;
set_scan_parse_pass_1([], _) -> [].
-parse_pass(#st{code=Tokens}=St) ->
- case catch asn1ct_parser2:parse(Tokens) of
+parse_pass(#st{file=File,code=Tokens}=St) ->
+ case asn1ct_parser2:parse(File, Tokens) of
{ok,M} ->
{ok,St#st{code=M}};
- {error,ErrorTerm} ->
- {error,St#st{error=handle_parse_error(ErrorTerm, St)}}
- end.
-
-handle_parse_error(ErrorTerm, #st{file=File,opts=Opts}) ->
- case ErrorTerm of
- {{Line,_Mod,Message},_TokTup} ->
- if
- is_integer(Line) ->
- BaseName = filename:basename(File),
- error("syntax error at line ~p in module ~s:~n",
- [Line,BaseName], Opts);
- true ->
- error("syntax error in module ~p:~n",
- [File], Opts)
- end,
- print_error_message(Message),
- Message;
- {Line,_Mod,[Message,Token]} ->
- error("syntax error: ~p ~p at line ~p~n",
- [Message,Token,Line], Opts),
- {Line,[Message,Token]}
+ {error,Errors} ->
+ {error,St#st{error=Errors}}
end.
merge_pass(#st{file=Base,code=Code}=St) ->
@@ -1410,33 +1390,6 @@ prepare_bytes(Bytes) -> list_to_binary(Bytes).
vsn() ->
?vsn.
-
-
-print_error_message([got,H|T]) when is_list(H) ->
- io:format(" got:"),
- print_listing(H,"and"),
- print_error_message(T);
-print_error_message([expected,H|T]) when is_list(H) ->
- io:format(" expected one of:"),
- print_listing(H,"or"),
- print_error_message(T);
-print_error_message([H|T]) ->
- io:format(" ~p",[H]),
- print_error_message(T);
-print_error_message([]) ->
- io:format("~n").
-
-print_listing([H1,H2|[]],AndOr) ->
- io:format(" ~p ~s ~p",[H1,AndOr,H2]);
-print_listing([H1,H2|T],AndOr) ->
- io:format(" ~p,",[H1]),
- print_listing([H2|T],AndOr);
-print_listing([H],_AndOr) ->
- io:format(" ~p",[H]);
-print_listing([],_) ->
- ok.
-
-
specialized_decode_prepare(Erule,M,TsAndVs,Options) ->
case lists:member(asn1config,Options) of
true ->
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl
index 65868642e6..d1c0b7feda 100644
--- a/lib/asn1/src/asn1ct_parser2.erl
+++ b/lib/asn1/src/asn1ct_parser2.erl
@@ -20,7 +20,7 @@
%%
-module(asn1ct_parser2).
--export([parse/1]).
+-export([parse/2,format_error/1]).
-include("asn1_records.hrl").
%% Only used internally within this module.
@@ -28,26 +28,29 @@
-record(constraint, {c,e}).
-record(identifier, {pos,val}).
-%% parse all types in module
-parse(Tokens) ->
- case catch parse_ModuleDefinition(Tokens) of
- {'EXIT',Reason} ->
- {error,{{undefined,get(asn1_module),
- [internal,error,'when',parsing,module,definition,Reason]},
- hd(Tokens)}};
- {asn1_error,Reason} ->
- {error,{Reason,hd(Tokens)}};
- {ModuleDefinition,Rest1} ->
- {Types,Rest2} = parse_AssignmentList(Rest1),
- clean_process_dictionary(),
- case Rest2 of
- [{'END',_}|_Rest3] ->
- {ok,ModuleDefinition#module{typeorval = Types}};
- _ ->
- {error,{{get_line(hd(Rest2)),get(asn1_module),
- [got,get_token(hd(Rest2)),expected,'END']},
- hd(Rest2)}}
- end
+parse(File0, Tokens) ->
+ try do_parse(Tokens) of
+ {ok,#module{}}=Result ->
+ Result
+ catch
+ throw:{asn1_error,{Line,_Mod,Message}} ->
+ File = filename:basename(File0),
+ Error = {structured_error,{File,Line},?MODULE,Message},
+ {error,[Error]}
+ after
+ clean_process_dictionary()
+ end.
+
+do_parse(Tokens0) ->
+ {ModuleDefinition,Tokens1} = parse_ModuleDefinition(Tokens0),
+ {Types,Tokens2} = parse_AssignmentList(Tokens1),
+ case Tokens2 of
+ [{'END',_}|_Rest3] ->
+ {ok,ModuleDefinition#module{typeorval=Types}};
+ _ ->
+ throw({asn1_error,
+ {get_line(hd(Tokens2)),get(asn1_module),
+ [got,get_token(hd(Tokens2)),expected,'END']}})
end.
clean_process_dictionary() ->
@@ -57,6 +60,32 @@ clean_process_dictionary() ->
_ = erase(extensiondefault),
ok.
+format_error(List) when is_list(List) ->
+ ["syntax error:"|print_error_message(List)].
+
+print_error_message([got,H|T]) when is_list(H) ->
+ [" got:",print_listing(H, "and"),
+ print_error_message(T)];
+print_error_message([expected,H|T]) when is_list(H) ->
+ [" expected one of:",
+ print_listing(H, "or"),
+ print_error_message(T)];
+print_error_message([H|T]) ->
+ [io_lib:format(" ~p", [H]),
+ print_error_message(T)];
+print_error_message([]) ->
+ "\n".
+
+print_listing([H1,H2|[]], AndOr) ->
+ io_lib:format(" ~p ~s ~p",[H1,AndOr,H2]);
+print_listing([H1,H2|T], AndOr) ->
+ [io_lib:format(" ~p,",[H1])|print_listing([H2|T], AndOr)];
+print_listing([H], _AndOr) ->
+ io_lib:format(" ~p", [H]);
+print_listing([],_) ->
+ [].
+
+
parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->
put(asn1_module,ModuleIdentifier),
{_DefinitiveIdentifier,Rest02} =
@@ -266,16 +295,9 @@ parse_AssignmentList(Tokens= [{'END',_}|_Rest],Acc) ->
{lists:reverse(Acc),Tokens};
parse_AssignmentList(Tokens= [{'$end',_}|_Rest],Acc) ->
{lists:reverse(Acc),Tokens};
-parse_AssignmentList(Tokens,Acc) ->
- case (catch parse_Assignment(Tokens)) of
- {'EXIT',Reason} ->
- exit(Reason);
- {asn1_error,R} ->
-% [H|T] = Tokens,
- throw({error,{R,hd(Tokens)}});
- {Assignment,Rest} ->
- parse_AssignmentList(Rest,[Assignment|Acc])
- end.
+parse_AssignmentList(Tokens0, Acc) ->
+ {Assignment,Tokens} = parse_Assignment(Tokens0),
+ parse_AssignmentList(Tokens, [Assignment|Acc]).
parse_Assignment(Tokens) ->
Flist = [fun parse_TypeAssignment/1,