erl_parse.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,387 行 · 第 1/5 页
ERL
1,387 行
-module(erl_parse).-export([parse/1, parse_and_scan/1, format_error/1]).-file("erl_parse.yrl", 425).%% ``The contents of this file are subject to the Erlang Public License,%% Version 1.1, (the "License"); you may not use this file except in%% compliance with the License. You should have received a copy of the%% Erlang Public License along with this software. If not, it can be%% retrieved via the world wide web at http://www.erlang.org/.%% %% Software distributed under the License is distributed on an "AS IS"%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See%% the License for the specific language governing rights and limitations%% under the License.%% %% The Initial Developer of the Original Code is Ericsson Utvecklings AB.%% Portions created by Ericsson are Copyright 1999, Ericsson Utvecklings%% AB. All Rights Reserved.''%% %% $Id$%%-export([parse_form/1,parse_exprs/1,parse_term/1]).-export([normalise/1,abstract/1,tokens/1,tokens/2]).-export([abstract/2, package_segments/1]).-export([inop_prec/1,preop_prec/1,func_prec/0,max_prec/0]).%% The following directive is needed for (significantly) faster compilation%% of the generated .erl file by the HiPE compiler. Please do not remove.-compile([inline,{hipe,[{regalloc,linear_scan}]}]).%% mkop(Op, Arg) -> {op,Line,Op,Arg}.%% mkop(Left, Op, Right) -> {op,Line,Op,Left,Right}.mkop(L, {Op,Pos}, R) -> {op,Pos,Op,L,R}.mkop({Op,Pos}, A) -> {op,Pos,Op,A}.%% keep track of line info in tokensline(Tup) -> element(2, Tup).%% Entry points compatible to old erl_parse.%% These really suck and are only here until Calle gets multiple%% entry points working.parse_form(Tokens) -> parse(Tokens).parse_exprs(Tokens) -> case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],Exprs}]}} -> {ok,Exprs}; {error,E} -> {error,E} end.parse_term(Tokens) -> case parse([{atom,0,f},{'(',0},{')',0},{'->',0}|Tokens]) of {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[Expr]}]}} -> case catch normalise(Expr) of {'EXIT',_R} -> {error,{line(Expr),?MODULE,"bad term"}}; Term -> {ok,Term} end; {ok,{function,_Lf,f,0,[{clause,_Lc,[],[],[_E1,E2|_Es]}]}} -> {error,{line(E2),?MODULE,"bad term"}}; {error,E} -> {error,E} end.build_type({atom,_,any}, []) -> {type, any, []};build_type({atom,_,atom}, []) -> {type, atom, []};build_type({atom,_,binary}, []) -> {type, binary, []};build_type({atom,_,bool}, []) -> {type, bool, []};build_type({atom,_,byte}, []) -> {type, byte, []};build_type({atom,_,char}, []) -> {type, char, []};build_type({atom,_,float}, []) -> {type, float, []};build_type({atom,_,function}, []) -> {type, 'fun', []};build_type({atom,_,identifier}, []) -> {type, identifier, []};build_type({atom,_,integer}, []) -> {type, integer, []};build_type({atom,_,list}, []) -> {type, list, []};build_type({atom,_,mfa}, []) -> {type, mfa, []};build_type({atom,_,neg_integer}, []) -> {type, neg_integer, []};build_type({atom,_,non_neg_integer}, []) -> {type, non_neg_integer, []};build_type({atom,_,none}, []) -> {type, none, []};build_type({atom,_,nonempty_list}, [C,T]) -> {type, cons, [C,T]};build_type({atom,_,nonempty_possibly_improper_list}, []) -> {type, cons, []};build_type({atom,_,nonempty_posssibly_improper_list}, [C,T]) -> {type, cons, [C, T]};build_type({atom,_,number}, []) -> {type, number, []};build_type({atom,_,pid}, []) -> {type, pid, []};build_type({atom,_,port}, []) -> {type, port, []};build_type({atom,_,pos_integer}, []) -> {type, pos_integer, []};build_type({atom,_,possibly_improper_list}, [C,T]) -> {type, pos_improper_list, [C,T]};build_type({atom,_,possibly_improper_list}, []) -> {type, pos_improper_list, []};build_type({atom,_,ref}, []) -> {type, ref, []};build_type({atom,_,string}, []) -> {type, string, []};build_type({atom,_,tuple}, []) -> {type, tuple, []};build_type({atom,_,Other}, []) -> {type, var, [Other]}.build_typed_attribute({atom,La,record}, [{atom,_Ln,RecordName},RecTuple]) -> {attribute,La,record,{RecordName,record_tuple(RecTuple)}};build_typed_attribute({atom,La,spec}, [{op,_Lo,'/',{atom,_La,FunName}, {integer,_Li,FunArity}}, TypeSpec]) -> {attribute,La,type_spec,{{FunName,FunArity},TypeSpec}};build_typed_attribute({atom,La,_},_) -> error_bad_decl(La,spec).lift_unions(T1, {type, union, List}) -> {type, union, [T1|List]};lift_unions(T1, T2 = {type, _, _}) -> {type, union, [T1, T2]}.%% build_attribute(AttrName, AttrValue) ->%% {attribute,Line,module,Module}%% {attribute,Line,export,Exports}%% {attribute,Line,import,Imports}%% {attribute,Line,record,{Name,Inits}}%% {attribute,Line,file,{Name,Line}}%% {attribute,Line,Name,Val}build_attribute({atom,La,module}, Val) -> case Val of [{atom,_Lm,Module}] -> {attribute,La,module,Module}; [{atom,_Lm,Module},ExpList] -> {attribute,La,module,{Module,var_list(ExpList)}}; [Name] -> case package_segments(Name) of error -> error_bad_decl(La, module); Module -> {attribute,La,module,Module} end; [Name,ExpList] -> case package_segments(Name) of error -> error_bad_decl(La, module); Module -> {attribute,La,module,{Module,var_list(ExpList)}} end; _Other -> error_bad_decl(La, module) end;build_attribute({atom,La,export}, Val) -> case Val of [ExpList] -> {attribute,La,export,farity_list(ExpList)}; _Other -> error_bad_decl(La, export) end;build_attribute({atom,La,import}, Val) -> case Val of [Name] -> case package_segments(Name) of error -> error_bad_decl(La, import); Module -> {attribute,La,import,Module} end; [{atom,_Lm,Mod},ImpList] -> {attribute,La,import,{Mod,farity_list(ImpList)}}; [Name, ImpList] -> case package_segments(Name) of error -> error_bad_decl(La, import); Module -> {attribute,La,import,{Module,farity_list(ImpList)}} end; _Other -> error_bad_decl(La, import) end;build_attribute({atom,La,record}, Val) -> case Val of [{atom,_Ln,Record},RecTuple] -> {attribute,La,record,{Record,record_tuple(RecTuple)}}; _Other -> error_bad_decl(La, record) end;build_attribute({atom,La,file}, Val) -> case Val of [{string,_Ln,Name},{integer,_Ll,Line}] -> {attribute,La,file,{Name,Line}}; _Other -> error_bad_decl(La, file) end;build_attribute({atom,La,Attr}, Val) -> case Val of [Expr] -> {attribute,La,Attr,term(Expr)}; _Other -> return_error(La, "bad attribute") end.var_list({cons,_Lc,{var,_,V},Tail}) -> [V|var_list(Tail)];var_list({nil,_Ln}) -> [];var_list(Other) -> return_error(line(Other), "bad variable list").error_bad_decl(L, S) -> return_error(L, io_lib:format("bad ~w declaration", [S])).farity_list({cons,_Lc,{op,_Lo,'/',{atom,_La,A},{integer,_Li,I}},Tail}) -> [{A,I}|farity_list(Tail)];farity_list({nil,_Ln}) -> [];farity_list(Other) -> return_error(line(Other), "bad function arity").record_tuple({tuple,_Lt,Fields}) -> record_fields(Fields);record_tuple(Other) -> return_error(line(Other), "bad record declaration").%%record_fields([{atom,La,A}|Fields]) ->%% [{record_field,La,{atom,La,A},{atom,La,undefined},{type, any, []}}%% |record_fields(Fields)];%%record_fields([{match,_Lm,{atom,La,A},Expr}|Fields]) ->%% [{record_field,La,{atom,La,A},Expr,{type, any, []}}%% |record_fields(Fields)];%%record_fields([{typed,Expr,TypeInfo}|Fields]) ->%% [{record_field,La,FieldName,Init,_BogusTypeInfo}] = record_fields([Expr]),%% [{record_field,La,FieldName,Init,TypeInfo}|record_fields(Fields)];%%record_fields([Other|_Fields]) ->%% return_error(line(Other), "bad record field");%%record_fields([]) -> [].record_fields([{atom,La,A}|Fields]) -> [{record_field,La,{atom,La,A}}|record_fields(Fields)];record_fields([{match,_Lm,{atom,La,A},Expr}|Fields]) -> [{record_field,La,{atom,La,A},Expr}|record_fields(Fields)];record_fields([{typed,Expr,TypeInfo}|Fields]) -> [Field] = record_fields([Expr]), TypeInfo1 = case Expr of {match, _, _, _} -> TypeInfo; %% If we have an initializer. {atom, _, _} -> lift_unions({type, atom, ['undefined']}, TypeInfo) end, [{typed_record_field,Field,TypeInfo1}|record_fields(Fields)];record_fields([Other|_Fields]) -> return_error(line(Other), "bad record field");record_fields([]) -> [].term(Expr) -> case catch normalise(Expr) of {'EXIT',_R} -> return_error(line(Expr), "bad attribute"); Term -> Term end.package_segments(Name) -> package_segments(Name, [], []).package_segments({record_field, _, F1, F2}, Fs, As) -> package_segments(F1, [F2 | Fs], As);package_segments({atom, _, A}, [F | Fs], As) -> package_segments(F, Fs, [A | As]);package_segments({atom, _, A}, [], As) -> lists:reverse([A | As]);package_segments(_, _, _) -> error.%% build_function([Clause]) -> {function,Line,Name,Arity,[Clause]}build_function(Cs) -> Name = element(3, hd(Cs)), Arity = length(element(4, hd(Cs))), {function,line(hd(Cs)),Name,Arity,check_clauses(Cs, Name, Arity)}.%% build_rule([Clause]) -> {rule,Line,Name,Arity,[Clause]'}build_rule(Cs) -> Name = element(3, hd(Cs)), Arity = length(element(4, hd(Cs))), {rule,line(hd(Cs)),Name,Arity,check_clauses(Cs, Name, Arity)}.%% build_fun(Line, [Clause]) -> {'fun',Line,{clauses,[Clause]}}.build_fun(Line, Cs) -> Arity = length(element(4, hd(Cs))),
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?