erl_parse.erl
来自「OTP是开放电信平台的简称」· ERL 代码 · 共 1,387 行 · 第 1/5 页
ERL
1,387 行
{'fun',Line,{clauses,check_clauses(Cs, 'fun', Arity)}}.check_clauses(Cs, Name, Arity) -> mapl(fun ({clause,L,N,As,G,B}) when N =:= Name, length(As) =:= Arity -> {clause,L,As,G,B}; ({clause,L,_N,_As,_G,_B}) -> return_error(L, "head mismatch") end, Cs).build_try(L,Es,Scs,{Ccs,As}) -> {'try',L,Es,Scs,Ccs,As}.%% mapl(F,List)%% an alternative map which always maps from left to right%% and makes it possible to interrupt the mapping with throw on%% the first occurence from left as expected.%% can be removed when the jam machine (and all other machines)%% uses the standardized (Erlang 5.0) evaluation order (from left to right)mapl(F, [H|T]) -> V = F(H), [V | mapl(F,T)];mapl(_, []) -> [].%% normalise(AbsTerm)%% abstract(Term)%% Convert between the abstract form of a term and a term.normalise({char,_,C}) -> C;normalise({integer,_,I}) -> I;normalise({float,_,F}) -> F;normalise({atom,_,A}) -> A;normalise({string,_,S}) -> S;normalise({nil,_}) -> [];normalise({bin,_,Fs}) -> {value, B, _} = eval_bits:expr_grp(Fs, [], fun(E, _) -> {value, normalise(E), []} end, [], true), B;normalise({cons,_,Head,Tail}) -> [normalise(Head)|normalise(Tail)];normalise({tuple,_,Args}) -> list_to_tuple(normalise_list(Args));%% Atom dot-notation, as in 'foo.bar.baz'normalise({record_field,_,_,_}=A) -> case package_segments(A) of error -> erlang:fault({badarg, A}); As -> list_to_atom(packages:concat(As)) end;%% Special case for unary +/-.normalise({op,_,'+',{char,_,I}}) -> I;normalise({op,_,'+',{integer,_,I}}) -> I;normalise({op,_,'+',{float,_,F}}) -> F;normalise({op,_,'-',{char,_,I}}) -> -I; %Weird, but compatible!normalise({op,_,'-',{integer,_,I}}) -> -I;normalise({op,_,'-',{float,_,F}}) -> -F;normalise(X) -> erlang:fault({badarg, X}).normalise_list([H|T]) -> [normalise(H)|normalise_list(T)];normalise_list([]) -> [].abstract(T) when is_integer(T) -> {integer,0,T};abstract(T) when is_float(T) -> {float,0,T};abstract(T) when is_atom(T) -> {atom,0,T};abstract([]) -> {nil,0};abstract(B) when is_binary(B) -> {bin, 0, lists:map(fun(Byte) -> {bin_element, 0, {integer, 0, Byte}, default, default} end, binary_to_list(B))};abstract([C|T]) when is_integer(C), 0 =< C, C < 256 -> abstract_string(T, [C]);abstract([H|T]) -> {cons,0,abstract(H),abstract(T)};abstract(Tuple) when is_tuple(Tuple) -> {tuple,0,abstract_list(tuple_to_list(Tuple))}.abstract_string([C|T], String) when is_integer(C), 0 =< C, C < 256 -> abstract_string(T, [C|String]);abstract_string([], String) -> {string, 0, lists:reverse(String)};abstract_string(T, String) -> not_string(String, abstract(T)).not_string([C|T], Result) -> not_string(T, {cons, 0, {integer, 0, C}, Result});not_string([], Result) -> Result.abstract_list([H|T]) -> [abstract(H)|abstract_list(T)];abstract_list([]) -> [].%%% abstract/2 keeps the line numberabstract(T, Line) when is_integer(T) -> {integer,Line,T};abstract(T, Line) when is_float(T) -> {float,Line,T};abstract(T, Line) when is_atom(T) -> {atom,Line,T};abstract([], Line) -> {nil,Line};abstract(B, Line) when is_binary(B) -> {bin, Line, lists:map(fun(Byte) -> {bin_element, Line, {integer, Line, Byte}, default, default} end, binary_to_list(B))};abstract([C|T], Line) when is_integer(C), 0 =< C, C < 256 -> abstract_string(T, [C], Line);abstract([H|T], Line) -> {cons,Line,abstract(H, Line),abstract(T, Line)};abstract(Tuple, Line) when is_tuple(Tuple) -> {tuple,Line,abstract_list(tuple_to_list(Tuple), Line)}.abstract_string([C|T], String, Line) when is_integer(C), 0 =< C, C < 256 -> abstract_string(T, [C|String], Line);abstract_string([], String, Line) -> {string, Line, lists:reverse(String)};abstract_string(T, String, Line) -> not_string(String, abstract(T, Line), Line).not_string([C|T], Result, Line) -> not_string(T, {cons, Line, {integer, Line, C}, Result}, Line);not_string([], Result, _Line) -> Result.abstract_list([H|T], Line) -> [abstract(H, Line)|abstract_list(T, Line)];abstract_list([], _Line) -> [].%% tokens(AbsTerm) -> [Token]%% tokens(AbsTerm, More) -> [Token]%% Generate a list of tokens representing the abstract term.tokens(Abs) -> tokens(Abs, []).tokens({char,L,C}, More) -> [{char,L,C}|More];tokens({integer,L,N}, More) -> [{integer,L,N}|More];tokens({float,L,F}, More) -> [{float,L,F}|More];tokens({atom,L,A}, More) -> [{atom,L,A}|More];tokens({var,L,V}, More) -> [{var,L,V}|More];tokens({string,L,S}, More) -> [{string,L,S}|More];tokens({nil,L}, More) -> [{'[',L},{']',L}|More];tokens({cons,L,Head,Tail}, More) -> [{'[',L}|tokens(Head, tokens_tail(Tail, More))];tokens({tuple,L,[]}, More) -> [{'{',L},{'}',L}|More];tokens({tuple,L,[E|Es]}, More) -> [{'{',L}|tokens(E, tokens_tuple(Es, line(E), More))].tokens_tail({cons,L,Head,Tail}, More) -> [{',',L}|tokens(Head, tokens_tail(Tail, More))];tokens_tail({nil,L}, More) -> [{']',L}|More];tokens_tail(Other, More) -> L = line(Other), [{'|',L}|tokens(Other, [{']',L}|More])].tokens_tuple([E|Es], Line, More) -> [{',',Line}|tokens(E, tokens_tuple(Es, line(E), More))];tokens_tuple([], Line, More) -> [{'}',Line}|More].%% Give the relative precedences of operators.inop_prec('=') -> {150,100,100};inop_prec('!') -> {150,100,100};inop_prec('orelse') -> {160,150,150};inop_prec('andalso') -> {200,160,160};inop_prec('==') -> {300,200,300};inop_prec('/=') -> {300,200,300};inop_prec('=<') -> {300,200,300};inop_prec('<') -> {300,200,300};inop_prec('>=') -> {300,200,300};inop_prec('>') -> {300,200,300};inop_prec('=:=') -> {300,200,300};inop_prec('=/=') -> {300,200,300};inop_prec('++') -> {400,300,300};inop_prec('--') -> {400,300,300};inop_prec('+') -> {400,400,500};inop_prec('-') -> {400,400,500};inop_prec('bor') -> {400,400,500};inop_prec('bxor') -> {400,400,500};inop_prec('bsl') -> {400,400,500};inop_prec('bsr') -> {400,400,500};inop_prec('or') -> {400,400,500};inop_prec('xor') -> {400,400,500};inop_prec('*') -> {500,500,600};inop_prec('/') -> {500,500,600};inop_prec('div') -> {500,500,600};inop_prec('rem') -> {500,500,600};inop_prec('band') -> {500,500,600};inop_prec('and') -> {500,500,600};inop_prec('#') -> {800,700,800};inop_prec(':') -> {900,800,900};inop_prec('.') -> {900,900,1000}.preop_prec('catch') -> {0,100};preop_prec('+') -> {600,700};preop_prec('-') -> {600,700};preop_prec('bnot') -> {600,700};preop_prec('not') -> {600,700};preop_prec('#') -> {700,800}.func_prec() -> {800,700}.max_prec() -> 1000.-file("/ldisk/daily_build/otp_prebuild_r11b.2007-06-11_19/otp_src_R11B-5/bootstrap/lib/parsetools/include/yeccpre.hrl", 0).%% ``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 $%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% The parser generator will insert appropriate declarations before this line.%parse(Tokens) -> yeccpars0(Tokens, false).parse_and_scan({F, A}) -> % Fun or {M, F} yeccpars0([], {F, A});parse_and_scan({M, F, A}) -> yeccpars0([], {{M, F}, A}).format_error(Message) -> case io_lib:deep_char_list(Message) of true -> Message; _ -> io_lib:write(Message) end.% To be used in grammar files to throw an error message to the parser% toplevel. Doesn't have to be exported!-compile({nowarn_unused_function,{return_error,2}}).return_error(Line, Message) -> throw({error, {Line, ?MODULE, Message}}).yeccpars0(Tokens, MFA) -> try yeccpars1(Tokens, MFA, 0, [], []) catch throw: {error, {_Line, ?MODULE, _M}} = Error -> Error % probably from return_error/1 end.% Don't change yeccpars1/6 too much, it is called recursively by yeccpars2/8!yeccpars1([Token | Tokens], Tokenizer, State, States, Vstack) -> yeccpars2(State, element(1, Token), States, Vstack, Token, Tokens, Tokenizer);yeccpars1([], {F, A}, State, States, Vstack) -> case apply(F, A) of {ok, Tokens, _Endline} -> yeccpars1(Tokens, {F, A}, State, States, Vstack); {eof, _Endline} -> yeccpars1([], false, State, States, Vstack); {error, Descriptor, _Endline} -> {error, Descriptor} end;yeccpars1([], false, State, States, Vstack) -> yeccpars2(State, '$end', States, Vstack, {'$end', 999999}, [], false).
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?