diff options
author | Björn Gustavsson <[email protected]> | 2014-12-03 12:46:49 +0100 |
---|---|---|
committer | Björn Gustavsson <[email protected]> | 2015-01-12 12:22:57 +0100 |
commit | 4247459eded419b9e693cfbfaf8746f4f6f60d2c (patch) | |
tree | dbd004fc09bee65de8142d02a90522d16a6e57b6 | |
parent | b718f376519c89c60805b26efb54b4c4b5b8b908 (diff) | |
download | otp-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.erl | 63 | ||||
-rw-r--r-- | lib/asn1/src/asn1ct_parser2.erl | 84 |
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, |