diff options
Diffstat (limited to 'lib/asn1/src/asn1ct_parser2.erl')
| -rw-r--r-- | lib/asn1/src/asn1ct_parser2.erl | 2517 | 
1 files changed, 788 insertions, 1729 deletions
diff --git a/lib/asn1/src/asn1ct_parser2.erl b/lib/asn1/src/asn1ct_parser2.erl index 3891fce8d3..488e4af4e0 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,34 @@  -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, Tokens0) -> +    try do_parse(Tokens0) of +	{ok,#module{}}=Result -> +	    Result +    catch +	throw:{asn1_error,Fun} when is_function(Fun, 0) -> +	    handle_parse_error(File0, Fun()); +	throw:{asn1_error,{parse_error,Tokens}} -> +	    handle_parse_error(File0, Tokens) +    after +	clean_process_dictionary() +    end. + +handle_parse_error(File0, [Token|_]) -> +    File = filename:basename(File0), +    Line = get_line(Token), +    Error = {structured_error,{File,Line},?MODULE, +	     {syntax_error,get_token(Token)}}, +    {error,[Error]}. + +do_parse(Tokens0) -> +    {ModuleDefinition,Tokens1} = parse_ModuleDefinition(Tokens0), +    {Types,Tokens2} = parse_AssignmentList(Tokens1), +    case Tokens2 of +	[{'END',_}|_Rest3] -> +	    {ok,ModuleDefinition#module{typeorval=Types}}; +	_  -> +	    parse_error(Tokens2)      end.  clean_process_dictionary() -> @@ -57,6 +65,11 @@ clean_process_dictionary() ->      _ = erase(extensiondefault),      ok. +format_error({syntax_error,Token}) when is_atom(Token) -> +    io_lib:format("syntax error before: '~s'", [Token]); +format_error({syntax_error,Token}) -> +    io_lib:format("syntax error before: '~p'", [Token]). +  parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->      put(asn1_module,ModuleIdentifier),      {_DefinitiveIdentifier,Rest02} =  @@ -70,9 +83,7 @@ parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->  	       [{'DEFINITIONS',_}|Rest03] ->  		   Rest03;  	       _ -> -		   throw({asn1_error,{get_line(hd(Rest02)),get(asn1_module), -				      [got,get_token(hd(Rest02)), -				       expected,'DEFINITIONS']}}) +		   parse_error(Rest02)  	   end,      {TagDefault,Rest2} =   	case Rest of @@ -104,12 +115,11 @@ parse_ModuleDefinition([{typereference,L1,ModuleIdentifier}|Rest0]) ->  		     extensiondefault = ExtensionDefault,  		     exports = Exports,  		     imports = {imports, Imports}}, Rest6}; -	_ -> throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -				[got,get_token(hd(Rest3)),expected,"::= BEGIN"]}}) +	_ -> +	    parse_error(Rest3)      end;  parse_ModuleDefinition(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,typereference]}}). +    parse_error(Tokens).  parse_Exports([{'EXPORTS',_L1},{';',_L2}|Rest]) ->      {{exports,[]},Rest}; @@ -122,8 +132,7 @@ parse_Exports([{'EXPORTS',_L1}|Rest]) ->  	[{';',_}|Rest3] ->      	    {{exports,SymbolList},Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,';']}}) +	    parse_error(Rest2)      end;  parse_Exports(Rest) ->      {{exports,all},Rest}. @@ -137,29 +146,25 @@ parse_SymbolList(Tokens,Acc) ->  	[{',',_L1}|Rest2] ->  	    parse_SymbolList(Rest2,[Symbol|Acc]);  	Rest2  -> -	    {lists:reverse([Symbol|Acc]),Rest2} +	    {lists:reverse(Acc, [Symbol]),Rest2}      end.  parse_Symbol(Tokens) ->      parse_Reference(Tokens).  parse_Reference([{typereference,L1,TrefName},{'{',_L2},{'}',_L3}|Rest]) -> -%    {Tref,Rest};      {tref2Exttref(L1,TrefName),Rest};  parse_Reference([Tref1 = {typereference,_,_},{'.',_},Tref2 = {typereference,_,_},  		 {'{',_L2},{'}',_L3}|Rest]) -> -%    {{Tref1,Tref2},Rest};      {{tref2Exttref(Tref1),tref2Exttref(Tref2)},Rest};  parse_Reference([Tref = {typereference,_L1,_TrefName}|Rest]) ->      {tref2Exttref(Tref),Rest}; -parse_Reference([Vref = {identifier,_L1,_VName},{'{',_L2},{'}',_L3}|Rest]) -> +parse_Reference([#identifier{}=Vref,{'{',_L2},{'}',_L3}|Rest]) ->      {identifier2Extvalueref(Vref),Rest}; -parse_Reference([Vref = {identifier,_L1,_VName}|Rest]) -> +parse_Reference([#identifier{}=Vref|Rest]) ->      {identifier2Extvalueref(Vref),Rest};  parse_Reference(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[typereference,identifier]]}}). +    parse_error(Tokens).  parse_Imports([{'IMPORTS',_L1},{';',_L2}|Rest]) ->      {{imports,[]},Rest}; @@ -168,9 +173,8 @@ parse_Imports([{'IMPORTS',_L1}|Rest]) ->      case Rest2 of  	[{';',_L2}|Rest3] ->  	    {{imports,SymbolsFromModuleList},Rest3}; -	Rest3 -> -	    throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,';']}}) +	_ -> +	    parse_error(Rest2)      end;  parse_Imports(Tokens) ->      {{imports,[]},Tokens}. @@ -180,11 +184,12 @@ parse_SymbolsFromModuleList(Tokens) ->  parse_SymbolsFromModuleList(Tokens,Acc) ->      {SymbolsFromModule,Rest} = parse_SymbolsFromModule(Tokens), -    case (catch parse_SymbolsFromModule(Rest)) of  +    try parse_SymbolsFromModule(Rest) of  	{Sl,_Rest2} when is_record(Sl,'SymbolsFromModule') -> -	    parse_SymbolsFromModuleList(Rest,[SymbolsFromModule|Acc]); -	_  -> -	    {lists:reverse([SymbolsFromModule|Acc]),Rest} +	    parse_SymbolsFromModuleList(Rest, [SymbolsFromModule|Acc]) +    catch +	throw:{asn1_error,_} -> +	    {lists:reverse(Acc, [SymbolsFromModule]),Rest}      end.  parse_SymbolsFromModule(Tokens) -> @@ -198,169 +203,154 @@ parse_SymbolsFromModule(Tokens) ->  	end,      {SymbolList,Rest} = parse_SymbolList(Tokens),      case Rest of -	[{'FROM',_L1},Tref = {typereference,_,Name},Ref={identifier,_L2,_Id},C={',',_}|Rest2] -> -	    NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList), +	[{'FROM',_L1},{typereference,_,Name}=Tref| +	 [#identifier{},{',',_}|_]=Rest2] -> +	    NewSymbolList = lists:map(SetRefModuleName(Name), SymbolList),  	    {#'SymbolsFromModule'{symbols=NewSymbolList, -				  module=tref2Exttref(Tref)},[Ref,C|Rest2]}; +				  module=tref2Exttref(Tref)},Rest2};  	%% This a special case when there is only one Symbol imported  	%% from the next module. No other way to distinguish Ref from  	%% a part of the GlobalModuleReference of Name. -	[{'FROM',_L1},Tref = {typereference,_,Name},Ref = {identifier,_L2,_Id},From = {'FROM',_}|Rest2] -> -	    NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList), +	[{'FROM',_L1},{typereference,_,Name}=Tref| +	 [#identifier{},{'FROM',_}|_]=Rest2] -> +	    NewSymbolList = lists:map(SetRefModuleName(Name), SymbolList),  	    {#'SymbolsFromModule'{symbols=NewSymbolList, -				  module=tref2Exttref(Tref)},[Ref,From|Rest2]}; -	[{'FROM',_L1},Tref = {typereference,_,Name},{identifier,_L2,_Id}|Rest2] -> -	    NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList), +				  module=tref2Exttref(Tref)},Rest2}; +	[{'FROM',_L1},{typereference,_,Name}=Tref,#identifier{}|Rest2] -> +	    NewSymbolList = lists:map(SetRefModuleName(Name), SymbolList),  	    {#'SymbolsFromModule'{symbols=NewSymbolList,  				  module=tref2Exttref(Tref)},Rest2};  -	[{'FROM',_L1},Tref = {typereference,_,Name},Brace = {'{',_}|Rest2] -> -	    {_ObjIdVal,Rest3} = parse_ObjectIdentifierValue([Brace|Rest2]), % value not used yet, fix me -	    NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList), +	[{'FROM',_L1},{typereference,_,Name}=Tref|[{'{',_}|_]=Rest2] -> +	    {_ObjIdVal,Rest3} = parse_ObjectIdentifierValue(Rest2), % value not used yet, fix me +	    NewSymbolList = lists:map(SetRefModuleName(Name), SymbolList),  	    {#'SymbolsFromModule'{symbols=NewSymbolList,  				  module=tref2Exttref(Tref)},Rest3};  -	[{'FROM',_L1},Tref = {typereference,_,Name}|Rest2] -> -	    NewSymbolList = lists:map(SetRefModuleName(Name),SymbolList), +	[{'FROM',_L1},{typereference,_,Name}=Tref|Rest2] -> +	    NewSymbolList = lists:map(SetRefModuleName(Name), SymbolList),  	    {#'SymbolsFromModule'{symbols=NewSymbolList,  				  module=tref2Exttref(Tref)},Rest2};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected, -				['FROM typerefernece identifier ,', -				 'FROM typereference identifier', -				 'FROM typereference {', -				 'FROM typereference']]}}) +	    parse_error(Rest)      end.  parse_ObjectIdentifierValue([{'{',_}|Rest]) ->      parse_ObjectIdentifierValue(Rest,[]). -parse_ObjectIdentifierValue([{number,_,Num}|Rest],Acc) -> +parse_ObjectIdentifierValue([{number,_,Num}|Rest], Acc) ->      parse_ObjectIdentifierValue(Rest,[Num|Acc]); -parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {number,_,Num}, {')',_}|Rest],Acc) -> +parse_ObjectIdentifierValue([#identifier{val=Id},{'(',_},{number,_,Num},{')',_}|Rest], Acc) ->      parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Num}|Acc]); -parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {identifier,_,Id2}, {')',_}|Rest],Acc) -> +parse_ObjectIdentifierValue([#identifier{val=Id},{'(',_},#identifier{val=Id2},{')',_}|Rest], Acc) ->      parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,Id2}|Acc]); -parse_ObjectIdentifierValue([{identifier,_,Id},{'(',_}, {typereference,_,Tref},{'.',_},{identifier,_,Id2}, {')',_}|Rest],Acc) -> -    parse_ObjectIdentifierValue(Rest,[{'NamedNumber',Id,{'ExternalValue',Tref,Id2}}|Acc]); -parse_ObjectIdentifierValue([Id = {identifier,_,_}|Rest],Acc) -> -    parse_ObjectIdentifierValue(Rest,[identifier2Extvalueref(Id)|Acc]); -parse_ObjectIdentifierValue([{'}',_}|Rest],Acc) -> +parse_ObjectIdentifierValue([#identifier{val=Id},{'(',_},{typereference,_,Tref},{'.',_},#identifier{val=Id2}, {')',_}|Rest], Acc) -> +    parse_ObjectIdentifierValue(Rest, [{'NamedNumber',Id,{'ExternalValue',Tref,Id2}}|Acc]); +parse_ObjectIdentifierValue([#identifier{}=Id|Rest], Acc) -> +    parse_ObjectIdentifierValue(Rest, [identifier2Extvalueref(Id)|Acc]); +parse_ObjectIdentifierValue([{'}',_}|Rest], Acc) ->      {lists:reverse(Acc),Rest}; -parse_ObjectIdentifierValue([H|_T],_Acc) -> -    throw({asn1_error,{get_line(H),get(asn1_module), -		       [got,get_token(H),expected, -			['{ some of the following }',number,'identifier ( number )', -			 'identifier ( identifier )', -			 'identifier ( typereference.identifier)',identifier]]}}). +parse_ObjectIdentifierValue(Tokens, _Acc) -> +    parse_error(Tokens). -parse_AssignmentList(Tokens = [{'END',_}|_Rest]) -> -    {[],Tokens}; -parse_AssignmentList(Tokens = [{'$end',_}|_Rest]) -> -    {[],Tokens};  parse_AssignmentList(Tokens) -> -    parse_AssignmentList(Tokens,[]). +    parse_AssignmentList(Tokens, []). -parse_AssignmentList(Tokens= [{'END',_}|_Rest],Acc) -> +parse_AssignmentList([{'END',_}|_]=Tokens, Acc) ->      {lists:reverse(Acc),Tokens}; -parse_AssignmentList(Tokens= [{'$end',_}|_Rest],Acc) -> +parse_AssignmentList([{'$end',_}|_]=Tokens, 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_Assignment(Tokens) -> -    Flist = [fun parse_TypeAssignment/1, -	     fun parse_ValueAssignment/1, -	     fun parse_ObjectClassAssignment/1, -	     fun parse_ObjectAssignment/1, -	     fun parse_ObjectSetAssignment/1, -	     fun parse_ParameterizedAssignment/1, +parse_AssignmentList(Tokens0, Acc) -> +    {Assignment,Tokens} = parse_Assignment(Tokens0), +    parse_AssignmentList(Tokens, [Assignment|Acc]). + +parse_Assignment([{typereference,L1,Name},{'::=',_}|Tokens0]) -> +    %% 1) Type ::= TypeDefinition +    %% 2) CLASS-NAME ::= CLASS {...} +    Flist = [{type,fun parse_Type/1}, +	     {class,fun parse_ObjectClass/1}], +    case parse_or_tag(Tokens0, Flist) of +	{{type,Type},Tokens} -> +	    %% TypeAssignment +	    {#typedef{pos=L1,name=Name,typespec=Type},Tokens}; +	{{class,Type},Tokens} -> +	    %% ObjectClassAssignment +	    {#classdef{pos=L1,name=Name,module=resolve_module(Type), +		       typespec=Type},Tokens} +    end; +parse_Assignment([{typereference,_,_},{'{',_}|_]=Tokens) -> +    %% 1) Type{...} ::= ... +    %% 2) ValueSet{...} Type ::= ... +    %%    ObjectSet{...} CLASS-NAME ::= CLASS {...} +    %% 3) CLASS-NAME{...} ::= CLASS {...} +    %% A parameterized value set and and a parameterized object set +    %% cannot be distinguished from each other without type information. +    Flist = [fun parse_ParameterizedTypeAssignment/1, +	     fun parse_ParameterizedValueSetTypeAssignment/1, +	     fun parse_ParameterizedObjectClassAssignment/1], +    parse_or(Tokens, Flist); +parse_Assignment([{typereference,_,_}|_]=Tokens) -> +    %% 1) ObjectSet CLASS-NAME ::= ... +    %% 2) ValueSet Type ::= ... +    Flist = [fun parse_ObjectSetAssignment/1,  	     fun parse_ValueSetTypeAssignment/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	{asn1_assignment_error,Reason} -> -	    throw({asn1_error,Reason}); -	Result -> -	    Result -    end. - +    parse_or(Tokens, Flist); +parse_Assignment([#identifier{},{'{',_}|_]=Tokens) -> +    %% 1) value{...} Type ::= ... +    %% 2) object{...} CLASS-NAME ::= ... +    Flist = [fun parse_ParameterizedValueAssignment/1, +	     fun parse_ParameterizedObjectAssignment/1], +    parse_or(Tokens, Flist); +parse_Assignment([#identifier{}|_]=Tokens) -> +    %% 1) value Type ::= ... +    %% 2) object CLASS-NAME ::= ... +    Flist = [fun parse_ValueAssignment/1, +	     fun parse_ObjectAssignment/1], +    parse_or(Tokens, Flist); +parse_Assignment(Tokens) -> +    parse_error(Tokens).  parse_or(Tokens,Flist) ->  	parse_or(Tokens,Flist,[]). -parse_or(_Tokens,[],ErrList) -> -    case ErrList of -	[] -> -	    throw({asn1_error,{parse_or,ErrList}}); -	L when is_list(L) -> -	    %% chose to throw 1) the error with the highest line no, -	    %% 2) the last error which is not a asn1_assignment_error or -	    %% 3) the last error. -	    throw(prioritize_error(ErrList)) +parse_or(Tokens, [Fun|Funs], ErrList) when is_function(Fun, 1) -> +    try Fun(Tokens) of +	{_,Rest}=Result when is_list(Rest) -> +	    Result +    catch +	throw:{asn1_error,Error} -> +	    parse_or(Tokens, Funs, [Error|ErrList])      end; -parse_or(Tokens,[Fun|Frest],ErrList) -> -    case (catch Fun(Tokens)) of -	Exit = {'EXIT',_Reason} -> -	    parse_or(Tokens,Frest,[Exit|ErrList]); -	AsnErr = {asn1_error,_} -> -	    parse_or(Tokens,Frest,[AsnErr|ErrList]); -	AsnAssErr = {asn1_assignment_error,_} -> -	    parse_or(Tokens,Frest,[AsnAssErr|ErrList]); -	Result = {_,L} when is_list(L) -> -	    Result; -	Error  -> -	    parse_or(Tokens,Frest,[Error|ErrList]) -    end. - -parse_or_tag(Tokens,Flist) -> -	parse_or_tag(Tokens,Flist,[]). - -parse_or_tag(_Tokens,[],ErrList) -> -    case ErrList of -	[] -> -	    throw({asn1_error,{parse_or_tag,ErrList}}); -	L when is_list(L) -> -	    %% chose to throw 1) the error with the highest line no, -	    %% 2) the last error which is not a asn1_assignment_error or -	    %% 3) the last error. -	    throw(prioritize_error(ErrList)) +parse_or(_Tokens, [], ErrList) -> +    throw({asn1_error,fun() -> prioritize_error(ErrList) end}). + +parse_or_tag(Tokens, Flist) -> +    parse_or_tag(Tokens, Flist, []). + +parse_or_tag(Tokens, [{Tag,Fun}|Funs], ErrList) when is_function(Fun, 1) -> +    try Fun(Tokens) of +	{Parsed,Rest} when is_list(Rest) -> +	    {{Tag,Parsed},Rest} +    catch +	throw:{asn1_error,Error} -> +	    parse_or_tag(Tokens, Funs, [Error|ErrList])      end; -parse_or_tag(Tokens,[{Tag,Fun}|Frest],ErrList) when is_function(Fun) -> -    case (catch Fun(Tokens)) of -	Exit = {'EXIT',_Reason} -> -	    parse_or_tag(Tokens,Frest,[Exit|ErrList]); -	AsnErr = {asn1_error,_} -> -	    parse_or_tag(Tokens,Frest,[AsnErr|ErrList]); -	AsnAssErr = {asn1_assignment_error,_} -> -	    parse_or_tag(Tokens,Frest,[AsnAssErr|ErrList]); -	{ParseRes,Rest} when is_list(Rest) -> -	    {{Tag,ParseRes},Rest}; -	Error  -> -	    parse_or_tag(Tokens,Frest,[Error|ErrList]) -    end. +parse_or_tag(_Tokens, [], ErrList) -> +    throw({asn1_error,fun() -> prioritize_error(ErrList) end}). + +prioritize_error(Errors0) -> +    Errors1 = prioritize_error_1(Errors0), +    Errors2 = [{length(L),L} || L <- Errors1], +    Errors = lists:sort(Errors2), +    [Res|_] = [L || {_,L} <- Errors], +    Res. + +prioritize_error_1([F|T]) when is_function(F, 0) -> +    [F()|prioritize_error_1(T)]; +prioritize_error_1([{parse_error,Tokens}|T]) -> +    [Tokens|prioritize_error_1(T)]; +prioritize_error_1([]) -> +    []. -parse_TypeAssignment([{typereference,L1,Tref},{'::=',_}|Rest]) ->	 -    {Type,Rest2} = parse_Type(Rest), -    {#typedef{pos=L1,name=Tref,typespec=Type},Rest2}; -parse_TypeAssignment([H1,H2|_Rest]) -> -    throw({asn1_assignment_error,{get_line(H1),get(asn1_module), -				  [got,[get_token(H1),get_token(H2)], expected, -				   typereference,'::=']}}); -parse_TypeAssignment([H|_T]) -> -    throw({asn1_assignment_error,{get_line(H),get(asn1_module), -				  [got,get_token(H),expected, -				   typereference]}}).  %% parse_Type(Tokens) -> Ret  %% @@ -370,9 +360,8 @@ parse_TypeAssignment([H|_T]) ->  %%  parse_Type(Tokens) ->      {Tag,Rest3} = case Tokens of -		      [Lbr= {'[',_}|Rest] -> -			  parse_Tag([Lbr|Rest]); -		      Rest-> {[],Rest} +		      [{'[',_}|_] -> parse_Tag(Tokens); +		      _ -> {[],Tokens}  		  end,      {Tag2,Rest4} = case Rest3 of  		       [{'IMPLICIT',_}|Rest31] when is_record(Tag,tag)-> @@ -384,31 +373,17 @@ parse_Type(Tokens) ->  		       Rest31 ->  			   {Tag,Rest31}  		   end, -    Flist = [fun parse_BuiltinType/1,fun parse_ReferencedType/1,fun parse_TypeWithConstraint/1], -    {Type,Rest5} = case (catch parse_or(Rest4,Flist)) of -		      {'EXIT',Reason} -> -			  exit(Reason); -			AsnErr = {asn1_error,_Reason} -> -			 throw(AsnErr); -		      Result -> -			  Result -		  end, -    case hd(Rest5) of -	{'(',_} -> +    Flist = [fun parse_BuiltinType/1, +	     fun parse_ReferencedType/1, +	     fun parse_TypeWithConstraint/1], +    {Type,Rest5} = parse_or(Rest4, Flist), +    case Rest5 of +	[{'(',_}|_] ->  	    {Constraints,Rest6} = parse_Constraints(Rest5), -	    if is_record(Type,type) -> -		    {Type#type{constraint=merge_constraints(Constraints), -			       tag=Tag2},Rest6}; -	       true -> -		    {#type{def=Type,constraint=merge_constraints(Constraints), -			   tag=Tag2},Rest6} -	    end; -	_ -> -	    if is_record(Type,type) -> -		    {Type#type{tag=Tag2},Rest5}; -	       true -> -		    {#type{def=Type,tag=Tag2},Rest5} -	    end +	    {Type#type{tag=Tag2, +		       constraint=merge_constraints(Constraints)},Rest6}; +	[_|_] -> +	    {Type#type{tag=Tag2},Rest5}      end.  parse_BuiltinType([{'BIT',_},{'STRING',_}|Rest]) -> @@ -419,11 +394,10 @@ parse_BuiltinType([{'BIT',_},{'STRING',_}|Rest]) ->  		[{'}',_}|Rest4] ->  		    {#type{def={'BIT STRING',NamedNumberList}},Rest4};  		_ -> -		    throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -				       [got,get_token(hd(Rest3)),expected,'}']}}) +		    parse_error(Rest3)  	    end;  	 _ -> -	    {{'BIT STRING',[]},Rest} +	    {#type{def={'BIT STRING',[]}},Rest}      end;  parse_BuiltinType([{'BOOLEAN',_}|Rest]) ->      {#type{def='BOOLEAN'},Rest}; @@ -435,41 +409,33 @@ parse_BuiltinType([{'CHARACTER',_},{'STRING',_}|Rest]) ->      {#type{def='CHARACTER STRING'},Rest};  parse_BuiltinType([{'CHOICE',_},{'{',_}|Rest]) -> -    {AlternativeTypeLists,Rest2} = parse_AlternativeTypeLists(Rest), -    AlternativeTypeLists1 = -	lists:filter(fun(#'ExtensionAdditionGroup'{}) -> false; -			('ExtensionAdditionGroupEnd') -> false; -			(_) -> true -		     end,AlternativeTypeLists), +    {L0,Rest2} = parse_AlternativeTypeLists(Rest),      case Rest2 of  	[{'}',_}|Rest3] -> -	    AlternativeTypeLists2 = -		case {[Ext||Ext = #'EXTENSIONMARK'{} <- AlternativeTypeLists1], -		      get(extensiondefault)} of -		    {[],'IMPLIED'} ->  AlternativeTypeLists1 ++ [#'EXTENSIONMARK'{}]; -		    _ -> AlternativeTypeLists1 +	    NeedExt = not lists:keymember('EXTENSIONMARK', 1, L0) andalso +		get(extensiondefault) =:= 'IMPLIED', +	    L = case NeedExt of +		    true -> +			L0 ++ [#'EXTENSIONMARK'{}]; +		    false -> +			L0  		end, - -	    {#type{def={'CHOICE',AlternativeTypeLists2}},Rest3}; +	    {#type{def={'CHOICE',L}},Rest3};  	_  -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end;  parse_BuiltinType([{'EMBEDDED',_},{'PDV',_}|Rest]) ->      {#type{def='EMBEDDED PDV'},Rest};  parse_BuiltinType([{'ENUMERATED',_},{'{',_}|Rest]) -> -    {Enumerations,Rest2} = parse_Enumerations(Rest,get(extensiondefault)), +    {Enumerations,Rest2} = parse_Enumerations(Rest),      case Rest2 of  	[{'}',_}|Rest3] ->  	    {#type{def={'ENUMERATED',Enumerations}},Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end;  parse_BuiltinType([{'EXTERNAL',_}|Rest]) ->      {#type{def='EXTERNAL'},Rest}; - -% InstanceOfType  parse_BuiltinType([{'INSTANCE',_},{'OF',_}|Rest]) ->      {DefinedObjectClass,Rest2} = parse_DefinedObjectClass(Rest),      case Rest2 of @@ -480,9 +446,6 @@ parse_BuiltinType([{'INSTANCE',_},{'OF',_}|Rest]) ->  	_ ->  	    {#type{def={'INSTANCE OF',DefinedObjectClass,[]}},Rest2}      end; - -% parse_BuiltinType(Tokens) -> -      parse_BuiltinType([{'INTEGER',_}|Rest]) ->      case Rest of   	[{'{',_}|Rest2] -> @@ -491,17 +454,13 @@ parse_BuiltinType([{'INTEGER',_}|Rest]) ->  		[{'}',_}|Rest4] ->  		    {#type{def={'INTEGER',NamedNumberList}},Rest4};  		_ -> -		    throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -				       [got,get_token(hd(Rest3)),expected,'}']}}) +		    parse_error(Rest3)  	    end;  	 _ ->  	    {#type{def='INTEGER'},Rest}      end;  parse_BuiltinType([{'NULL',_}|Rest]) ->      {#type{def='NULL'},Rest}; - -% ObjectClassFieldType fix me later -  parse_BuiltinType([{'OBJECT',_},{'IDENTIFIER',_}|Rest]) ->      {#type{def='OBJECT IDENTIFIER'},Rest};  parse_BuiltinType([{'OCTET',_},{'STRING',_}|Rest]) -> @@ -529,18 +488,14 @@ parse_BuiltinType([{'SEQUENCE',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->  		parse_ComponentTypeLists2(Rest2,[#'EXTENSIONMARK'{pos=Line}]),  	    case Rest3 of  		[{'}',_}|Rest4] -> -	    {#type{def=#'SEQUENCE'{components=ComponentTypeLists}},Rest4}; +		    {#type{def=#'SEQUENCE'{components=ComponentTypeLists}},Rest4};  		_  -> -		    throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,'}']}}) +		    parse_error(Rest3)  	    end -% 	_ -> % Seq case 4,17-19,23-26 will fail here -% 	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -% 			       [got,get_token(hd(Rest2)),expected,'}']}})      end;  parse_BuiltinType([{'SEQUENCE',_},{'{',_}|Rest]) ->      {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest), -    case Rest2  of +    case Rest2 of  	[{'}',_}|Rest3] ->  	    ComponentTypeLists2 =  		case {[Ext||Ext = #'EXTENSIONMARK'{} <- ComponentTypeLists], @@ -551,25 +506,19 @@ parse_BuiltinType([{'SEQUENCE',_},{'{',_}|Rest]) ->  	    {#type{def=#'SEQUENCE'{components = ComponentTypeLists2}},  	     Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end; - -parse_BuiltinType([{'SEQUENCE',_},{'OF',_},Id={identifier,_,_},Lt={'<',_}|Rest]) -> -%% TODO: take care of the identifier for something useful -    {Type,Rest2} = parse_SelectionType([Id,Lt|Rest]), -    {#type{def={'SEQUENCE OF',#type{def=Type,tag=[]}}},Rest2}; - -parse_BuiltinType([{'SEQUENCE',_},{'OF',_},{identifier,_,_} |Rest]) -> +parse_BuiltinType([{'SEQUENCE',_},{'OF',_}| +		   [#identifier{},{'<',_}|_]=Tokens0]) -> +    {Type,Tokens} = parse_SelectionType(Tokens0), +    {#type{def={'SEQUENCE OF',Type}},Tokens}; +parse_BuiltinType([{'SEQUENCE',_},{'OF',_},#identifier{} |Rest]) ->  %% TODO: take care of the identifier for something useful      {Type,Rest2} = parse_Type(Rest),      {#type{def={'SEQUENCE OF',Type}},Rest2}; -  parse_BuiltinType([{'SEQUENCE',_},{'OF',_}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      {#type{def={'SEQUENCE OF',Type}},Rest2}; - -  parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'}',_}|Rest]) ->      {#type{def=#'SET'{components=[#'EXTENSIONMARK'{pos = Line}]}},Rest};  parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) -> @@ -581,12 +530,18 @@ parse_BuiltinType([{'SET',_},{'{',_},{'...',Line},{'!',_}|Rest]) ->  						val = ExceptionIdentification}]}},  	     Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    {ComponentTypeLists,Rest3}= +		parse_ComponentTypeLists2(Rest2,[#'EXTENSIONMARK'{pos=Line}]), +	    case Rest3 of +		[{'}',_}|Rest4] -> +		    {#type{def=#'SET'{components=ComponentTypeLists}},Rest4}; +		_  -> +		    parse_error(Rest3) +	    end      end;  parse_BuiltinType([{'SET',_},{'{',_}|Rest]) ->      {ComponentTypeLists,Rest2} = parse_ComponentTypeLists(Rest), -    case Rest2  of +    case Rest2 of  	[{'}',_}|Rest3] ->  	    ComponentTypeLists2 =  		case {[Ext||Ext = #'EXTENSIONMARK'{} <- ComponentTypeLists], @@ -597,184 +552,128 @@ parse_BuiltinType([{'SET',_},{'{',_}|Rest]) ->  	    {#type{def=#'SET'{components = ComponentTypeLists2}},  	     Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end; - -parse_BuiltinType([{'SET',_},{'OF',_},Id={identifier,_,_},Lt={'<',_}|Rest]) -> -%% TODO: take care of the identifier for something useful -    {Type,Rest2} = parse_SelectionType([Id,Lt|Rest]), -    {#type{def={'SET OF',#type{def=Type,tag=[]}}},Rest2}; - - -parse_BuiltinType([{'SET',_},{'OF',_},{identifier,_,_}|Rest]) -> +parse_BuiltinType([{'SET',_},{'OF',_}| +		   [#identifier{},{'<',_}|_]=Tokens0]) -> +    {Type,Tokens} = parse_SelectionType(Tokens0), +    {#type{def={'SET OF',Type}},Tokens}; +parse_BuiltinType([{'SET',_},{'OF',_},#identifier{}|Rest]) ->  %%TODO: take care of the identifier for something useful      {Type,Rest2} = parse_Type(Rest),      {#type{def={'SET OF',Type}},Rest2}; -  parse_BuiltinType([{'SET',_},{'OF',_}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      {#type{def={'SET OF',Type}},Rest2}; - -%% The so called Useful types  parse_BuiltinType([{'GeneralizedTime',_}|Rest]) ->      {#type{def='GeneralizedTime'},Rest};  parse_BuiltinType([{'UTCTime',_}|Rest]) ->      {#type{def='UTCTime'},Rest};  parse_BuiltinType([{'ObjectDescriptor',_}|Rest]) ->      {#type{def='ObjectDescriptor'},Rest}; - -%% For compatibility with old standard -parse_BuiltinType([{'ANY',_},{'DEFINED',_},{'BY',_},{identifier,_,Id}|Rest]) -> +parse_BuiltinType([{'ANY',_},{'DEFINED',_},{'BY',_},#identifier{val=Id}|Rest]) -> +    %% For compatibility with the old standard.      {#type{def={'ANY_DEFINED_BY',Id}},Rest};  parse_BuiltinType([{'ANY',_}|Rest]) -> +    %% For compatibility with the old standard.      {#type{def='ANY'},Rest}; -  parse_BuiltinType(Tokens) ->      parse_ObjectClassFieldType(Tokens). -%    throw({asn1_error,unhandled_type}). -parse_TypeWithConstraint([{'SEQUENCE',_},Lpar = {'(',_}|Rest]) -> -    {Constraint,Rest2} = parse_Constraint([Lpar|Rest]), +parse_TypeWithConstraint([{'SEQUENCE',_}|[{'(',_}|_]=Rest0]) -> +    {Constraint,Rest2} = parse_Constraint(Rest0),      Rest4 = case Rest2 of -		[{'OF',_}, {identifier,_,_Id}|Rest3] -> +		[{'OF',_},#identifier{}|Rest3] ->  %%% TODO: make some use of the identifier, maybe useful in the XML mapping  		    Rest3;  		[{'OF',_}|Rest3] ->  		    Rest3;  		_ -> -		    throw({asn1_error, -			   {get_line(hd(Rest2)),get(asn1_module), -			    [got,get_token(hd(Rest2)),expected,'OF']}}) +		    parse_error(Rest2)  	    end,      {Type,Rest5} = parse_Type(Rest4),      {#type{def = {'SEQUENCE OF',Type},  	   constraint = merge_constraints([Constraint])},Rest5}; -parse_TypeWithConstraint([{'SEQUENCE',_},{'SIZE',_},Lpar = {'(',_}|Rest]) -> -    {Constraint,Rest2} = parse_Constraint([Lpar|Rest]), +parse_TypeWithConstraint([{'SEQUENCE',_},{'SIZE',_}|[{'(',_}|_]=Rest0]) -> +    {Constraint,Rest2} = parse_Constraint(Rest0),      #constraint{c=C} = Constraint, -    Constraint2 = Constraint#constraint{c={'SizeConstraint',C}}, +    Constraint2 = Constraint#constraint{c={element_set,{'SizeConstraint',C}, +					   none}},      Rest4 = case Rest2 of -		[{'OF',_}, {identifier,_,_Id}|Rest3] -> +		[{'OF',_},#identifier{}|Rest3] ->  %%% TODO: make some use of the identifier, maybe useful in the XML mapping  		    Rest3;  		[{'OF',_}|Rest3] ->  		    Rest3;  		_ -> -		    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -				       [got,get_token(hd(Rest2)),expected,'OF']}}) +		    parse_error(Rest2)  	    end,      {Type,Rest5} = parse_Type(Rest4),      {#type{def = {'SEQUENCE OF',Type}, constraint = merge_constraints([Constraint2])},Rest5}; -parse_TypeWithConstraint([{'SET',_},Lpar = {'(',_}|Rest]) -> -    {Constraint,Rest2} = parse_Constraint([Lpar|Rest]), +parse_TypeWithConstraint([{'SET',_}|[{'(',_}|_]=Rest0]) -> +    {Constraint,Rest2} = parse_Constraint(Rest0),      Rest4 = case Rest2 of -		[{'OF',_}, {identifier,_,_Id}|Rest3] -> +		[{'OF',_},#identifier{}|Rest3] ->  %%% TODO: make some use of the identifier, maybe useful in the XML mapping  		    Rest3;  		[{'OF',_}|Rest3] ->  		    Rest3;  		_ -> -		    throw({asn1_error, -			   {get_line(hd(Rest2)),get(asn1_module), -			    [got,get_token(hd(Rest2)),expected,'OF']}}) +		    parse_error(Rest2)  	    end,      {Type,Rest5} = parse_Type(Rest4),      {#type{def = {'SET OF',Type},  	   constraint = merge_constraints([Constraint])},Rest5}; -parse_TypeWithConstraint([{'SET',_},{'SIZE',_},Lpar = {'(',_}|Rest]) -> -    {Constraint,Rest2} = parse_Constraint([Lpar|Rest]), +parse_TypeWithConstraint([{'SET',_},{'SIZE',_}|[{'(',_}|_]=Rest0]) -> +    {Constraint,Rest2} = parse_Constraint(Rest0),      #constraint{c=C} = Constraint, -    Constraint2 = Constraint#constraint{c={'SizeConstraint',C}}, +    Constraint2 = Constraint#constraint{c={element_set, +					   {'SizeConstraint',C},none}},      Rest4 = case Rest2 of -		[{'OF',_}, {identifier,_,_Id}|Rest3] -> +		[{'OF',_},#identifier{}|Rest3] ->  %%% TODO: make some use of the identifier, maybe useful in the XML mapping  		    Rest3;  		[{'OF',_}|Rest3] ->  		    Rest3;  		_ -> -		    throw({asn1_error, -			   {get_line(hd(Rest2)),get(asn1_module), -			    [got,get_token(hd(Rest2)),expected,'OF']}}) +		    parse_error(Rest2)  	    end,      {Type,Rest5} = parse_Type(Rest4),      {#type{def = {'SET OF',Type},  	   constraint = merge_constraints([Constraint2])},Rest5};  parse_TypeWithConstraint(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -		       ['SEQUENCE','SEQUENCE SIZE','SET','SET SIZE'], -		       followed,by,a,constraint]}}). +    parse_error(Tokens).  %% --------------------------  parse_ReferencedType(Tokens) -> -    Flist = [fun parse_DefinedType/1, +    Flist = [fun parse_ParameterizedType/1, +	     fun parse_DefinedType/1,  	     fun parse_SelectionType/1, -	     fun parse_TypeFromObject/1, -	     fun parse_ValueSetFromObjects/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +	     fun parse_TypeFromObject/1], +    parse_or(Tokens, Flist). -parse_DefinedType(Tokens=[{typereference,_,_},{'{',_}|_Rest]) -> -    parse_ParameterizedType(Tokens); -parse_DefinedType(Tokens=[{typereference,L1,TypeName}, -			  T2={typereference,_,_},T3={'{',_}|Rest]) -> -    case (catch parse_ParameterizedType(Tokens)) of -	{'EXIT',_Reason} -> -	    Rest2 = [T2,T3|Rest], -	    {#type{def = #'Externaltypereference'{pos=L1, -						  module=resolve_module(TypeName), -						  type=TypeName}},Rest2}; -	{asn1_error,_} -> -	    Rest2 = [T2,T3|Rest], -	    {#type{def = #'Externaltypereference'{pos=L1, -						  module=resolve_module(TypeName), -						  type=TypeName}},Rest2}; -	Result -> -	    Result -    end; -parse_DefinedType(Tokens=[{typereference,_L1,_Module},{'.',_}, -			  {typereference,_,_TypeName},{'{',_}|_Rest]) -> -    parse_ParameterizedType(Tokens); -parse_DefinedType([{typereference,L1,Module},{'.',_},{typereference,_,TypeName}|Rest]) -> -    {#type{def = #'Externaltypereference'{pos=L1,module=Module,type=TypeName}},Rest}; -parse_DefinedType([{typereference,L1,TypeName}|Rest]) -> -    case is_pre_defined_class(TypeName) of -	false  -> -	    {#type{def = #'Externaltypereference'{pos=L1,module=resolve_module(TypeName), -						  type=TypeName}},Rest}; -	_ -> -	    throw({asn1_error, -		   {L1,get(asn1_module), -		    [got,TypeName,expected, -		     [typereference,'typereference.typereference', -		      'typereference typereference']]}}) -    end; +parse_DefinedType([{typereference,L1,Module}, +		   {'.',_}, +		   {typereference,_,TypeName}|Tokens]) -> +    {#type{def = #'Externaltypereference'{pos=L1,module=Module, +					  type=TypeName}},Tokens}; +parse_DefinedType([{typereference,_,_}=Tr|Tokens]) -> +    {#type{def=tref2Exttref(Tr)},Tokens};  parse_DefinedType(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[typereference,'typereference.typereference', -			 'typereference typereference']]}}). +    parse_error(Tokens). -parse_SelectionType([{identifier,_,Name},{'<',_}|Rest]) ->     +parse_SelectionType([#identifier{val=Name},{'<',_}|Rest]) ->      {Type,Rest2} = parse_Type(Rest), -    {{'SelectionType',Name,Type},Rest2}; +    {#type{def={'SelectionType',Name,Type}},Rest2};  parse_SelectionType(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'identifier <']}}). +    parse_error(Tokens).  resolve_module(Type) -> @@ -787,30 +686,13 @@ resolve_module(_Type, Current, undefined) ->  resolve_module(Type, Current, Imports) ->      case [Mod || #'SymbolsFromModule'{symbols = S, module = Mod} <- Imports,                   #'Externaltypereference'{type = T} <- S,  -                 Type == T] of +                 Type =:= T] of          [#'Externaltypereference'{type = Mod}|_] -> Mod;   	%% This allows the same symbol to be imported several times  	%% which ought to be checked elsewhere and flagged as an error          []  -> Current      end. -%% -------------------------- - - -%% This should probably be removed very soon  -% parse_ConstrainedType(Tokens) -> -%     case (catch parse_TypeWithConstraint(Tokens)) of -% 	{'EXIT',Reason} -> -% 	    {Type,Rest} = parse_Type(Tokens), -% 	    {Constraint,Rest2} = parse_Constraint(Rest), -% 	    {Type#type{constraint=Constraint},Rest2}; -% 	{asn1_error,Reason2} -> -% 	    {Type,Rest} = parse_Type(Tokens), -% 	    {Constraint,Rest2} = parse_Constraint(Rest), -% 	    {Type#type{constraint=Constraint},Rest2}; -% 	Result -> -% 	    Result -%     end.  parse_Constraints(Tokens) ->      parse_Constraints(Tokens,[]). @@ -819,9 +701,9 @@ parse_Constraints(Tokens,Acc) ->      {Constraint,Rest} = parse_Constraint(Tokens),      case Rest of  	[{'(',_}|_Rest2] -> -	    parse_Constraints(Rest,[Constraint|Acc]); +	    parse_Constraints(Rest, [Constraint|Acc]);  	_ -> -	    {lists:reverse([Constraint|Acc]),Rest} +	    {lists:reverse(Acc, [Constraint]),Rest}      end.  parse_Constraint([{'(',_}|Rest]) -> @@ -830,46 +712,27 @@ parse_Constraint([{'(',_}|Rest]) ->      case Rest3 of  	[{')',_}|Rest4] ->  	    {#constraint{c=Constraint,e=Exception},Rest4}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,')']}}) -    end; -parse_Constraint(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'(']}}). +	[_|_] -> +	    parse_error(Rest3) +    end.  parse_ConstraintSpec(Tokens) ->      Flist = [fun parse_GeneralConstraint/1,  	     fun parse_SubtypeConstraint/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	{asn1_error,Reason2} -> -	    throw({asn1_error,Reason2}); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_ExceptionSpec([LPar={')',_}|Rest]) ->      {undefined,[LPar|Rest]};  parse_ExceptionSpec([{'!',_}|Rest]) ->      parse_ExceptionIdentification(Rest);  parse_ExceptionSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,[')','!']]}}). +    parse_error(Tokens).  parse_ExceptionIdentification(Tokens) ->      Flist = [fun parse_SignedNumber/1,  	     fun parse_DefinedValue/1,  	     fun parse_TypeColonValue/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	{asn1_error,Reason2} -> -	    throw({asn1_error,Reason2}); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_TypeColonValue(Tokens) ->      {Type,Rest} = parse_Type(Tokens), @@ -877,32 +740,28 @@ parse_TypeColonValue(Tokens) ->  	[{':',_}|Rest2] ->  	    {Value,Rest3} = parse_Value(Rest2),  	    {{Type,Value},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,':']}}) +	[_|_] -> +	    parse_error(Rest)      end.  parse_SubtypeConstraint(Tokens) ->      parse_ElementSetSpecs(Tokens). -parse_ElementSetSpecs([{'...',_}|Rest]) -> -    {Elements,Rest2} = parse_ElementSetSpec(Rest), -    {{[],Elements},Rest2};  parse_ElementSetSpecs(Tokens) ->      {RootElems,Rest} = parse_ElementSetSpec(Tokens),      case Rest of  	[{',',_},{'...',_},{',',_}|Rest2] ->  	    {AdditionalElems,Rest3} = parse_ElementSetSpec(Rest2), -	    {{RootElems,AdditionalElems},Rest3}; +	    {{element_set,RootElems,AdditionalElems},Rest3};  	[{',',_},{'...',_}|Rest2] -> -	    {{RootElems,[]},Rest2}; +	    {{element_set,RootElems,empty},Rest2};  	_ -> -	    {RootElems,Rest} +	    {{element_set,RootElems,none},Rest}      end.  parse_ElementSetSpec([{'ALL',_},{'EXCEPT',_}|Rest]) ->      {Exclusions,Rest2} = parse_Elements(Rest), -    {{'ALL',{'EXCEPT',Exclusions}},Rest2}; +    {{'ALL-EXCEPT',Exclusions},Rest2};  parse_ElementSetSpec(Tokens) ->      parse_Unions(Tokens). @@ -918,14 +777,8 @@ parse_Unions(Tokens) ->      case {InterSec,Unions} of  	{InterSec,[]} ->  	    {InterSec,Rest2}; -	{{'SingleValue',V1},{'SingleValue',V2}} -> -	    {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest2}; -	{V1,V2} when is_list(V2) -> -	    {[V1] ++ [union|V2],Rest2};  	{V1,V2} -> -	    {[V1,union,V2],Rest2} -%	Other -> -%	    throw(Other) +	    {{union,V1,V2},Rest2}      end.  parse_UnionsRec([{'|',_}|Rest]) -> @@ -934,12 +787,8 @@ parse_UnionsRec([{'|',_}|Rest]) ->      case {InterSec,URec} of  	{V1,[]} ->  	    {V1,Rest3}; -	{{'SingleValue',V1},{'SingleValue',V2}} -> -	    {{'SingleValue',ordsets:union(to_set(V1),to_set(V2))},Rest3}; -	{V1,V2} when is_list(V2) -> -	    {[V1] ++ [union|V2],Rest3};  	{V1,V2} -> -	    {[V1,union,V2],Rest3} +	    {{union,V1,V2},Rest3}  	end;  parse_UnionsRec([{'UNION',Info}|Rest]) ->      parse_UnionsRec([{'|',Info}|Rest]); @@ -952,13 +801,8 @@ parse_Intersections(Tokens) ->      case {InterSec,IRec} of  	{V1,[]} ->  	    {V1,Rest2}; -	{{'SingleValue',V1},{'SingleValue',V2}} -> -	    {{'SingleValue', -	      ordsets:intersection(to_set(V1),to_set(V2))},Rest2}; -	{V1,V2} when is_list(V2) -> -	    {[V1] ++ [intersection|V2],Rest2};  	{V1,V2} -> -	    {[V1,intersection,V2],Rest2} +	    {{intersection,V1,V2},Rest2}      end.  %% parse_IElemsRec(Tokens) -> Result @@ -967,15 +811,10 @@ parse_IElemsRec([{'^',_}|Rest]) ->      {InterSec,Rest2} = parse_IntersectionElements(Rest),      {IRec,Rest3} = parse_IElemsRec(Rest2),      case {InterSec,IRec} of -	{{'SingleValue',V1},{'SingleValue',V2}} -> -	    {{'SingleValue', -	      ordsets:intersection(to_set(V1),to_set(V2))},Rest3};  	{V1,[]} -> -	    {V1,Rest3}; -	{V1,V2} when is_list(V2) -> -	    {[V1] ++ [intersection|V2],Rest3}; +	    {V1,Rest2};  	{V1,V2} -> -	    {[V1,intersection,V2],Rest3} +	    {{intersection,V1,V2},Rest3}      end;  parse_IElemsRec([{'INTERSECTION',Info}|Rest]) ->      parse_IElemsRec([{'^',Info}|Rest]); @@ -992,7 +831,7 @@ parse_IntersectionElements(Tokens) ->      case Rest of  	[{'EXCEPT',_}|Rest2] ->  	    {Exclusion,Rest3} = parse_Elements(Rest2), -	    {{InterSec,{'EXCEPT',Exclusion}},Rest3}; +	    {{'EXCEPT',InterSec,Exclusion},Rest3};  	Rest ->  	    {InterSec,Rest}      end. @@ -1006,102 +845,73 @@ parse_Elements([{'(',_}|Rest]) ->      case Rest2 of  	[{')',_}|Rest3] ->  	    {Elems,Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,')']}}) +	[_|_] -> +	    parse_error(Rest2)      end;  parse_Elements(Tokens) ->      Flist = [fun parse_ObjectSetElements/1,  	     fun parse_SubtypeElements/1, -%	     fun parse_Value/1, -%	     fun parse_Type/1,  	     fun parse_Object/1,  	     fun parse_DefinedObjectSet/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	Err = {asn1_error,_} -> -	    throw(Err); -	Result = {Val,_} when is_record(Val,type) -> -	    Result; - -	Result -> -	    Result -    end. -     - +    parse_or(Tokens, Flist).  %% -------------------------- -parse_DefinedObjectClass([{typereference,_,_ModName},{'.',_},Tr={typereference,_,_ObjClName}|Rest]) -> -%%    {{objectclassname,ModName,ObjClName},Rest}; -%    {{objectclassname,tref2Exttref(Tr)},Rest}; -    {tref2Exttref(Tr),Rest}; +parse_DefinedObjectClass([{typereference,_,ModName},{'.',_}, +			  {typereference,Pos,Name}|Tokens]) -> +    Ext = #'Externaltypereference'{pos=Pos, +				   module=ModName, +				   type=Name}, +    {Ext,Tokens};  parse_DefinedObjectClass([Tr={typereference,_,_ObjClName}|Rest]) -> -%    {{objectclassname,tref2Exttref(Tr)},Rest};      {tref2Exttref(Tr),Rest};  parse_DefinedObjectClass(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			['typereference . typereference', -			 typereference, -			 'TYPE-IDENTIFIER', -			 'ABSTRACT-SYNTAX']]}}). - -parse_ObjectClassAssignment([{typereference,L1,ObjClName},{'::=',_}|Rest]) -> -    {Type,Rest2} = parse_ObjectClass(Rest), -    {#classdef{pos=L1,name=ObjClName,module=resolve_module(Type), -	       typespec=Type},Rest2}; -parse_ObjectClassAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   'typereference ::=']}}). +    parse_error(Tokens).  parse_ObjectClass(Tokens) -> -    Flist = [fun parse_DefinedObjectClass/1, -	     fun parse_ObjectClassDefn/1, -	     fun parse_ParameterizedObjectClass/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	{asn1_error,Reason2} -> -	    throw({asn1_error,Reason2}); -	Result -> -	    Result -    end. +    Flist = [fun parse_ObjectClassDefn/1, +	     fun parse_DefinedObjectClass/1], +    parse_or(Tokens, Flist).  parse_ObjectClassDefn([{'CLASS',_},{'{',_}|Rest]) ->      {Type,Rest2} = parse_FieldSpec(Rest),      {WithSyntaxSpec,Rest3} = parse_WithSyntaxSpec(Rest2),      {#objectclass{fields=Type,syntax=WithSyntaxSpec},Rest3};  parse_ObjectClassDefn(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'CLASS {']}}). +    parse_error(Tokens).  parse_FieldSpec(Tokens) ->      parse_FieldSpec(Tokens,[]). -parse_FieldSpec(Tokens,Acc) -> -    Flist = [fun parse_FixedTypeValueFieldSpec/1, -	     fun parse_VariableTypeValueFieldSpec/1, -	     fun parse_ObjectFieldSpec/1, -	     fun parse_FixedTypeValueSetFieldSpec/1, -	     fun parse_VariableTypeValueSetFieldSpec/1, -	     fun parse_TypeFieldSpec/1, -	     fun parse_ObjectSetFieldSpec/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); +parse_FieldSpec(Tokens0, Acc) -> +    Fl = case Tokens0 of +	     [{valuefieldreference,_,_}|_] -> +		 %% 1) &field Type +		 %%    &object CLASS-NAME +		 %% 2) &field &FieldName +		 %% A fixed type field cannot be distinguished from +		 %% an object field without type information. +		 [fun parse_FixedTypeValueFieldSpec/1, +		  fun parse_VariableTypeValueFieldSpec/1]; +	     [{typefieldreference,_,_}|_] -> +		 %% 1) &Set Type +		 %%    &ObjectSet CLASS-NAME +		 %% 2) &Set &FieldName +		 %% 3) &Type +		 %% A value set and an object cannot be distinguished +		 %% without type information. +		 [fun parse_FixedTypeValueSetFieldSpec/1, +		  fun parse_VariableTypeValueSetFieldSpec/1, +		  fun parse_TypeFieldSpec/1]; +	     [_|_] -> +		 parse_error(Tokens0) +	 end, +    case parse_or(Tokens0, Fl) of  	{Type,[{'}',_}|Rest]} -> -	    {lists:reverse([Type|Acc]),Rest}; +	    {lists:reverse(Acc, [Type]),Rest};  	{Type,[{',',_}|Rest2]} -> -	    parse_FieldSpec(Rest2,[Type|Acc]); -	{_,[H|_T]}  -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'}']}}) +	    parse_FieldSpec(Rest2, [Type|Acc])      end.  parse_PrimitiveFieldName([{typefieldreference,_,FieldName}|Rest]) -> @@ -1109,27 +919,19 @@ parse_PrimitiveFieldName([{typefieldreference,_,FieldName}|Rest]) ->  parse_PrimitiveFieldName([{valuefieldreference,_,FieldName}|Rest]) ->      {{valuefieldreference,FieldName},Rest};  parse_PrimitiveFieldName(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[typefieldreference,valuefieldreference]]}}). +    parse_error(Tokens).  parse_FieldName(Tokens) ->      {Field,Rest} = parse_PrimitiveFieldName(Tokens),      parse_FieldName(Rest,[Field]). -parse_FieldName([{'.',_}|Rest],Acc) -> -    case (catch parse_PrimitiveFieldName(Rest)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	{FieldName,Rest2} -> -	    parse_FieldName(Rest2,[FieldName|Acc]) -    end; -parse_FieldName(Tokens,Acc) -> +parse_FieldName([{'.',_}|Rest0],Acc) -> +    {FieldName,Rest1} = parse_PrimitiveFieldName(Rest0), +    parse_FieldName(Rest1, [FieldName|Acc]); +parse_FieldName(Tokens, Acc) ->      {lists:reverse(Acc),Tokens}. -parse_FixedTypeValueFieldSpec([{valuefieldreference,L1,VFieldName}|Rest]) -> +parse_FixedTypeValueFieldSpec([{valuefieldreference,_,VFieldName}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      {Unique,Rest3} =   	case Rest2 of @@ -1139,109 +941,61 @@ parse_FixedTypeValueFieldSpec([{valuefieldreference,L1,VFieldName}|Rest]) ->  		{undefined,Rest2}  	end,      {OptionalitySpec,Rest5} = parse_ValueOptionalitySpec(Rest3), -    case {Unique,Rest5} of -	{'UNIQUE',[{Del,_}|_]} when Del =:= ','; Del =:= '}' -> -	    case OptionalitySpec of  -		{'DEFAULT',_} -> -		    throw({asn1_error, -			   {L1,get(asn1_module), -			    ['UNIQUE and DEFAULT in same field',VFieldName]}}); -		_ -> -		    {{fixedtypevaluefield,VFieldName,Type,Unique,OptionalitySpec},Rest5} -	    end; -	{_,[{Del,_}|_]} when Del =:= ','; Del =:= '}'  -> -	    {{object_or_fixedtypevalue_field,VFieldName,Type,Unique,OptionalitySpec},Rest5}; -	_ -> -	    throw({asn1_error,{L1,get(asn1_module), -			       [got,get_token(hd(Rest5)),expected,[',','}']]}}) -    end; -parse_FixedTypeValueFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,valuefieldreference]}}). +    case is_end_delimiter(Rest5) of +	false -> parse_error(Rest5); +	true -> ok +    end, +    Tag = case Unique of +	      'UNIQUE' -> fixedtypevaluefield; +	      _ -> object_or_fixedtypevalue_field +	  end, +    {{Tag,VFieldName,Type,Unique,OptionalitySpec},Rest5}. + +parse_VariableTypeValueFieldSpec([{valuefieldreference,_,VFieldName}|Rest0]) -> +    {FieldRef,Rest1} = parse_FieldName(Rest0), +    {OptionalitySpec,Rest} = parse_ValueOptionalitySpec(Rest1), +    case is_end_delimiter(Rest) of +	true -> +	    {{variabletypevaluefield,VFieldName,FieldRef,OptionalitySpec}, +	     Rest}; +	false -> +	    parse_error(Rest) +    end. -parse_VariableTypeValueFieldSpec([{valuefieldreference,L,VFieldName}|Rest]) -> -    {FieldRef,Rest2} = parse_FieldName(Rest), -    {OptionalitySpec,Rest3} = parse_ValueOptionalitySpec(Rest2), -    case Rest3 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{variabletypevaluefield,VFieldName,FieldRef,OptionalitySpec},Rest3}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			   [got,get_token(hd(Rest3)),expected,[',','}']]}}) -    end; -parse_VariableTypeValueFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,valuefieldreference]}}). +parse_TypeFieldSpec([{typefieldreference,_,Name}|Rest0]) -> +    {OptionalitySpec,Rest} = parse_TypeOptionalitySpec(Rest0), +    case is_end_delimiter(Rest) of +	true -> +	    {{typefield,Name,OptionalitySpec},Rest}; +	false -> +	    parse_error(Rest) +    end. -parse_ObjectFieldSpec([{valuefieldreference,L,VFieldName}|Rest]) -> -    {Class,Rest2} = parse_DefinedObjectClass(Rest), -    {OptionalitySpec,Rest3} = parse_ObjectOptionalitySpec(Rest2), -    case Rest3 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{objectfield,VFieldName,Class,undefined,OptionalitySpec},Rest3}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			   [got,get_token(hd(Rest3)),expected,[',','}']]}}) -    end; -parse_ObjectFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,valuefieldreference]}}). +parse_FixedTypeValueSetFieldSpec([{typefieldreference,_,Name}|Rest0]) -> +    {Type,Rest1} = parse_Type(Rest0), +    {OptionalitySpec,Rest} = parse_ValueSetOptionalitySpec(Rest1), +    case is_end_delimiter(Rest) of +	true -> +	    {{objectset_or_fixedtypevalueset_field,Name,Type, +	      OptionalitySpec},Rest}; +	false -> +	    parse_error(Rest) +    end. -parse_TypeFieldSpec([{typefieldreference,L,TFieldName}|Rest]) -> -    {OptionalitySpec,Rest2} = parse_TypeOptionalitySpec(Rest), -    case Rest2 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{typefield,TFieldName,OptionalitySpec},Rest2}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,[',','}']]}}) -    end; -parse_TypeFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,typefieldreference]}}). +parse_VariableTypeValueSetFieldSpec([{typefieldreference,_,Name}|Rest0]) -> +    {FieldRef,Rest1} = parse_FieldName(Rest0), +    {OptionalitySpec,Rest} = parse_ValueSetOptionalitySpec(Rest1), +    case is_end_delimiter(Rest) of +	true -> +	    {{variabletypevaluesetfield,Name,FieldRef,OptionalitySpec}, +	     Rest}; +	false -> +	    parse_error(Rest) +    end. -parse_FixedTypeValueSetFieldSpec([{typefieldreference,L,TFieldName}|Rest]) -> -    {Type,Rest2} = parse_Type(Rest), -    {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2), -    case Rest3 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{objectset_or_fixedtypevalueset_field,TFieldName,Type, -	      OptionalitySpec},Rest3}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,[',','}']]}}) -    end;   -parse_FixedTypeValueSetFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,typefieldreference]}}). - -parse_VariableTypeValueSetFieldSpec([{typefieldreference,L,TFieldName}|Rest]) -> -    {FieldRef,Rest2} = parse_FieldName(Rest), -    {OptionalitySpec,Rest3} = parse_ValueSetOptionalitySpec(Rest2), -    case Rest3 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{variabletypevaluesetfield,TFieldName,FieldRef,OptionalitySpec},Rest3}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,[',','}']]}}) -    end;  -parse_VariableTypeValueSetFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,typefieldreference]}}). - -parse_ObjectSetFieldSpec([{typefieldreference,L,TFieldName}|Rest]) -> -    {Class,Rest2} = parse_DefinedObjectClass(Rest), -    {OptionalitySpec,Rest3} = parse_ObjectSetOptionalitySpec(Rest2), -    case Rest3 of -	[{Del,_}|_] when Del =:= ','; Del =:= '}' -> -	    {{objectsetfield,TFieldName,Class,OptionalitySpec},Rest3}; -	_ -> -	    throw({asn1_error,{L,get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,[',','}']]}}) -    end;   -parse_ObjectSetFieldSpec(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,typefieldreference]}}). +is_end_delimiter([{',',_}|_]) -> true; +is_end_delimiter([{'}',_}|_]) -> true; +is_end_delimiter([_|_]) -> false.  parse_ValueOptionalitySpec(Tokens)->      case Tokens of @@ -1252,15 +1006,6 @@ parse_ValueOptionalitySpec(Tokens)->  	_  -> {'MANDATORY',Tokens}      end. -parse_ObjectOptionalitySpec(Tokens) -> -    case Tokens of -	[{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest}; -	[{'DEFAULT',_}|Rest] -> -	    {Object,Rest2} = parse_Object(Rest), -	    {{'DEFAULT',Object},Rest2}; -	_  -> {'MANDATORY',Tokens} -    end. -  parse_TypeOptionalitySpec(Tokens) ->      case Tokens of  	[{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest}; @@ -1279,65 +1024,44 @@ parse_ValueSetOptionalitySpec(Tokens) ->  	_  -> {'MANDATORY',Tokens}      end. -parse_ObjectSetOptionalitySpec(Tokens) -> -        case Tokens of -	[{'OPTIONAL',_}|Rest] -> {'OPTIONAL',Rest}; -	[{'DEFAULT',_}|Rest] -> -	    {ObjectSet,Rest2} = parse_ObjectSet(Rest), -	    {{'DEFAULT',ObjectSet},Rest2}; -	_  -> {'MANDATORY',Tokens} -    end. -  parse_WithSyntaxSpec([{'WITH',_},{'SYNTAX',_}|Rest]) ->      {SyntaxList,Rest2} = parse_SyntaxList(Rest),      {{'WITH SYNTAX',SyntaxList},Rest2};  parse_WithSyntaxSpec(Tokens) ->      {[],Tokens}. -parse_SyntaxList([{'{',_},{'}',_}|Rest]) -> -    {[],Rest};  parse_SyntaxList([{'{',_}|Rest]) ->      parse_SyntaxList(Rest,[]);  parse_SyntaxList(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,['{}','{']]}}). +    parse_error(Tokens). -parse_SyntaxList(Tokens,Acc) -> +parse_SyntaxList(Tokens, Acc) ->      {SyntaxList,Rest} = parse_TokenOrGroupSpec(Tokens),      case Rest of  	[{'}',_}|Rest2] ->  -	    {lists:reverse([SyntaxList|Acc]),Rest2}; +	    {lists:reverse(Acc, [SyntaxList]),Rest2};  	_ -> -	    parse_SyntaxList(Rest,[SyntaxList|Acc]) +	    parse_SyntaxList(Rest, [SyntaxList|Acc])      end.  parse_TokenOrGroupSpec(Tokens) ->      Flist = [fun parse_RequiredToken/1,  	     fun parse_OptionalGroup/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist). -parse_RequiredToken([{typereference,L1,WordName}|Rest]) -> +parse_RequiredToken([{typereference,_,WordName}|Rest]=Tokens) ->      case is_word(WordName) of  	false -> -	    throw({asn1_error,{L1,get(asn1_module), -			       [got,WordName,expected,a,'Word']}}); +	    parse_error(Tokens);  	true ->  	    {WordName,Rest}      end;  parse_RequiredToken([{',',L1}|Rest]) ->      {{',',L1},Rest}; -parse_RequiredToken([{WordName,L1}|Rest]) -> +parse_RequiredToken([{WordName,_}|Rest]=Tokens) ->      case is_word(WordName) of  	false -> -	    throw({asn1_error,{L1,get(asn1_module), -			       [got,WordName,expected,a,'Word']}}); +	    parse_error(Tokens);  	true ->  	    {WordName,Rest}      end; @@ -1347,7 +1071,9 @@ parse_RequiredToken(Tokens) ->  parse_OptionalGroup([{'[',_}|Rest]) ->      {Spec,Rest2} = parse_TokenOrGroupSpec(Rest),      {SpecList,Rest3} = parse_OptionalGroup(Rest2,[Spec]), -    {SpecList,Rest3}. +    {SpecList,Rest3}; +parse_OptionalGroup(Tokens) -> +    parse_error(Tokens).  parse_OptionalGroup([{']',_}|Rest],Acc) ->      {lists:reverse(Acc),Rest}; @@ -1355,82 +1081,55 @@ parse_OptionalGroup(Tokens,Acc) ->      {Spec,Rest} = parse_TokenOrGroupSpec(Tokens),      parse_OptionalGroup(Rest,[Spec|Acc]). -parse_DefinedObject([Id={identifier,_,_ObjName}|Rest]) -> +parse_DefinedObject([#identifier{}=Id|Rest]) ->      {{object,identifier2Extvalueref(Id)},Rest}; -parse_DefinedObject([{typereference,L1,ModName},{'.',_},{identifier,_,ObjName}|Rest]) -> +parse_DefinedObject([{typereference,L1,ModName},{'.',_},#identifier{val=ObjName}|Rest]) ->      {{object, #'Externaltypereference'{pos=L1,module=ModName,type=ObjName}},Rest};  parse_DefinedObject(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -		       [identifier,'typereference.identifier']]}}). +    parse_error(Tokens). -parse_ObjectAssignment([{identifier,L1,ObjName}|Rest]) -> +parse_ObjectAssignment([#identifier{pos=L1,val=ObjName}|Rest]) ->      {Class,Rest2} = parse_DefinedObjectClass(Rest),      case Rest2 of  	[{'::=',_}|Rest3] ->  	    {Object,Rest4} = parse_Object(Rest3),  	    {#typedef{pos=L1,name=ObjName,  		      typespec=#'Object'{classname=Class,def=Object}},Rest4}; -	[H|_T]  ->  -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}); -	Other -> -	    throw({asn1_error,{L1,get(asn1_module), -			       [got,Other,expected,'::=']}}) -    end; -parse_ObjectAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected,identifier]}}). - +	_ -> +	    parse_error(Rest2) +    end.  %% parse_Object(Tokens) -> Ret  %% Tokens    = [Tok]  %% Tok       = tuple()  %% Ret       = {object,_} | {object, _, _}  parse_Object(Tokens) -> -    Flist=[fun parse_ObjectDefn/1, -	   fun parse_ObjectFromObject/1, -	   fun parse_ParameterizedObject/1, -	   fun parse_DefinedObject/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    %% The ObjectFromObject production is not included here, +    %% since it will have been catched by the ValueFromObject +    %% before we reach this point. +    Flist = [fun parse_ObjectDefn/1, +	     fun parse_DefinedObject/1], +    parse_or(Tokens, Flist).  parse_ObjectDefn(Tokens) ->      Flist=[fun parse_DefaultSyntax/1,  	   fun parse_DefinedSyntax/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist). -parse_DefaultSyntax([{'{',_},{'}',_}|Rest]) -> -    {{object,defaultsyntax,[]},Rest};  parse_DefaultSyntax([{'{',_}|Rest]) ->      parse_DefaultSyntax(Rest,[]);  parse_DefaultSyntax(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,['{}','{']]}}). +    parse_error(Tokens). -parse_DefaultSyntax(Tokens,Acc) -> +parse_DefaultSyntax(Tokens, Acc) ->      {Setting,Rest} = parse_FieldSetting(Tokens),      case Rest of  	[{',',_}|Rest2] ->  	    parse_DefaultSyntax(Rest2,[Setting|Acc]);  	[{'}',_}|Rest3] -> -	    {{object,defaultsyntax,lists:reverse([Setting|Acc])},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,[',','}']]}}) +	    {{object,defaultsyntax,lists:reverse(Acc, [Setting])},Rest3}; +	_ -> +	    parse_error(Rest)      end.  parse_FieldSetting(Tokens) -> @@ -1439,7 +1138,9 @@ parse_FieldSetting(Tokens) ->      {{PrimFieldName,Setting},Rest2}.  parse_DefinedSyntax([{'{',_}|Rest]) -> -    parse_DefinedSyntax(Rest,[]). +    parse_DefinedSyntax(Rest, []); +parse_DefinedSyntax(Tokens) -> +    parse_error(Tokens).  parse_DefinedSyntax(Tokens,Acc) ->      case Tokens of @@ -1455,95 +1156,70 @@ parse_DefinedSyntax(Tokens,Acc) ->  %% Literal ::= word | ','  %% Setting ::= Type | Value | ValueSet | Object | ObjectSet  %% word equals typereference, but no lower cases -parse_DefinedSyntaxToken([{',',L1}|Rest]) -> -    {{',',L1},Rest}; +parse_DefinedSyntaxToken([{',',_}=Comma|Rest]) -> +    {Comma,Rest};  %% ObjectClassFieldType or a defined type with a constraint.  %% Should also be able to parse a parameterized type. It may be  %% impossible to distinguish between a parameterized type and a Literal  %% followed by an object set. -parse_DefinedSyntaxToken(Tokens=[{typereference,L1,_Name},{T,_}|_Rest])  -  when T == '.'; T == '(' -> -    case catch parse_Setting(Tokens) of -	{asn1_error,_} -> -	    throw({asn1_error,{L1,get(asn1_module), -			       [got,hd(Tokens), expected,['Word',setting]]}}); -	{'EXIT',Reason} -> -	    exit(Reason); -	Result -> -	    Result -    end; -parse_DefinedSyntaxToken(Tokens=[TRef={typereference,L1,Name}|Rest]) -> +parse_DefinedSyntaxToken([{typereference,_,_Name},{T,_}|_]=Tokens) +  when T =:= '.'; T =:= '(' -> +    parse_Setting(Tokens); +parse_DefinedSyntaxToken([{typereference,L1,Name}=TRef|Rest]=Tokens) ->      case is_word(Name) of  	false ->  	    case lookahead_definedsyntax(Rest) of  		word_or_setting ->  		    {{setting,L1,tref2Exttref(TRef)},Rest}; -		_ -> +		setting ->  		    parse_Setting(Tokens)  	    end;  	true -> -	    %% {{word_or_setting,L1,Name},Rest}  	    {{word_or_setting,L1,tref2Exttref(TRef)},Rest}      end;  parse_DefinedSyntaxToken(Tokens) -> -    case catch parse_Setting(Tokens) of -	{asn1_error,_} -> -	    parse_Word(Tokens); -	{'EXIT',Reason} -> -	    exit(Reason); -	Result -> +    try parse_Setting(Tokens) of +	{_,_}=Result ->  	    Result +    catch +	throw:{asn1_error,_} -> +	    parse_Word(Tokens)      end.  lookahead_definedsyntax([{typereference,_,Name}|_Rest]) -> -    case is_word(Name)  of +    case is_word(Name) of  	true -> word_or_setting; -	_ -> setting +	false -> setting      end;  lookahead_definedsyntax([{'}',_}|_Rest]) ->      word_or_setting;  lookahead_definedsyntax(_) ->      setting. -parse_Word([{Name,Pos}|Rest]) -> +parse_Word([{Name,Pos}|Rest]=Tokens) ->      case is_word(Name) of  	false -> -	    throw({asn1_error,{Pos,get(asn1_module), -			       [got,Name, expected,a,'Word']}}); +	    parse_error(Tokens);  	true ->  	    {{word_or_setting,Pos,tref2Exttref(Pos,Name)},Rest} -    end. +    end; +parse_Word(Tokens) -> +    parse_error(Tokens).  parse_Setting(Tokens) ->      Flist = [{type_tag,fun parse_Type/1},  	     {value_tag,fun parse_Value/1},  	     {object_tag,fun parse_Object/1},  	     {objectset_tag,fun parse_ObjectSet/1}], -    case (catch parse_or_tag(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result = {{value_tag,_},_} -> +    case parse_or_tag(Tokens, Flist) of +	{{value_tag,_},_}=Result -> +	    %% Keep the value_tag.  	    Result;  	{{Tag,Setting},Rest} when is_atom(Tag) -> +	    %% Remove all other tags.  	    {Setting,Rest}      end. -%% parse_Setting(Tokens) -> -%%     Flist = [fun parse_Type/1, -%% 	     fun parse_Value/1, -%% 	     fun parse_Object/1, -%% 	     fun parse_ObjectSet/1], -%%     case (catch parse_or(Tokens,Flist)) of -%% 	{'EXIT',Reason} -> -%% 	    exit(Reason); -%% 	AsnErr = {asn1_error,_} -> -%% 	    throw(AsnErr); -%% 	Result -> -%% 	    Result -%%     end. -  parse_DefinedObjectSet([{typereference,L1,ModuleName},{'.',_},  			{typereference,L2,ObjSetName}|Rest]) ->      {{objectset,L1,#'Externaltypereference'{pos=L2,module=ModuleName, @@ -1552,9 +1228,7 @@ parse_DefinedObjectSet([{typereference,L1,ObjSetName}|Rest]) ->      {{objectset,L1,#'Externaltypereference'{pos=L1,module=resolve_module(ObjSetName),  					    type=ObjSetName}},Rest};  parse_DefinedObjectSet(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[typereference,'typereference.typereference']]}}). +    parse_error(Tokens).  parse_ObjectSetAssignment([{typereference,L1,ObjSetName}|Rest]) ->      {Class,Rest2} = parse_DefinedObjectClass(Rest), @@ -1564,16 +1238,9 @@ parse_ObjectSetAssignment([{typereference,L1,ObjSetName}|Rest]) ->  	    {#typedef{pos=L1,name=ObjSetName,  		      typespec=#'ObjectSet'{class=Class,  					    set=ObjectSet}},Rest4}; -	[H|_T]  ->  -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -%%%	Other -> -%%%	    throw(Other) -    end; -parse_ObjectSetAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest2) +    end.  %% parse_ObjectSet(Tokens) -> {Ret,Rest}  %% Tokens    = [Tok] @@ -1590,26 +1257,20 @@ parse_ObjectSet([{'{',_}|Rest]) ->      case Rest2 of  	[{'}',_}|Rest3] ->  	    {ObjSetSpec,Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'}']}}) +	_ -> +	    parse_error(Rest2)      end;  parse_ObjectSet(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_error(Tokens). -parse_ObjectSetSpec([{'...',_}|Rest]) -> -    case Rest of -	[{',',_}|Rest2] -> -	    {Elements,Rest3}=parse_ElementSetSpecs(Rest2), -	    {{[],Elements},Rest3}; -	_ -> -	    {['EXTENSIONMARK'],Rest} -    end; +parse_ObjectSetSpec([{'...',_},{',',_}|Tokens0]) -> +    {Elements,Tokens} = parse_ElementSetSpec(Tokens0), +    {{element_set,empty,Elements},Tokens}; +parse_ObjectSetSpec([{'...',_}|Tokens]) -> +    {{element_set,empty,empty},Tokens};  parse_ObjectSetSpec(Tokens) ->      parse_ElementSetSpecs(Tokens). -% moved fun parse_Object/1 and fun parse_DefinedObjectSet/1 to parse_Elements  %% parse_ObjectSetElements(Tokens) -> {Result,Rest}  %% Result ::= {'ObjectSetFromObjects',Objects,Name} | {pos,ObjectSet,Params}  %% Objects ::= ReferencedObjects @@ -1619,18 +1280,9 @@ parse_ObjectSetSpec(Tokens) ->  %% ObjectSet ::= {objectset,integer(),#'Externaltypereference'{}}  %% Params ::= list() (see parse_ActualParameterList/1)  parse_ObjectSetElements(Tokens) -> -    Flist = [%fun parse_Object/1, -	     %fun parse_DefinedObjectSet/1, -	     fun parse_ObjectSetFromObjects/1, +    Flist = [fun parse_ObjectSetFromObjects/1,  	     fun parse_ParameterizedObjectSet/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_ObjectClassFieldType(Tokens) ->      {Class,Rest} = parse_DefinedObjectClass(Tokens), @@ -1641,25 +1293,10 @@ parse_ObjectClassFieldType(Tokens) ->  	      classname=Class,  	      class=Class,fieldname=FieldName},  	    {#type{def=OCFT},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) -%%%	Other -> -%%%	    throw(Other) +	_ -> +	    parse_error(Rest)      end. -%parse_ObjectClassFieldValue(Tokens) -> -%    Flist = [fun parse_OpenTypeFieldVal/1, -%	     fun parse_FixedTypeFieldVal/1], -%    case (catch parse_or(Tokens,Flist)) of -%	{'EXIT',Reason} -> -%	    throw(Reason); -%	AsnErr = {asn1_error,_} -> -%	    throw(AsnErr); -%	Result -> -%	    Result -%    end. -  parse_ObjectClassFieldValue(Tokens) ->      parse_OpenTypeFieldVal(Tokens). @@ -1669,28 +1306,10 @@ parse_OpenTypeFieldVal(Tokens) ->  	[{':',_}|Rest2] ->  	    {Value,Rest3} = parse_Value(Rest2),  	    {{opentypefieldvalue,Type,Value},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,':']}}) +	_ -> +	    parse_error(Rest)      end. -% parse_FixedTypeFieldVal(Tokens) -> -%     parse_Value(Tokens). - -% parse_InformationFromObjects(Tokens) -> -%     Flist = [fun parse_ValueFromObject/1, -% 	     fun parse_ValueSetFromObjects/1, -% 	     fun parse_TypeFromObject/1, -% 	     fun parse_ObjectFromObject/1], -%     case (catch parse_or(Tokens,Flist)) of -% 	{'EXIT',Reason} -> -% 	    throw(Reason); -% 	AsnErr = {asn1_error,_} -> -% 	    throw(AsnErr); -% 	Result -> -% 	    Result -%     end. -  %% parse_ReferencedObjects(Tokens) -> {Result,Rest}  %% Result    ::= DefObject | DefObjSet |  %%               {po,DefObject,Params} | {pos,DefObjSet,Params} | @@ -1702,18 +1321,11 @@ parse_OpenTypeFieldVal(Tokens) ->  parse_ReferencedObjects(Tokens) ->      Flist = [fun parse_DefinedObject/1,  	     fun parse_DefinedObjectSet/1, -	     fun parse_ParameterizedObject/1,  	     fun parse_ParameterizedObjectSet/1], -        case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_ValueFromObject(Tokens) -> +    %% This production also matches ObjectFromObject.      {Objects,Rest} = parse_ReferencedObjects(Tokens),      case Rest of  	[{'.',_}|Rest2] -> @@ -1722,35 +1334,10 @@ parse_ValueFromObject(Tokens) ->  		{valuefieldreference,_} ->  		    {{'ValueFromObject',Objects,Name},Rest3};  		_ -> -		    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -				       [got,typefieldreference,expected, -					valuefieldreference]}}) +		    parse_error(Rest2)  	    end; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) -%%%	Other -> -%%%	    throw({asn1_error,{got,Other,expected,'.'}}) -    end. - -parse_ValueSetFromObjects(Tokens) -> -    {Objects,Rest} = parse_ReferencedObjects(Tokens), -    case Rest of -	[{'.',_}|Rest2] -> -	    {Name,Rest3} = parse_FieldName(Rest2), -	    case lists:last(Name) of -		{typefieldreference,_FieldName} -> -		    {{'ValueSetFromObjects',Objects,Name},Rest3}; -		_ -> -		    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -				       [got,get_token(hd(Rest2)),expected, -					typefieldreference]}}) -	    end; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) -%%%	Other -> -%%%	    throw({asn1_error,{got,Other,expected,'.'}}) +	_ -> +	    parse_error(Rest)      end.  parse_TypeFromObject(Tokens) -> @@ -1760,28 +1347,12 @@ parse_TypeFromObject(Tokens) ->  	    {Name,Rest3} = parse_FieldName(Rest2),  	    case lists:last(Name) of  		{typefieldreference,_FieldName} -> -		    {{'TypeFromObject',Objects,Name},Rest3}; +		    {#type{def={'TypeFromObject',Objects,Name}},Rest3};  		_ -> -		    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -				       [got,get_token(hd(Rest2)),expected, -					typefieldreference]}}) +		    parse_error(Rest2)  	    end; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) -%%%	Other -> -%%%	    throw({asn1_error,{got,Other,expected,'.'}}) -    end. - -parse_ObjectFromObject(Tokens) -> -    {Objects,Rest} = parse_ReferencedObjects(Tokens), -    case Rest of -	[{'.',_}|Rest2] -> -	    {Name,Rest3} = parse_FieldName(Rest2), -	    {{'ObjectFromObject',Objects,Name},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) +	_ -> +	    parse_error(Rest)      end.  %% parse_ObjectSetFromObjects(Tokens) -> {Result,Rest} @@ -1799,23 +1370,12 @@ parse_ObjectSetFromObjects(Tokens) ->  		{typefieldreference,_FieldName} ->  		    {{'ObjectSetFromObjects',Objects,Name},Rest3};  		_ -> -		    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -				       [got,get_token(hd(Rest2)),expected, -					typefieldreference]}}) +		    parse_error(Rest2)  	    end; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'.']}}) +	_ -> +	    parse_error(Rest)      end. -% parse_InstanceOfType([{'INSTANCE',_},{'OF',_}|Rest]) -> -%     {Class,Rest2} = parse_DefinedObjectClass(Rest), -%     {{'InstanceOfType',Class},Rest2}. - -% parse_InstanceOfValue(Tokens) -> -%     parse_Value(Tokens). - -  %% X.682 constraint specification @@ -1823,14 +1383,7 @@ parse_GeneralConstraint(Tokens) ->      Flist = [fun parse_UserDefinedConstraint/1,  	     fun parse_TableConstraint/1,  	     fun parse_ContentsConstraint/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_UserDefinedConstraint([{'CONSTRAINED',_},{'BY',_},{'{',_},{'}',_}|Rest])->      {{constrained_by,[]},Rest}; @@ -1841,32 +1394,23 @@ parse_UserDefinedConstraint([{'CONSTRAINED',_},      case Rest2 of  	[{'}',_}|Rest3] ->  	    {{constrained_by,Param},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'}']}}) +	_ -> +	    parse_error(Rest2)      end;  parse_UserDefinedConstraint(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			['CONSTRAINED BY {}','CONSTRAINED BY {']]}}). +    parse_error(Tokens).  parse_UserDefinedConstraintParameter(Tokens) -> -    parse_UserDefinedConstraintParameter(Tokens,[]). -parse_UserDefinedConstraintParameter(Tokens,Acc) -> +    parse_UserDefinedConstraintParameter(Tokens, []). + +parse_UserDefinedConstraintParameter(Tokens0, Acc) ->      Flist = [fun parse_GovernorAndActualParameter/1,  	     fun parse_ActualParameter/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	{Result,Rest} -> -	    case Rest of -		[{',',_}|_Rest2] -> -		    parse_UserDefinedConstraintParameter(Tokens,[Result|Acc]); -		_  -> -		    {lists:reverse([Result|Acc]),Rest} -	    end +    case parse_or(Tokens0, Flist) of +	{Result,[{',',_}|Tokens]} -> +	    parse_UserDefinedConstraintParameter(Tokens, [Result|Acc]); +	{Result,Tokens} -> +	    {lists:reverse(Acc, [Result]),Tokens}      end.  parse_GovernorAndActualParameter(Tokens) -> @@ -1875,26 +1419,18 @@ parse_GovernorAndActualParameter(Tokens) ->  	[{':',_}|Rest2] ->  	    {Params,Rest3} = parse_ActualParameter(Rest2),  	    {{'Governor_Params',Governor,Params},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,':']}}) +	_ -> +	    parse_error(Rest)      end.  parse_TableConstraint(Tokens) ->      Flist = [fun parse_ComponentRelationConstraint/1,  	     fun parse_SimpleTableConstraint/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_SimpleTableConstraint(Tokens) ->      {ObjectSet,Rest} = parse_ObjectSet(Tokens), -    {{simpletable,ObjectSet},Rest}. +    {{element_set,{simpletable,ObjectSet},none},Rest}.  parse_ComponentRelationConstraint([{'{',_}|Rest]) ->      {ObjectSet,Rest2} = parse_DefinedObjectSet(Rest), @@ -1903,21 +1439,18 @@ parse_ComponentRelationConstraint([{'{',_}|Rest]) ->  	    {AtNot,Rest4} = parse_AtNotationList(Rest3,[]),  	    case Rest4 of  		[{'}',_}|Rest5] -> -		    {{componentrelation,ObjectSet,AtNot},Rest5}; -		[H|_T]  -> -		    throw({asn1_error,{get_line(H),get(asn1_module), -				       [got,get_token(H),expected,'}']}}) +		    Ret = {element_set, +			   {componentrelation,ObjectSet,AtNot}, +			   none}, +		    {Ret,Rest5}; +		_ -> +		    parse_error(Rest4)  	    end; -	[H|_T]  -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected, -				'ComponentRelationConstraint',ended,with,'}']}}) -%%%	Other -> -%%%	    throw(Other) +	_  -> +	    parse_error(Rest2)      end;  parse_ComponentRelationConstraint(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_error(Tokens).  parse_AtNotationList(Tokens,Acc) ->      {AtNot,Rest} = parse_AtNotation(Tokens), @@ -1925,7 +1458,7 @@ parse_AtNotationList(Tokens,Acc) ->  	[{',',_}|Rest2] ->  	    parse_AtNotationList(Rest2,[AtNot|Acc]);  	_  -> -	    {lists:reverse([AtNot|Acc]),Rest} +	    {lists:reverse(Acc, [AtNot]),Rest}      end.  parse_AtNotation([{'@',_},{'.',_}|Rest]) -> @@ -1935,20 +1468,17 @@ parse_AtNotation([{'@',_}|Rest]) ->      {CIdList,Rest2} = parse_ComponentIdList(Rest),      {{outermost,CIdList},Rest2};  parse_AtNotation(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,['@','@.']]}}). +    parse_error(Tokens).  parse_ComponentIdList(Tokens) ->      parse_ComponentIdList(Tokens,[]). -parse_ComponentIdList([Id = {identifier,_,_},{'.',_}|Rest],Acc) -> +parse_ComponentIdList([#identifier{}=Id,{'.',_}|Rest], Acc) ->      parse_ComponentIdList(Rest,[identifier2Extvalueref(Id)|Acc]); -parse_ComponentIdList([Id = {identifier,_,_}|Rest],Acc) -> -    {lists:reverse([identifier2Extvalueref(Id)|Acc]),Rest}; +parse_ComponentIdList([#identifier{}=Id|Rest], Acc) -> +    {lists:reverse(Acc, [identifier2Extvalueref(Id)]),Rest};  parse_ComponentIdList(Tokens,_) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[identifier,'identifier.']]}}). +    parse_error(Tokens).  parse_ContentsConstraint([{'CONTAINING',_}|Rest]) ->      {Type,Rest2} = parse_Type(Rest), @@ -1963,24 +1493,14 @@ parse_ContentsConstraint([{'ENCODED',_},{'BY',_}|Rest]) ->      {Value,Rest2} = parse_Value(Rest),      {{contentsconstraint,[],Value},Rest2};  parse_ContentsConstraint(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			'CONTAINING','or','ENCODED BY']}}). - +    parse_error(Tokens).  % X.683 Parameterization of ASN.1 specifications  parse_Governor(Tokens) ->      Flist = [fun parse_Type/1,  	     fun parse_DefinedObjectClass/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_ActualParameter(Tokens) ->      Flist = [fun parse_Type/1, @@ -1989,32 +1509,7 @@ parse_ActualParameter(Tokens) ->  	     fun parse_DefinedObjectClass/1,  	     fun parse_Object/1,  	     fun parse_ObjectSet/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. - -parse_ParameterizedAssignment(Tokens) -> -    Flist = [fun parse_ParameterizedTypeAssignment/1, -	     fun parse_ParameterizedValueAssignment/1, -	     fun parse_ParameterizedValueSetTypeAssignment/1, -	     fun parse_ParameterizedObjectClassAssignment/1, -	     fun parse_ParameterizedObjectAssignment/1, -	     fun parse_ParameterizedObjectSetAssignment/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	AsnAssErr = {asn1_assignment_error,_} -> -	    throw(AsnAssErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  %% parse_ParameterizedTypeAssignment(Tokens) -> Result  %% Result = {#ptypedef{},Rest} | throw() @@ -2025,18 +1520,13 @@ parse_ParameterizedTypeAssignment([{typereference,L1,Name}|Rest]) ->  	    {Type,Rest4} = parse_Type(Rest3),  	    {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Type},  	     Rest4}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -    end; -parse_ParameterizedTypeAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest2) +    end.  %% parse_ParameterizedValueAssignment(Tokens) -> Result  %% Result = {#pvaluedef{},Rest} | throw() -parse_ParameterizedValueAssignment([{identifier,L1,Name}|Rest]) -> +parse_ParameterizedValueAssignment([#identifier{pos=L1,val=Name}|Rest]) ->      {ParameterList,Rest2} = parse_ParameterList(Rest),      {Type,Rest3} = parse_Type(Rest2),      case Rest3 of @@ -2044,13 +1534,9 @@ parse_ParameterizedValueAssignment([{identifier,L1,Name}|Rest]) ->  	    {Value,Rest5} = parse_Value(Rest4),  	    {#pvaluedef{pos=L1,name=Name,args=ParameterList,type=Type,  			 value=Value},Rest5}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -    end; -parse_ParameterizedValueAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected,identifier]}}). +	_ -> +	    parse_error(Rest3) +    end.  %% parse_ParameterizedValueSetTypeAssignment(Tokens) -> Result  %% Result = {#pvaluesetdef{},Rest} | throw() @@ -2062,14 +1548,9 @@ parse_ParameterizedValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->  	    {ValueSet,Rest5} = parse_ValueSet(Rest4),  	    {#pvaluesetdef{pos=L1,name=Name,args=ParameterList,  			   type=Type,valueset=ValueSet},Rest5}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -    end; -parse_ParameterizedValueSetTypeAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest3) +    end.  %% parse_ParameterizedObjectClassAssignment(Tokens) -> Result  %% Result = {#ptypedef{},Rest} | throw() @@ -2080,18 +1561,13 @@ parse_ParameterizedObjectClassAssignment([{typereference,L1,Name}|Rest]) ->  	    {Class,Rest4} = parse_ObjectClass(Rest3),  	    {#ptypedef{pos=L1,name=Name,args=ParameterList,typespec=Class},  	     Rest4}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -    end; -parse_ParameterizedObjectClassAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest2) +    end.  %% parse_ParameterizedObjectAssignment(Tokens) -> Result  %% Result = {#pobjectdef{},Rest} | throw() -parse_ParameterizedObjectAssignment([{identifier,L1,Name}|Rest]) -> +parse_ParameterizedObjectAssignment([#identifier{pos=L1,val=Name}|Rest]) ->      {ParameterList,Rest2} = parse_ParameterList(Rest),      {Class,Rest3} = parse_DefinedObjectClass(Rest2),      case Rest3 of @@ -2099,36 +1575,9 @@ parse_ParameterizedObjectAssignment([{identifier,L1,Name}|Rest]) ->  	    {Object,Rest5} = parse_Object(Rest4),  	    {#pobjectdef{pos=L1,name=Name,args=ParameterList,  			 class=Class,def=Object},Rest5}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -%%%	Other -> -%%%	    throw(Other) -    end; -parse_ParameterizedObjectAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected,identifier]}}). - -%% parse_ParameterizedObjectSetAssignment(Tokens) -> Result -%% Result = {#pobjectsetdef{},Rest} | throw{} -parse_ParameterizedObjectSetAssignment([{typereference,L1,Name}|Rest]) -> -    {ParameterList,Rest2} = parse_ParameterList(Rest), -    {Class,Rest3} = parse_DefinedObjectClass(Rest2), -    case Rest3 of -	[{'::=',_}|Rest4] -> -	    {ObjectSet,Rest5} = parse_ObjectSet(Rest4), -	    {#pobjectsetdef{pos=L1,name=Name,args=ParameterList, -			    class=Class,def=ObjectSet},Rest5}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -%%%	Other -> -%%%	    throw(Other) -    end; -parse_ParameterizedObjectSetAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest3) +    end.  %% parse_ParameterList(Tokens) -> Result  %% Result = [Parameter] @@ -2137,35 +1586,24 @@ parse_ParameterizedObjectSetAssignment(Tokens) ->  %% Type = #type{}  %% DefinedObjectClass = #'Externaltypereference'{}  %% Reference = #'Externaltypereference'{} | #'Externalvaluereference'{} -parse_ParameterList([{'{',_}|Rest]) -> -    parse_ParameterList(Rest,[]); -parse_ParameterList(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +parse_ParameterList([{'{',_}|Tokens]) -> +    parse_ParameterList(Tokens, []).  parse_ParameterList(Tokens,Acc) ->      {Parameter,Rest} = parse_Parameter(Tokens),      case Rest of  	[{',',_}|Rest2] -> -	    parse_ParameterList(Rest2,[Parameter|Acc]); +	    parse_ParameterList(Rest2, [Parameter|Acc]);  	[{'}',_}|Rest3] -> -	    {lists:reverse([Parameter|Acc]),Rest3}; -	[H|_T]  -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,[',','}']]}}) +	    {lists:reverse(Acc, [Parameter]),Rest3}; +	_ -> +	    parse_error(Rest)      end.  parse_Parameter(Tokens) ->      Flist = [fun parse_ParamGovAndRef/1,  	     fun parse_Reference/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_ParamGovAndRef(Tokens) ->      {ParamGov,Rest} = parse_ParamGovernor(Tokens), @@ -2173,86 +1611,54 @@ parse_ParamGovAndRef(Tokens) ->  	[{':',_}|Rest2] ->  	    {Ref,Rest3} = parse_Reference(Rest2),  	    {{ParamGov,Ref},Rest3}; -	[H|_T] -> -	   throw({asn1_error,{get_line(H),get(asn1_module), -			      [got,get_token(H),expected,':']}}) +	_ -> +	    parse_error(Rest)      end.  parse_ParamGovernor(Tokens) ->      Flist = [fun parse_Governor/1,  	     fun parse_Reference/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. - -% parse_ParameterizedReference(Tokens) -> -%     {Ref,Rest} = parse_Reference(Tokens), -%     case Rest of -% 	[{'{',_},{'}',_}|Rest2] -> -% 	    {{ptref,Ref},Rest2}; -% 	_  -> -% 	    {{ptref,Ref},Rest} -%     end. +    parse_or(Tokens, Flist).  parse_SimpleDefinedType([{typereference,L1,ModuleName},{'.',_},  			 {typereference,_,TypeName}|Rest]) ->      {#'Externaltypereference'{pos=L1,module=ModuleName,  						 type=TypeName},Rest};  parse_SimpleDefinedType([Tref={typereference,_,_}|Rest]) -> -%    {#'Externaltypereference'{pos=L2,module=get(asn1_module), -%						 type=TypeName},Rest};      {tref2Exttref(Tref),Rest};  parse_SimpleDefinedType(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[typereference,'typereference.typereference']]}}). +    parse_error(Tokens).  parse_SimpleDefinedValue([{typereference,L1,ModuleName},{'.',_}, -			  {identifier,_,Value}|Rest]) -> +			  #identifier{val=Value}|Rest]) ->      {{simpledefinedvalue,#'Externalvaluereference'{pos=L1,module=ModuleName,  						   value=Value}},Rest}; -parse_SimpleDefinedValue([Id={identifier,_,_Value}|Rest]) -> +parse_SimpleDefinedValue([#identifier{}=Id|Rest]) ->      {{simpledefinedvalue,identifier2Extvalueref(Id)},Rest};  parse_SimpleDefinedValue(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			['typereference.identifier',identifier]]}}). +    parse_error(Tokens).  parse_ParameterizedType(Tokens) -> +    %% May also be a parameterized class.      {Type,Rest} = parse_SimpleDefinedType(Tokens),      {Params,Rest2} = parse_ActualParameterList(Rest), -    {{pt,Type,Params},Rest2}. +    {#type{def={pt,Type,Params}},Rest2}.  parse_ParameterizedValue(Tokens) -> +    %% May also be a parameterized object.      {Value,Rest} = parse_SimpleDefinedValue(Tokens),      {Params,Rest2} = parse_ActualParameterList(Rest),      {{pv,Value,Params},Rest2}. -parse_ParameterizedObjectClass(Tokens) -> -    {Type,Rest} = parse_DefinedObjectClass(Tokens), -    {Params,Rest2} = parse_ActualParameterList(Rest), -    {{poc,Type,Params},Rest2}. -  parse_ParameterizedObjectSet(Tokens) ->      {ObjectSet,Rest} = parse_DefinedObjectSet(Tokens),      {Params,Rest2} = parse_ActualParameterList(Rest),      {{pos,ObjectSet,Params},Rest2}. -parse_ParameterizedObject(Tokens) -> -    {Object,Rest} = parse_DefinedObject(Tokens), -    {Params,Rest2} = parse_ActualParameterList(Rest), -    {{po,Object,Params},Rest2}. -  parse_ActualParameterList([{'{',_}|Rest]) ->      parse_ActualParameterList(Rest,[]);  parse_ActualParameterList(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_error(Tokens).  parse_ActualParameterList(Tokens,Acc) ->      {Parameter,Rest} = parse_ActualParameter(Tokens), @@ -2260,43 +1666,22 @@ parse_ActualParameterList(Tokens,Acc) ->  	[{',',_}|Rest2] ->  	    parse_ActualParameterList(Rest2,[Parameter|Acc]);  	[{'}',_}|Rest3] -> -	    {lists:reverse([Parameter|Acc]),Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,[',','}']]}}) -%%%	Other -> -%%%	    throw(Other) +	    {lists:reverse(Acc, [Parameter]),Rest3}; +	_ -> +	    parse_error(Rest)      end. - - - - - - -%------------------------- - +%% Test whether Token is allowed in a syntax list.  is_word(Token) -> -    case not_allowed_word(Token) of +    List = atom_to_list(Token), +    case not_allowed_word(List) of  	true -> false; -	_ -> -	    if -		is_atom(Token) -> -		    Item = atom_to_list(Token), -		    is_word(Item); -		is_list(Token), length(Token) == 1 -> -		    check_one_char_word(Token); -		is_list(Token) -> -		    [A|Rest] = Token, -		    case check_first(A) of -			true -> -			    check_rest(Rest); -			_ ->  -			    false -		    end -	    end +	false -> is_word_1(List)      end. +is_word_1([H|T]) -> +    check_first(H) andalso check_rest(T). +  not_allowed_word(Name) ->      lists:member(Name,["BIT",  		       "BOOLEAN", @@ -2321,257 +1706,123 @@ not_allowed_word(Name) ->  		       "TRUE",  		       "UNION"]). -check_one_char_word([A]) when $A =< A, $Z >= A -> -    true; -check_one_char_word([_]) -> -    false. %% unknown item in SyntaxList +check_first(C) -> +    $A =< C andalso C =< $Z. -check_first(A) when $A =< A, $Z >= A -> -    true; -check_first(_) -> -    false. %% unknown item in SyntaxList - -check_rest([R,R|_Rs]) when $- == R -> -    false; %% two consecutive hyphens are not allowed in a word -check_rest([R]) when $- == R -> -    false; %% word cannot end with hyphen -check_rest([R|Rs]) when $A=<R, $Z>=R; $-==R -> +check_rest([R|Rs]) when $A =< R, R =< $Z; R =:= $- ->      check_rest(Rs);  check_rest([]) ->      true;  check_rest(_) ->      false. +%%% +%%% Parse alternative type lists for CHOICE. +%%% + +parse_AlternativeTypeLists(Tokens0) -> +    {Root,Tokens1} = parse_AlternativeTypeList(Tokens0), +    case Tokens1 of +	[{',',_}|Tokens2] -> +	    {ExtMarker,Tokens3} = parse_ExtensionAndException(Tokens2), +	    {ExtAlts,Tokens4} =	parse_ExtensionAdditionAlternatives(Tokens3), +	    {_,Tokens} = parse_OptionalExtensionMarker(Tokens4, []), +	    {Root++ExtMarker++ExtAlts,Tokens}; +	Tokens -> +	    {Root,Tokens} +    end. + +parse_ExtensionAndException([{'...',L}|Tokens0]) -> +    {[#'EXTENSIONMARK'{pos=L}], +     case Tokens0 of +	 [{'!',_}|Tokens1] -> +	     {_,Tokens} = parse_ExceptionIdentification(Tokens1), +	     Tokens; +	 _ -> +	     Tokens0 +     end}. + +parse_AlternativeTypeList([#identifier{}|_]=Tokens0) -> +    {AltType,Tokens} = parse_NamedType(Tokens0), +    parse_AlternativeTypeList_1(Tokens, [AltType]); +parse_AlternativeTypeList(Tokens) -> +    parse_error(Tokens). + +parse_AlternativeTypeList_1([{',',_}|[#identifier{}|_]=Tokens0], Acc) -> +    {AltType,Tokens} = parse_NamedType(Tokens0), +    parse_AlternativeTypeList_1(Tokens, [AltType|Acc]); +parse_AlternativeTypeList_1(Tokens, Acc) -> +    {lists:reverse(Acc),Tokens}. -to_set(V) when is_list(V) -> -	ordsets:from_list(V); -to_set(V) -> -	ordsets:from_list([V]). - -parse_AlternativeTypeLists(Tokens) -> -    parse_AlternativeTypeLists(Tokens,[]). - -parse_AlternativeTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) -> -    {CompList,Rest1} = parse_AlternativeTypeList(Tokens,[]), -    parse_AlternativeTypeLists(Rest1,Clist++CompList); -parse_AlternativeTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) -> -    {_,Rest03} = parse_ExceptionIdentification(Rest02), -    %% Exception info is currently thrown away -    parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); -parse_AlternativeTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []-> -    {_,Rest03} = parse_ExceptionIdentification(Rest02), -    %% Exception info is currently thrown away -    parse_AlternativeTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); - -parse_AlternativeTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []-> -    parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); -parse_AlternativeTypeLists([{'...',L1}|Rest02],Clist0) -> -    parse_AlternativeTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]); -parse_AlternativeTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) -> -    {Clist0,Tokens}. - -parse_AlternativeTypeLists2(Tokens,Clist) -> -    {ExtAdd,Rest} = parse_ExtensionAdditionAlternatives(Tokens,Clist), -    {Clist2,Rest2} = parse_OptionalExtensionMarker(Rest,lists:flatten(ExtAdd)), -    case Rest2 of -	[{',',_}|Rest3] -> -	    {CompList,Rest4} = parse_AlternativeTypeList(Rest3,[]), -	    {Clist2 ++ CompList,Rest4}; -	_ -> -	    {Clist2,Rest2} -    end. - - - -parse_AlternativeTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] -> -    {AlternativeType,Rest2} = parse_NamedType([Id|Rest]), -    parse_AlternativeTypeList(Rest2,[AlternativeType|Acc]); -parse_AlternativeTypeList(Tokens = [{'}',_}|_],Acc) -> -    {lists:reverse(Acc),Tokens}; -parse_AlternativeTypeList(Tokens = [{']',_},{']',_}|_],Acc) -> -    {lists:reverse(Acc),Tokens}; -parse_AlternativeTypeList(Tokens = [{',',_},{'...',_}|_],Acc) -> -    {lists:reverse(Acc),Tokens}; -parse_AlternativeTypeList(Tokens,[]) -> -    {AlternativeType,Rest} = parse_NamedType(Tokens), -    parse_AlternativeTypeList(Rest,[AlternativeType]); -parse_AlternativeTypeList(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['}',', identifier']]}}). - -parse_ExtensionAdditionAlternatives(Tokens =[{',',_}|_],Clist) -> -    {ExtAddList,Rest2} = parse_ExtensionAdditionAlternativesList(Tokens,[]), -    {Clist++lists:flatten(ExtAddList),Rest2}; -parse_ExtensionAdditionAlternatives(Tokens,Clist) -> -    %% Empty -    {Clist,Tokens}. +parse_ExtensionAdditionAlternatives([{',',_}|_]=Tokens0) -> +    parse_ExtensionAdditionAlternativesList(Tokens0, []); +parse_ExtensionAdditionAlternatives(Tokens) -> +    {[],Tokens}. -parse_ExtensionAdditionAlternativesList([{',',_},Id = {identifier,_,_}|Rest],Acc) -> -    {AlternativeType,Rest2} = parse_NamedType([Id|Rest]), -    parse_ExtensionAdditionAlternativesList(Rest2,[AlternativeType|Acc]); -parse_ExtensionAdditionAlternativesList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) -> -    {ExtAddGroup,Rest2} = parse_ExtensionAdditionAlternativesGroup([C1,C2|Rest],[]), -    parse_ExtensionAdditionAlternativesList(Rest2,[ExtAddGroup|Acc]); -parse_ExtensionAdditionAlternativesList(Tokens = [{'}',_}|_],Acc) -> -    {lists:reverse(Acc),Tokens}; -parse_ExtensionAdditionAlternativesList(Tokens = [{',',_},{'...',_}|_],Acc) -> -    {lists:reverse(Acc),Tokens}; -parse_ExtensionAdditionAlternativesList(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['}',', identifier']]}}). - - -parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) -> -    parse_ExtensionAdditionAlternativesGroup2(Rest,Num); -parse_ExtensionAdditionAlternativesGroup([ {'[',_},{'[',_}|Rest],[]) -> -    parse_ExtensionAdditionAlternativesGroup2(Rest,undefined); -parse_ExtensionAdditionAlternativesGroup(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['[[']]}}). - - -parse_ExtensionAdditionAlternativesGroup2(Tokens,Num) -> -    {CompTypeList,Rest} = parse_AlternativeTypeList(Tokens,[]), -    case Rest of -	[{']',_},{']',_}|Rest2] -> -	    {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++ -		['ExtensionAdditionGroupEnd'],Rest2}; +parse_ExtensionAdditionAlternativesList([{',',_}|Tokens1]=Tokens0, Acc) -> +    try parse_ExtensionAdditionAlternative(Tokens1) of +	{ExtAddAlt,Tokens2} -> +	    parse_ExtensionAdditionAlternativesList(Tokens2, [ExtAddAlt|Acc]) +    catch +	throw:{asn1_error,_} -> +	    {lists:append(lists:reverse(Acc)),Tokens0} +    end; +parse_ExtensionAdditionAlternativesList(Tokens, Acc) -> +    {lists:append(lists:reverse(Acc)),Tokens}. + +parse_ExtensionAdditionAlternative([#identifier{}|_]=Tokens0) -> +    {NamedType,Tokens} = parse_NamedType(Tokens0), +    {[NamedType],Tokens}; +parse_ExtensionAdditionAlternative([{'[',_},{'[',_}|Tokens0]) -> +    Tokens2 = case Tokens0 of +		  [{number,_,_},{':',_}|Tokens1] -> Tokens1; +		  _ -> Tokens0 +	      end, +    {GroupList,Tokens3} = parse_AlternativeTypeList(Tokens2), +    case Tokens3 of +	[{']',_},{']',_}|Tokens] -> +	    {GroupList,Tokens};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected,[']]']]}}) -    end. - -%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% - -%% parse_AlternativeTypeLists(Tokens,ExtensionDefault) -> -%%     {AltTypeList,Rest1} = parse_AlternativeTypeList(Tokens), -%%     {ExtensionAndException,Rest2} = -%% 	case Rest1 of -%% 	    [{',',_},{'...',L1},{'!',_}|Rest12] -> -%% 		{_,Rest13} = parse_ExceptionIdentification(Rest12), -%% 		%% Exception info is currently thrown away -%% 		{[#'EXTENSIONMARK'{pos=L1}],Rest13}; -%% 	    [{',',_},{'...',L1}|Rest12] -> -%% 		{[#'EXTENSIONMARK'{pos=L1}],Rest12}; -%% 	    _ -> -%% 		{[],Rest1} -%% 	end, -%%     {AltTypeList2,Rest5} = -%% 	case ExtensionAndException of -%% 	    [] -> -%% 		{AltTypeList,Rest2}; -%% 	    _ -> -%% 		{ExtensionAddition,Rest3} = -%% 		    case Rest2 of -%% 			[{',',_}|Rest23] -> -%% 			    parse_ExtensionAdditionAlternativeList(Rest23); -%% 			_ -> -%% 			    {[],Rest2} -%% 		    end, -%% 		{OptionalExtensionMarker,Rest4} = -%% 		    case Rest3 of -%% 			[{',',_},{'...',L3}|Rest31] -> -%% 			    {[#'EXTENSIONMARK'{pos=L3}],Rest31}; -%% 			_ -> -%% 			    {[],Rest3} -%% 		    end, -%% 		{AltTypeList ++ ExtensionAndException ++ -%% 		 ExtensionAddition ++ OptionalExtensionMarker, Rest4} -%% 	end, -%%     AltTypeList3 = -%% 	case [X || X=#'EXTENSIONMARK'{} <- AltTypeList2] of -%% 	    [] when ExtensionDefault == 'IMPLIED' -> -%% 		AltTypeList2 ++ [#'EXTENSIONMARK'{}]; -%% 	    _ -> -%% 		AltTypeList2 -%% 	end, -%%     {AltTypeList3,Rest5}. -     - -%% parse_AlternativeTypeList(Tokens) -> -%%     parse_AlternativeTypeList(Tokens,[]). +	    parse_error(Tokens3) +    end; +parse_ExtensionAdditionAlternative(Tokens) -> +    parse_error(Tokens). -%% parse_AlternativeTypeList(Tokens,Acc) -> -%%     {NamedType,Rest} = parse_NamedType(Tokens), -%%     case Rest of -%% 	[{',',_},Id = {identifier,_,_}|Rest2] -> -%% 	    parse_AlternativeTypeList([Id|Rest2],[NamedType|Acc]); -%% 	_ -> -%% 	    {lists:reverse([NamedType|Acc]),Rest} -%%     end. +%%% +%%% End of parsing of alternative type lists. +%%% -     - -%% parse_ExtensionAdditionAlternativeList(Tokens) -> -%%     parse_ExtensionAdditionAlternativeList(Tokens,[]). - -%% parse_ExtensionAdditionAlternativeList([{'[[',_}|Rest],Acc) -> -%%     parse_ExtensionAdditionAlternativeList(Rest,Acc); -%% parse_ExtensionAdditionAlternativeList(Tokens = [{identifier,_,_}|_Rest],Acc) -> -%%     {Element,Rest0} = parse_NamedType(Tokens); -%%     case Rest0 of -%% 	[{',',_}|Rest01] -> -%% 	    parse_ExtensionAdditionAlternativeList(Rest01,[Element|Acc]); -%% 	_  -> -%% 	    {lists:reverse([Element|Acc]),Rest0} -%%     end. - -%% parse_ExtensionAdditionAlternatives([{'[[',_}|Rest]) -> -%%     parse_ExtensionAdditionAlternatives(Rest,[]); -%% parse_ExtensionAdditionAlternatives(Tokens) -> -%%     throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -%% 		       [got,get_token(hd(Tokens)),expected,'[[']}}). - -%% parse_ExtensionAdditionAlternatives([Id = {identifier,_,_}|Rest],Acc) -> -%%     {NamedType, Rest2} = parse_NamedType([Id|Rest]), -%%     case Rest2 of -%% 	[{',',_}|Rest21] -> -%% 	    parse_ExtensionAdditionAlternatives(Rest21,[NamedType|Acc]); -%% 	[{']]',_}|Rest21] -> -%% 	    {lists:reverse(Acc),Rest21}; -%% 	_ -> -%% 	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -%% 			       [got,get_token(hd(Rest2)),expected,[',',']]']]}}) -%%     end. - -parse_NamedType([{identifier,L1,Idname}|Rest]) -> +parse_NamedType([#identifier{pos=L1,val=Idname}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      {#'ComponentType'{pos=L1,name=Idname,typespec=Type,prop=mandatory},Rest2};  parse_NamedType(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,identifier]}}). +    parse_error(Tokens). +%%% +%%% Parse component type lists for SEQUENCE and SET. +%%%  parse_ComponentTypeLists(Tokens) -> -    parse_ComponentTypeLists(Tokens,[]). +    parse_ComponentTypeLists(Tokens, []). -parse_ComponentTypeLists(Tokens = [{identifier,_,_}|_Rest0],Clist) -> -    {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]), -    parse_ComponentTypeLists(Rest1,Clist++CompList); -parse_ComponentTypeLists(Tokens = [{'COMPONENTS',_},{'OF',_}|_Rest],Clist) -> +parse_ComponentTypeLists([#identifier{}|_Rest0]=Tokens, Clist) ->      {CompList,Rest1} = parse_ComponentTypeList(Tokens,[]),      parse_ComponentTypeLists(Rest1,Clist++CompList); -parse_ComponentTypeLists([{'...',L1},{'!',_}|Rest02],Clist0) -> -    {_,Rest03} = parse_ExceptionIdentification(Rest02), -    %% Exception info is currently thrown away -    parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); +parse_ComponentTypeLists([{'COMPONENTS',_},{'OF',_}|_]=Tokens,Clist) -> +    {CompList,Rest1} = parse_ComponentTypeList(Tokens, []), +    parse_ComponentTypeLists(Rest1, Clist++CompList);  parse_ComponentTypeLists([{',',L1},{'...',_},{'!',_}|Rest02],Clist0) when Clist0 =/= []->      {_,Rest03} = parse_ExceptionIdentification(Rest02),      %% Exception info is currently thrown away      parse_ComponentTypeLists2(Rest03,Clist0++[#'EXTENSIONMARK'{pos=L1}]); - - parse_ComponentTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []-> +parse_ComponentTypeLists([{',',_},{'...',L1}|Rest02],Clist0) when Clist0 =/= []->      parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);  parse_ComponentTypeLists([{'...',L1}|Rest02],Clist0) ->      parse_ComponentTypeLists2(Rest02,Clist0++[#'EXTENSIONMARK'{pos=L1}]);  parse_ComponentTypeLists(Tokens = [{'}',_L1}|_Rest02],Clist0) -> -    {Clist0,Tokens}. +    {Clist0,Tokens}; +parse_ComponentTypeLists(Tokens, _) -> +    parse_error(Tokens).  parse_ComponentTypeLists2(Tokens,Clist) ->      {ExtAdd,Rest} = parse_ExtensionAdditions(Tokens,Clist), @@ -2590,12 +1841,12 @@ parse_OptionalExtensionMarker(Tokens,Clist) ->      {Clist,Tokens}. -parse_ComponentTypeList([{',',_},Id = {identifier,_,_}|Rest],Acc) when Acc =/= [] -> -    {ComponentType,Rest2} = parse_ComponentType([Id|Rest]), -    parse_ComponentTypeList(Rest2,[ComponentType|Acc]); -parse_ComponentTypeList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) when Acc =/= [] -> -    {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]), -    parse_ComponentTypeList(Rest2,[ComponentType|Acc]); +parse_ComponentTypeList([{',',_}|[#identifier{}|_]=Tokens0], Acc) when Acc =/= [] -> +    {ComponentType,Tokens} = parse_ComponentType(Tokens0), +    parse_ComponentTypeList(Tokens, [ComponentType|Acc]); +parse_ComponentTypeList([{',',_}|[{'COMPONENTS',_},{'OF',_}|_]=Tokens0], Acc) when Acc =/= [] -> +    {ComponentType,Tokens} = parse_ComponentType(Tokens0), +    parse_ComponentTypeList(Tokens, [ComponentType|Acc]);  parse_ComponentTypeList(Tokens = [{'}',_}|_],Acc) ->      {lists:reverse(Acc),Tokens};  parse_ComponentTypeList(Tokens = [{']',_},{']',_}|_],Acc) -> @@ -2606,10 +1857,7 @@ parse_ComponentTypeList(Tokens,[]) ->      {ComponentType,Rest} = parse_ComponentType(Tokens),      parse_ComponentTypeList(Rest,[ComponentType]);  parse_ComponentTypeList(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['}',', identifier']]}}). +    parse_error(Tokens).  parse_ExtensionAdditions(Tokens=[{',',_}|_],Clist) ->      {ExtAddList,Rest2} = parse_ExtensionAdditionList(Tokens,[]), @@ -2618,46 +1866,36 @@ parse_ExtensionAdditions(Tokens,Clist) ->      %% Empty      {Clist,Tokens}. -parse_ExtensionAdditionList([{',',_},Id = {identifier,_,_}|Rest],Acc) -> -    {ComponentType,Rest2} = parse_ComponentType([Id|Rest]), -    parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]); -parse_ExtensionAdditionList([{',',_},C1={'COMPONENTS',_},C2={'OF',_}|Rest],Acc) -> -    {ComponentType,Rest2} = parse_ComponentType([C1,C2|Rest]), -    parse_ExtensionAdditionList(Rest2,[ComponentType|Acc]); -parse_ExtensionAdditionList([{',',_},C1 = {'[',_},C2 = {'[',_}|Rest],Acc) -> -    {ExtAddGroup,Rest2} = parse_ExtensionAdditionGroup([C1,C2|Rest],[]), +parse_ExtensionAdditionList([{',',_}|[#identifier{}|_]=Tokens0], Acc) -> +    {ComponentType,Tokens} = parse_ComponentType(Tokens0), +    parse_ExtensionAdditionList(Tokens, [ComponentType|Acc]); +parse_ExtensionAdditionList([{',',_}|[{'COMPONENTS',_},{'OF',_}|_]=Tokens0], Acc) -> +    {ComponentType,Tokens} = parse_ComponentType(Tokens0), +    parse_ExtensionAdditionList(Tokens, [ComponentType|Acc]); +parse_ExtensionAdditionList([{',',_},{'[',_},{'[',_}|Tokens], Acc) -> +    {ExtAddGroup,Rest2} = parse_ExtensionAdditionGroup(Tokens),      parse_ExtensionAdditionList(Rest2,[ExtAddGroup|Acc]); -parse_ExtensionAdditionList(Tokens = [{'}',_}|_],Acc) -> +parse_ExtensionAdditionList([{'}',_}|_]=Tokens, Acc) ->      {lists:reverse(Acc),Tokens}; -parse_ExtensionAdditionList(Tokens = [{',',_},{'...',_}|_],Acc) -> +parse_ExtensionAdditionList([{',',_},{'...',_}|_]=Tokens, Acc) ->      {lists:reverse(Acc),Tokens}; -parse_ExtensionAdditionList(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['}',', identifier']]}}). - +parse_ExtensionAdditionList(Tokens, _) -> +    parse_error(Tokens). -parse_ExtensionAdditionGroup([ {'[',_},{'[',_},_VsnNr = {number,_,Num},{':',_}|Rest],[]) -> -    parse_ExtensionAdditionGroup2(Rest,Num); -parse_ExtensionAdditionGroup([ {'[',_},{'[',_}|Rest],[]) -> -    parse_ExtensionAdditionGroup2(Rest,undefined); -parse_ExtensionAdditionGroup(Tokens,_) -> -    throw({asn1_error, -	   {get_line(hd(Tokens)),get(asn1_module), -	    [got,[get_token(hd(Tokens)),get_token(hd(tl(Tokens)))], -	     expected,['[[']]}}). +parse_ExtensionAdditionGroup([{number,_,Num},{':',_}|Tokens]) -> +    parse_ExtensionAdditionGroup2(Tokens, Num); +parse_ExtensionAdditionGroup(Tokens) -> +    parse_ExtensionAdditionGroup2(Tokens, undefined). -parse_ExtensionAdditionGroup2(Tokens,Num) -> +parse_ExtensionAdditionGroup2(Tokens, Num) ->      {CompTypeList,Rest} = parse_ComponentTypeList(Tokens,[]),      case Rest of  	[{']',_},{']',_}|Rest2] ->  	    {[{'ExtensionAdditionGroup',Num}|CompTypeList] ++  		['ExtensionAdditionGroupEnd'],Rest2};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected,[']]']]}}) +	    parse_error(Rest)      end. @@ -2676,83 +1914,81 @@ parse_ComponentType(Tokens) ->  	    Result      end. -	     +%%% +%%% Parse ENUMERATED. +%%% -parse_SignedNumber([{number,_,Value}|Rest]) -> -    {Value,Rest}; -parse_SignedNumber([{'-',_},{number,_,Value}|Rest]) -> -    {-Value,Rest}; -parse_SignedNumber(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected, -			[number,'-number']]}}). - -parse_Enumerations(Tokens=[{identifier,_,_}|_Rest],ExtensionDefault) -> -    parse_Enumerations(Tokens,[],ExtensionDefault); -parse_Enumerations([H|_T],_) -> -    throw({asn1_error,{get_line(H),get(asn1_module), -		       [got,get_token(H),expected,identifier]}}). - -parse_Enumerations(Tokens = [{identifier,_,_},{'(',_}|_Rest], Acc, ExtensionDefault) -> -    {NamedNumber,Rest2} = parse_NamedNumber(Tokens), -    case Rest2 of -	[{',',_}|Rest3] -> -	    parse_Enumerations(Rest3,[NamedNumber|Acc], ExtensionDefault); -	_ when ExtensionDefault == 'IMPLIED'-> -	    {lists:reverse(['EXTENSIONMARK',NamedNumber|Acc]),Rest2}; +parse_Enumerations(Tokens0) -> +    {Root,Tokens1} = parse_Enumeration(Tokens0), +    case Tokens1 of +	[{',',_},{'...',_},{',',_}|Tokens2] -> +	    {Ext,Tokens} = parse_Enumeration(Tokens2), +	    {Root++['EXTENSIONMARK'|Ext],Tokens}; +	[{',',_},{'...',_}|Tokens] -> +	    {Root++['EXTENSIONMARK'],Tokens};  	_ -> -	    {lists:reverse([NamedNumber|Acc]),Rest2} -    end; -parse_Enumerations([{identifier,_,Id}|Rest], Acc, ExtensionDefault) -> -    case Rest of -	[{',',_}|Rest2] -> -	    parse_Enumerations(Rest2,[Id|Acc], ExtensionDefault); -	_ when ExtensionDefault == 'IMPLIED' -> -	    {lists:reverse(['EXTENSIONMARK', Id |Acc]),Rest}; -	_ -> -	    {lists:reverse([Id|Acc]),Rest} -    end; -parse_Enumerations([{'...',_}|Rest], Acc, _ExtensionDefault) -> -    case Rest of -	[{',',_}|Rest2] -> -	    parse_Enumerations(Rest2,['EXTENSIONMARK'|Acc],undefined); -	_ -> -	    {lists:reverse(['EXTENSIONMARK'|Acc]),Rest} +	    case get(extensiondefault) of +		'IMPLIED' -> +		    {Root++['EXTENSIONMARK'],Tokens1}; +		_ -> +		    {Root,Tokens1} +	    end +    end. + +parse_Enumeration(Tokens0) -> +    {Item,Tokens} = parse_EnumerationItem(Tokens0), +    parse_Enumeration_1(Tokens, [Item]). + +parse_Enumeration_1([{',',_}|Tokens1]=Tokens0, Acc) -> +    try parse_EnumerationItem(Tokens1) of +	{Item,Tokens} -> +	    parse_Enumeration_1(Tokens, [Item|Acc]) +    catch +	throw:{asn1_error,_} -> +	    {lists:reverse(Acc),Tokens0}      end; -parse_Enumerations([H|_T],_,_) -> -    throw({asn1_error,{get_line(H),get(asn1_module), -		       [got,get_token(H),expected,identifier]}}). +parse_Enumeration_1(Tokens, Acc) -> +    {lists:reverse(Acc),Tokens}. + +parse_EnumerationItem([#identifier{},{'(',_}|_]=Tokens) -> +    parse_NamedNumber(Tokens); +parse_EnumerationItem([#identifier{val=Id}|Tokens]) -> +    {Id,Tokens}; +parse_EnumerationItem(Tokens) -> +    parse_error(Tokens). + +%%% +%%% End of parsing of ENUMERATED. +%%%  parse_NamedNumberList(Tokens) -> -    parse_NamedNumberList(Tokens,[]). +    parse_NamedNumberList(Tokens, []). -parse_NamedNumberList(Tokens,Acc) -> +parse_NamedNumberList(Tokens, Acc) ->      {NamedNum,Rest} = parse_NamedNumber(Tokens),      case Rest of  	[{',',_}|Rest2] ->  	    parse_NamedNumberList(Rest2,[NamedNum|Acc]);  	_ -> -	    {lists:reverse([NamedNum|Acc]),Rest} +	    {lists:reverse(Acc, [NamedNum]),Rest}      end. -parse_NamedNumber([{identifier,_,Name},{'(',_}|Rest]) -> +parse_NamedNumber([#identifier{val=Name},{'(',_}|Rest]) ->      Flist = [fun parse_SignedNumber/1,  	     fun parse_DefinedValue/1], -    case (catch parse_or(Rest,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); +    case parse_or(Rest, Flist) of  	{NamedNum,[{')',_}|Rest2]} ->  	    {{'NamedNumber',Name,NamedNum},Rest2};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected,'NamedNumberList']}}) +	    parse_error(Rest)      end;  parse_NamedNumber(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,identifier]}}). +    parse_error(Tokens). +parse_SignedNumber([{number,_,Value}|Rest]) -> +    {Value,Rest}; +parse_SignedNumber(Tokens) -> +    parse_error(Tokens).  parse_Tag([{'[',_}|Rest]) ->      {Class,Rest2} = parse_Class(Rest), @@ -2767,12 +2003,8 @@ parse_Tag([{'[',_}|Rest]) ->  	[{']',_}|Rest4] ->  	    {#tag{class=Class,number=ClassNumber},Rest4};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest3)),get(asn1_module), -			       [got,get_token(hd(Rest3)),expected,']']}}) -    end; -parse_Tag(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'[']}}). +	    parse_error(Rest3) +    end.  parse_Class([{'UNIVERSAL',_}|Rest]) ->      {'UNIVERSAL',Rest}; @@ -2791,15 +2023,7 @@ parse_Value(Tokens) ->      Flist = [fun parse_BuiltinValue/1,  	     fun parse_ValueFromObject/1,  	     fun parse_DefinedValue/1], - -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end. +    parse_or(Tokens, Flist).  parse_BuiltinValue([{bstring,_,Bstr}|Rest]) ->      {{bstring,Bstr},Rest}; @@ -2812,18 +2036,11 @@ parse_BuiltinValue(Tokens = [{'{',_}|_Rest]) ->  	     fun parse_SequenceOfValue/1,   	     fun parse_SequenceValue/1,   	     fun parse_ObjectIdentifierValue/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	Result -> -	    Result -    end; -parse_BuiltinValue([{identifier,_,IdName},{':',_}|Rest]) -> +    parse_or(Tokens, Flist); +parse_BuiltinValue([#identifier{val=IdName},{':',_}|Rest]) ->      {Value,Rest2} = parse_Value(Rest),      {{'CHOICE',{IdName,Value}},Rest2}; -parse_BuiltinValue(Tokens=[{'NULL',_},{':',_}|_Rest])  -> +parse_BuiltinValue([{'NULL',_},{':',_}|_]=Tokens)  ->      parse_ObjectClassFieldValue(Tokens);  parse_BuiltinValue([{'NULL',_}|Rest])  ->      {'NULL',Rest}; @@ -2839,31 +2056,29 @@ parse_BuiltinValue([{cstring,_,Cstr}|Rest]) ->      {Cstr,Rest};  parse_BuiltinValue([{number,_,Num}|Rest]) ->      {Num,Rest}; -parse_BuiltinValue([{'-',_},{number,_,Num}|Rest]) -> -    {- Num,Rest};  parse_BuiltinValue(Tokens) ->      parse_ObjectClassFieldValue(Tokens). -parse_DefinedValue(Tokens=[{identifier,_,_},{'{',_}|_Rest]) -> -    parse_ParameterizedValue(Tokens); -%% Externalvaluereference -parse_DefinedValue([{typereference,L1,Tname},{'.',_},{identifier,_,Idname}|Rest]) -> +parse_DefinedValue(Tokens) -> +    Flist = [fun parse_ParameterizedValue/1, +	     fun parse_DefinedValue2/1], +    parse_or(Tokens, Flist). + +parse_DefinedValue2([{typereference,L1,Tname}, +		     {'.',_}, +		     #identifier{val=Idname}|Rest]) ->      {#'Externalvaluereference'{pos=L1,module=Tname,value=Idname},Rest};  %% valuereference -parse_DefinedValue([Id = {identifier,_,_}|Rest]) -> +parse_DefinedValue2([#identifier{}=Id|Rest]) ->      {identifier2Extvalueref(Id),Rest}; -%% ParameterizedValue -parse_DefinedValue(Tokens) -> -    parse_ParameterizedValue(Tokens). +parse_DefinedValue2(Tokens) -> +    parse_error(Tokens).  parse_SequenceValue([{'{',_}|Tokens]) -> -    parse_SequenceValue(Tokens,[]); -parse_SequenceValue(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_SequenceValue(Tokens, []). -parse_SequenceValue([{identifier,Pos,IdName}|Rest],Acc) -> +parse_SequenceValue([#identifier{pos=Pos,val=IdName}|Rest],Acc) ->      {Value,Rest2} = parse_Value(Rest),      SeqTag = #seqtag{pos=Pos,module=get(asn1_module),val=IdName},      case Rest2 of @@ -2872,18 +2087,13 @@ parse_SequenceValue([{identifier,Pos,IdName}|Rest],Acc) ->  	[{'}',_}|Rest3] ->  	    {lists:reverse(Acc, [{SeqTag,Value}]),Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end;  parse_SequenceValue(Tokens,_Acc) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,identifier]}}). +    parse_error(Tokens).  parse_SequenceOfValue([{'{',_}|Tokens]) -> -    parse_SequenceOfValue(Tokens,[]); -parse_SequenceOfValue(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_SequenceOfValue(Tokens, []).  parse_SequenceOfValue(Tokens,Acc) ->      {Value,Rest2} = parse_Value(Tokens), @@ -2891,10 +2101,9 @@ parse_SequenceOfValue(Tokens,Acc) ->  	[{',',_}|Rest3] ->  	    parse_SequenceOfValue(Rest3,[Value|Acc]);  	[{'}',_}|Rest3] -> -	    {lists:reverse([Value|Acc]),Rest3}; +	    {lists:reverse(Acc, [Value]),Rest3};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'}']}}) +	    parse_error(Rest2)      end.  parse_ValueSetTypeAssignment([{typereference,L1,Name}|Rest]) -> @@ -2904,49 +2113,31 @@ parse_ValueSetTypeAssignment([{typereference,L1,Name}|Rest]) ->  	    {ValueSet,Rest4} = parse_ValueSet(Rest3),  	    {#valuedef{pos=L1,name=Name,type=Type,value=ValueSet,  		       module=get(asn1_module)},Rest4}; -	[H|_T] -> -	    throw({asn1_error,{get_line(L1),get(asn1_module), -			       [got,get_token(H),expected,'::=']}}) -    end; -parse_ValueSetTypeAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected, -				   typereference]}}). +	_ -> +	    parse_error(Rest2) +    end.  parse_ValueSet([{'{',_}|Rest]) ->      {Elems,Rest2} = parse_ElementSetSpecs(Rest),      case Rest2 of  	[{'}',_}|Rest3] ->  	    {{valueset,Elems},Rest3}; -	[H|_T] -> -	    throw({asn1_error,{get_line(H),get(asn1_module), -			       [got,get_token(H),expected,'}']}}) +	_ -> +	    parse_error(Rest2)      end;  parse_ValueSet(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'{']}}). +    parse_error(Tokens). -parse_ValueAssignment([{identifier,L1,IdName}|Rest]) -> +parse_ValueAssignment([#identifier{pos=L1,val=IdName}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      case Rest2 of  	[{'::=',_}|Rest3] ->  	    {Value,Rest4} = parse_Value(Rest3), -	    case catch lookahead_assignment(Rest4) of -		ok -> -		    {#valuedef{pos=L1,name=IdName,type=Type,value=Value, -			       module=get(asn1_module)},Rest4}; -		Error -> -		    throw(Error) -%% 		    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -%% 				       [got,get_token(hd(Rest2)),expected,'::=']}}) -	    end; +	    {#valuedef{pos=L1,name=IdName,type=Type,value=Value, +		       module=get(asn1_module)},Rest4};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest2)),get(asn1_module), -			       [got,get_token(hd(Rest2)),expected,'::=']}}) -    end; -parse_ValueAssignment(Tokens) -> -    throw({asn1_assignment_error,{get_line(hd(Tokens)),get(asn1_module), -				  [got,get_token(hd(Tokens)),expected,identifier]}}). +	    parse_error(Rest2) +    end.  %% SizeConstraint  parse_SubtypeElements([{'SIZE',_}|Tokens]) -> @@ -2966,8 +2157,7 @@ parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_},{'...',_},{',',_}|Tok  	[{'}',_}|Rest2] ->  	    {{'WITH COMPONENTS',{'PartialSpecification',Constraint}},Rest2};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected,'}']}}) +	    parse_error(Rest)      end;  parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_}|Tokens]) ->      {Constraint,Rest} = parse_TypeConstraints(Tokens), @@ -2975,28 +2165,18 @@ parse_SubtypeElements([{'WITH',_},{'COMPONENTS',_},{'{',_}|Tokens]) ->  	[{'}',_}|Rest2] ->  	    {{'WITH COMPONENTS',{'FullSpecification',Constraint}},Rest2};  	_ -> -	    throw({asn1_error,{get_line(hd(Rest)),get(asn1_module), -			       [got,get_token(hd(Rest)),expected,'}']}}) +	    parse_error(Rest)      end;  parse_SubtypeElements([{'PATTERN',_}|Tokens]) ->      {Value,Rest} = parse_Value(Tokens),      {{pattern,Value},Rest}; -%% SingleValue -%% ContainedSubtype -%% ValueRange -%% TypeConstraint -%% Moved fun parse_Value/1 and fun parse_Type/1 to parse_Elements  parse_SubtypeElements(Tokens) ->      Flist = [fun parse_ContainedSubtype/1,  	     fun parse_Value/1,  -	     fun([{'MIN',_}|T]) -> {'MIN',T} end, +	     fun parse_MIN/1,  	     fun parse_Type/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	{asn1_error,Reason} -> -	    throw(Reason); -	Result = {Val,_} when is_record(Val,type) -> +    case parse_or(Tokens, Flist) of +	{#type{},_}=Result ->  	    Result;  	{Lower,[{'..',_}|Rest]} ->  	    {Upper,Rest2} = parse_UpperEndpoint(Rest), @@ -3014,10 +2194,7 @@ parse_ContainedSubtype([{'INCLUDES',_}|Rest]) ->      {Type,Rest2} = parse_Type(Rest),      {{'ContainedSubtype',Type},Rest2};  parse_ContainedSubtype(Tokens) -> -    throw({asn1_error,{get_line(hd(Tokens)),get(asn1_module), -		       [got,get_token(hd(Tokens)),expected,'INCLUDES']}}). -%%parse_ContainedSubtype(Tokens) -> %this option is moved to parse_SubtypeElements -%%    parse_Type(Tokens). +    parse_error(Tokens).  parse_UpperEndpoint([{'<',_}|Rest]) ->      parse_UpperEndpoint(lt,Rest); @@ -3025,33 +2202,38 @@ parse_UpperEndpoint(Tokens) ->      parse_UpperEndpoint(false,Tokens).  parse_UpperEndpoint(Lt,Tokens) -> -    Flist = [ fun([{'MAX',_}|T]) -> {'MAX',T} end, -	      fun parse_Value/1], -    case (catch parse_or(Tokens,Flist)) of -	{'EXIT',Reason} -> -	    exit(Reason); -	AsnErr = {asn1_error,_} -> -	    throw(AsnErr); -	{Value,Rest2} when Lt == lt -> +    Flist = [fun parse_MAX/1, +	     fun parse_Value/1], +    case parse_or(Tokens, Flist) of +	{Value,Rest2} when Lt =:= lt ->  	    {{lt,Value},Rest2};  	{Value,Rest2} ->  	    {Value,Rest2}      end. +parse_MIN([{'MIN',_}|T]) -> +    {'MIN',T}; +parse_MIN(Tokens) -> +    parse_error(Tokens). + +parse_MAX([{'MAX',_}|T]) -> +    {'MAX',T}; +parse_MAX(Tokens) -> +    parse_error(Tokens). +  parse_TypeConstraints(Tokens) -> -    parse_TypeConstraints(Tokens,[]). +    parse_TypeConstraints(Tokens, []). -parse_TypeConstraints([{identifier,_,_}|Rest],Acc) -> +parse_TypeConstraints([#identifier{}|Rest], Acc) ->      {ComponentConstraint,Rest2} = parse_ComponentConstraint(Rest),      case Rest2 of  	[{',',_}|Rest3] -> -	    parse_TypeConstraints(Rest3,[ComponentConstraint|Acc]); +	    parse_TypeConstraints(Rest3, [ComponentConstraint|Acc]);  	_ -> -	    {lists:reverse([ComponentConstraint|Acc]),Rest2} +	    {lists:reverse(Acc, [ComponentConstraint]),Rest2}      end; -parse_TypeConstraints([H|_T],_) -> -    throw({asn1_error,{get_line(H),get(asn1_module), -		       [got,get_token(H),expected,identifier]}}). +parse_TypeConstraints(Tokens, _) -> +    parse_error(Tokens).  parse_ComponentConstraint(Tokens = [{'(',_}|_Rest]) ->      {ValueConstraint,Rest2} = parse_Constraint(Tokens), @@ -3071,145 +2253,36 @@ parse_PresenceConstraint(Tokens) ->      {asn1_empty,Tokens}. -% merge_constraints({Rlist,ExtList}) -> % extensionmarker in constraint -%     {merge_constraints(Rlist,[],[]), -%      merge_constraints(ExtList,[],[])}; - -%% An arg with a constraint with extension marker will look like -%% [#constraint{c={Root,Ext}}|Rest] -	  merge_constraints(Clist) ->      merge_constraints(Clist, [], []). -merge_constraints([Ch|Ct],Cacc, Eacc) -> -    NewEacc = case Ch#constraint.e of -		  undefined -> Eacc; -		  E -> [E|Eacc] -	      end, -    merge_constraints(Ct,[fixup_constraint(Ch#constraint.c)|Cacc],NewEacc); - -merge_constraints([],Cacc,[]) -> -%%    lists:flatten(Cacc); +merge_constraints([#constraint{c=C,e=E}|T], Cacc0, Eacc0) -> +    Eacc = case E of +	       undefined -> Eacc0; +	       E -> [E|Eacc0] +	   end, +    Cacc = [C|Cacc0], +    merge_constraints(T, Cacc, Eacc); +merge_constraints([], Cacc, []) ->      lists:reverse(Cacc); -merge_constraints([],Cacc,Eacc) -> -%%    lists:flatten(Cacc) ++ [{'Errors',Eacc}]. -    lists:reverse(Cacc) ++ [{'Errors',Eacc}]. - - -fixup_constraint(C) -> -    case C of -	{'SingleValue',SubType} when element(1,SubType) == 'ContainedSubtype' -> -	    SubType; -	{'SingleValue',V} when is_list(V) -> -	    C; -	%%	    [C,{'ValueRange',{lists:min(V),lists:max(V)}}];  -	%% bug, turns wrong when an element in V is a reference to a defined value -	{'PermittedAlphabet',{'SingleValue',V}} when is_list(V) -> -	    %%sort and remove duplicates -	    V2 = {'SingleValue', -		  ordsets:from_list(lists:flatten(V))}, -	    {'PermittedAlphabet',V2}; -	{'PermittedAlphabet',{'SingleValue',V}} -> -	    V2 = {'SingleValue',[V]}, -	    {'PermittedAlphabet',V2}; -	{'SizeConstraint',Sc} -> -	    {'SizeConstraint',fixup_size_constraint(Sc)}; -	 -	List when is_list(List) ->  %% In This case maybe a union or intersection -	    [fixup_constraint(Xc)||Xc <- List]; -	Other -> -	    Other -    end. +merge_constraints([], Cacc, Eacc) -> +    lists:reverse(Cacc) ++ [{element_set,{'Errors',Eacc},none}]. -fixup_size_constraint({'ValueRange',{Lb,Ub}}) -> -	{Lb,Ub}; -fixup_size_constraint({{'ValueRange',R},[]}) -> -	{R,[]}; -fixup_size_constraint({[],{'ValueRange',R}}) -> -	{[],R}; -fixup_size_constraint({{'ValueRange',R1},{'ValueRange',R2}}) -> -	{R1,R2}; -fixup_size_constraint({'SingleValue',[Sv]}) -> -	fixup_size_constraint({'SingleValue',Sv}); -fixup_size_constraint({'SingleValue',L}) when is_list(L) -> -	ordsets:from_list(L); -fixup_size_constraint({'SingleValue',L}) -> -	{L,L}; -fixup_size_constraint({'SizeConstraint',C}) -> -    %% this is a second SIZE -    fixup_size_constraint(C); -fixup_size_constraint({C1,C2}) -> -    %% this is with extension marks -    {turn2vr(fixup_size_constraint(C1)), extension_size(fixup_size_constraint(C2))}; -fixup_size_constraint(CList) when is_list(CList) -> -    [fixup_constraint(Xc)||Xc <- CList]. -    -turn2vr(L) when is_list(L) -> -    L2 =[X||X<-ordsets:from_list(L),is_integer(X)], -    case L2 of -	[H|_] -> -	    {H,hd(lists:reverse(L2))}; -	_ -> -	    L -    end; -turn2vr(VR) -> -    VR. -extension_size({I,I}) -> -    [I]; -extension_size({I1,I2}) -> -    [I1,I2]; -extension_size(C) -> -    C. - -get_line({_,Pos,Token}) when is_integer(Pos),is_atom(Token) -> +get_line({Token,Pos,_}) when is_integer(Pos), is_atom(Token) ->      Pos;  get_line({Token,Pos}) when is_integer(Pos),is_atom(Token) -> -    Pos; -get_line(_) -> -    undefined. - -get_token({_,Pos,Token}) when is_integer(Pos),is_atom(Token) -> -    Token; +    Pos. + +get_token({valuefieldreference,_,FieldName}) -> +    list_to_atom([$&|atom_to_list(FieldName)]); +get_token({typefieldreference,_,FieldName}) -> +    list_to_atom([$&|atom_to_list(FieldName)]); +get_token({Token,Pos,Value}) when is_integer(Pos), is_atom(Token) -> +    Value;  get_token({'$end',Pos}) when is_integer(Pos) -> -    undefined; +    'END-OF-FILE';  get_token({Token,Pos}) when is_integer(Pos),is_atom(Token) -> -    Token; -get_token(_) -> -    undefined. - -prioritize_error(ErrList) -> -    case lists:keymember(asn1_error,1,ErrList) of -	false -> % only asn1_assignment_error -> take the last -	    lists:last(ErrList); -	true -> % contains errors from deeper in a Type -	    NewErrList = [_Err={_,_}|_RestErr] = -		lists:filter(fun({asn1_error,_})->true;(_)->false end, -			     ErrList), -	    SplitErrs = -		lists:splitwith(fun({_,X})-> -					case element(1,X) of -					    Int when is_integer(Int) -> true; -					    _ -> false -					end -				end, -				NewErrList), -	    case SplitErrs of -		{[],UndefPosErrs} -> % if no error with Positon exists -		    lists:last(UndefPosErrs); -		{IntPosErrs,_} -> -		    IntPosReasons = lists:map(fun(X)->element(2,X) end,IntPosErrs), -		    SortedReasons = lists:keysort(1,IntPosReasons), -		    {asn1_error,lists:last(SortedReasons)} -	    end -    end. - -%% most_prio_error([H={_,Reason}|T],Atom,Err) when is_atom(Atom) -> -%%     most_prio_error(T,element(1,Reason),H); -%% most_prio_error([H={_,Reason}|T],Greatest,Err) -> -%%     case element(1,Reason) of -%% 	Pos when is_integer(Pos),Pos>Greatest -> -%% 	    most_prio_error( - +    Token.  tref2Exttref(#typereference{pos=Pos,val=Name}) ->      #'Externaltypereference'{pos=Pos, @@ -3226,19 +2299,5 @@ identifier2Extvalueref(#identifier{pos=Pos,val=Name}) ->  			      module=resolve_module(Name),  			      value=Name}. -%% lookahead_assignment/1 checks that the next sequence of tokens -%% in Token contain a valid assignment or the -%% 'END' token. Otherwise an exception is thrown. -lookahead_assignment([{'END',_}|_Rest]) -> -    ok; -lookahead_assignment(Tokens) -> -    parse_Assignment(Tokens), -    ok. -	 -is_pre_defined_class('TYPE-IDENTIFIER') -> -    true; -is_pre_defined_class('ABSTRACT-SYNTAX') -> -    true; -is_pre_defined_class(_) -> -    false. -     +parse_error(Tokens) -> +    throw({asn1_error,{parse_error,Tokens}}).  | 
