icscan.erl

来自「OTP是开放电信平台的简称」· ERL 代码 · 共 451 行 · 第 1/2 页

ERL
451
字号
%% ``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$%%-module(icscan).-export([scan/2]).-include("ic.hrl").%%----------------------------------------------------------------------%%-----------------------------------------------------------------------import(lists, [reverse/1]).scan(G, File) ->    PL = call_preproc(G, File),    call_scan(G, PL).call_preproc(G, File) ->    case ic_options:get_opt(G, use_preproc) of	true -> 	    icpreproc:preproc(G, File);	false ->	    case catch file:read_file(File) of		{ok, Bin} ->		    binary_to_list(Bin);		Other ->		    exit(Other)	    end    end.call_scan(G, PL) ->    BE = ic_options:get_opt(G, be),    RSL = scan(G, BE, PL, 1, []),    lists:reverse(RSL).%% Guard macros used at top scan functions only-define(is_number(X), X >= $0 , X =< $9).-define(is_upper(X), X >= $A , X =< $Z).-define(is_lower(X), X >= $a, X =< $z).-define(is_hex_uc(X), X >= $A , X =< $F).-define(is_hex_lc(X), X >= $a , X =< $f).-define(is_octal(X), X >=$0, X =< $7).%% Handle:%%  const wchar aWChar = L'X';scan(G, BE, [$L, $'|Str], Line, Out) ->    scan_const(G, BE, wchar, Str, [], Line, Out);scan(G, BE, [$L, $"|Str], Line, Out) ->    scan_const(G, BE, wstring, Str, [], Line, Out);scan(G, BE, [$_, X|Str], Line, Out) when ?is_upper(X) ->    scan_name(G, BE, Str, [X], false, Line, Out);scan(G, BE, [$_, X|Str], Line, Out) when ?is_lower(X) ->    scan_name(G, BE, Str, [X], false, Line, Out);scan(G, BE, [X|Str], Line, Out) when ?is_upper(X) ->    scan_name(G, BE, Str, [X], true, Line, Out);scan(G, BE, [X|Str], Line, Out) when ?is_lower(X) ->    scan_name(G, BE, Str, [X], true, Line, Out);scan(G, BE, [X|Str], Line, Out) when ?is_number(X) ->    scan_number(G, BE, Str, [X], Line, Out);scan(G, BE, [9| T], Line, Out) -> scan(G, BE, T, Line, Out);scan(G, BE, [32| T], Line, Out) -> scan(G, BE, T, Line, Out);scan(G, BE, [$\r|Str], Line, Out) ->    scan(G, BE, Str, Line, Out);scan(G, BE, [$\n|Str], Line, Out) ->    scan(G, BE, Str, Line+1, Out);scan(G, BE, [$:, $: | Str], Line, Out) ->    scan(G, BE, Str, Line, [{'::', Line} | Out]);scan(G, BE, [$/, $/ | Str], Line, Out) ->    Rest = skip_to_nl(Str),    scan(G, BE, Rest, Line, Out);scan(G, BE, [$/, $* | Str], Line, Out) ->    Rest = skip_comment(Str),    scan(G, BE, Rest, Line, Out);scan(G, BE, [$", $\\|Str], Line, Out) ->    scan_const(G, BE, string, [$\\|Str], [], Line, Out);scan(G, BE, [$"|Str], Line, Out) ->    scan_const(G, BE, string, Str, [], Line, Out);scan(G, BE, [$', $\\|Str], Line, Out) ->    scan_const(G, BE, char, [$\\|Str], [], Line, Out);scan(G, BE, [$'|Str], Line, Out) ->    scan_const(G, BE, char, Str, [], Line, Out);scan(G, BE, [$\\|Str], Line, Out) ->    scan_const(G, BE, escaped, [$\\|Str], [], Line, Out);scan(G, BE, [$. | Str], Line, Out) ->    scan_frac(G, BE, Str, [$.], Line, Out);scan(G, BE, [$# | Str], Line, Out) ->    scan_preproc(G, BE, Str, Line, Out);scan(G, BE, [$<, $< | Str], Line, Out) ->    scan(G, BE, Str, Line, [{'<<', Line} | Out]);scan(G, BE, [$>, $> | Str], Line, Out) ->    scan(G, BE, Str, Line, [{'>>', Line} | Out]);scan(G, BE, [C|Str], Line, Out) ->    scan(G, BE, Str, Line, [{list_to_atom([C]), Line} | Out]);	    scan(_G, _BE, [], _Line, Out) ->    Out.scan_number(G, BE, [X|Str], [$0], Line, Out) when X == $X ; X ==$x ->    case Str of	[D|_TmpStr] when ?is_number(D); ?is_hex_uc(D); ?is_hex_lc(D) ->	    {Num,Rest} = scan_hex_number(Str,0),	    scan(G, BE, Rest, Line, [{'<integer_literal>', Line, 				  integer_to_list(Num)} | Out]);	[D|TmpStr] -> 	    scan(G, BE, TmpStr, Line, [{list_to_atom([D]), Line} | Out])    end;scan_number(G, BE, Str, [$0], Line, Out) ->    %% If an integer literal starts with a 0 it may indicate that    %% it is represented as an octal number. But, it can also be a fixed    %% type which must use padding to match a fixed typedef. For example:    %% typedef fixed<5,2> fixed52;    %% 123.45d, 123.00d and 023.00d is all valid fixed values.    %% Naturally, a float can be defined as 0.14 or 00.14.    case pre_scan_number(Str, [], octal) of	octal ->	    {Num, Rest} = scan_octal_number(Str,0),	    scan(G, BE, Rest, Line, [{'<integer_literal>', Line, 				  integer_to_list(Num)} | Out]);	{fixed, Fixed, Rest} ->	    scan(G, BE, Rest, Line, [{'<fixed_pt_literal>', Line, Fixed} | Out]);	float ->	    %% Not very likely that someone defines a constant as 00.14 but ... 	    NewStr = remove_leading_zeroes(Str),	    scan(G, BE, NewStr, Line, Out)    end;scan_number(G, BE, [X|Str], Accum, Line, Out) when ?is_number(X) ->    scan_number(G, BE, Str, [X|Accum], Line, Out);scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$. ->    scan_frac(G, BE, Str, [X|Accum], Line, Out);scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$e ; X==$e ->    scan_exp(G, BE, Str, [X|Accum], Line, Out);scan_number(G, BE, [X|Str], Accum, Line, Out) when X==$D ; X==$d ->    scan(G, BE, Str, Line, [{'<fixed_pt_literal>', Line,			 (lists:reverse(Accum))} | Out]);scan_number(G, BE, Str, Accum, Line, Out) ->    scan(G, BE, Str, Line, [{'<integer_literal>', Line,			 (lists:reverse(Accum))} | Out]).remove_leading_zeroes([$0|Rest]) ->    remove_leading_zeroes(Rest);remove_leading_zeroes(L) ->    L.scan_hex_number([X|Rest],Acc) when X >=$a, X =< $f ->    scan_hex_number(Rest,(Acc bsl 4) + (X - $a + 10)); scan_hex_number([X|Rest],Acc) when X >=$A, X =< $F ->    scan_hex_number(Rest,(Acc bsl 4) + (X - $A + 10)); scan_hex_number([X|Rest],Acc) when X >=$0, X =< $9 ->    scan_hex_number(Rest,(Acc bsl 4) + (X-$0));scan_hex_number(Rest,Acc) ->     {Acc,Rest}.pre_scan_number([$d|Rest], Acc, _) ->    {fixed, [$0|lists:reverse(Acc)], Rest};pre_scan_number([$D|Rest], Acc, _) ->    {fixed, [$0|lists:reverse(Acc)], Rest};pre_scan_number([$.|Rest], Acc, _) ->    %% Actually, we don't know if it's a float since it can be a fixed.    pre_scan_number(Rest, [$.|Acc], float);pre_scan_number([X|_], _Acc, _) when X == $E ; X ==$e  ->    %% Now we now it's a float.    float;pre_scan_number([X|Rest], Acc, Type) when ?is_number(X) ->    pre_scan_number(Rest, [X|Acc], Type);pre_scan_number(_Rest, _Acc, Type) ->    %% At this point we know it's a octal or float.    Type.scan_octal_number([X|Rest],Acc) when ?is_octal(X) ->    scan_octal_number(Rest,(Acc bsl 3) + (X-$0)); scan_octal_number(Rest,Acc) ->     {Acc, Rest}.%% Floating point number scan.%%%%	Non trivial scan. A float consists of an integral part, a%%	decimal point, a fraction part, an e or E and a signed integer%%	exponent. Either the integer part or the fraction part but not%%	both may be missing, and either the decimal point or the%%	exponent part but not both may be missing. The exponent part%%	must consist of an e or E and a possibly signed exponent.%%%%	Analysis shows that "1." ".7" "1e2" ".5e-3" "1.7e2" "1.7e-2"%%	is allowed and "1" ".e9" is not. The sign is only allowed just%%	after an e or E. The scanner reads a number as an integer%%	until it encounters a "." so the integer part only error case%%	will not be caught in the scanner (but rather in expression%%	evaluation)scan_frac(G, _BE, [$e | _Str], [$.], Line, _Out) ->    ic_error:fatal_error(G, {illegal_float, Line});scan_frac(G, _BE, [$E | _Str], [$.], Line, _Out) ->    ic_error:fatal_error(G, {illegal_float, Line});scan_frac(G, BE, Str, Accum, Line, Out) ->    scan_frac2(G, BE, Str, Accum, Line, Out).scan_frac2(G, BE, [X|Str], Accum, Line, Out) when ?is_number(X) ->    scan_frac2(G, BE, Str, [X|Accum], Line, Out);scan_frac2(G, BE, [X|Str], Accum, Line, Out) when X==$e ; X==$E ->    scan_exp(G, BE, Str, [X|Accum], Line, Out);%% The following case is for fixed (e.g. 123.45d).scan_frac2(G, BE, [X|Str], Accum, Line, Out) when X==$d ; X==$D ->    scan(G, BE, Str, Line, [{'<fixed_pt_literal>', Line,			 (lists:reverse(Accum))} | Out]);scan_frac2(G, BE, Str, Accum, Line, Out) ->

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?