diff options
Diffstat (limited to 'lib/stdlib/src/erl_scan.erl')
-rw-r--r-- | lib/stdlib/src/erl_scan.erl | 445 |
1 files changed, 287 insertions, 158 deletions
diff --git a/lib/stdlib/src/erl_scan.erl b/lib/stdlib/src/erl_scan.erl index f2e9d2d7b9..b7975c6ed2 100644 --- a/lib/stdlib/src/erl_scan.erl +++ b/lib/stdlib/src/erl_scan.erl @@ -93,7 +93,7 @@ -type text_fun() :: fun((atom(), string()) -> boolean()). -type option() :: 'return' | 'return_white_spaces' | 'return_comments' | 'text' | {'reserved_word_fun', resword_fun()} - | {'text_fun', text_fun()}. + | {'text_fun', text_fun()} | {'compiler_internal', [term()]}. -type options() :: option() | [option()]. -type symbol() :: atom() | float() | integer() | string(). -type token() :: {category(), Anno :: erl_anno:anno(), symbol()} @@ -108,7 +108,11 @@ text_fun = fun(_, _) -> false end :: text_fun(), ws = false :: boolean(), comment = false :: boolean(), - has_fun = false :: boolean()}). + has_fun = false :: boolean(), + %% True if requested to parse %ssa%-check comments + checks = false :: boolean(), + %% True if we're scanning inside a %ssa%-check comment + in_check = false :: boolean()}). %%---------------------------------------------------------------------------- @@ -264,15 +268,15 @@ string_thing(_) -> "string". -define(WHITE_SPACE(C), is_integer(C) andalso (C >= $\000 andalso C =< $\s orelse C >= $\200 andalso C =< $\240)). --define(DIGIT(C), C >= $0 andalso C =< $9). --define(CHAR(C), is_integer(C), C >= 0). +-define(DIGIT(C), (is_integer(C) andalso $0 =< C andalso C =< $9)). +-define(CHAR(C), (is_integer(C) andalso 0 =< C andalso C < 16#110000)). -define(UNICODE(C), - is_integer(C) andalso + (is_integer(C) andalso (C >= 0 andalso C < 16#D800 orelse C > 16#DFFF andalso C < 16#FFFE orelse - C > 16#FFFF andalso C =< 16#10FFFF)). + C > 16#FFFF andalso C =< 16#10FFFF))). --define(UNI255(C), C >= 0, C =< 16#ff). +-define(UNI255(C), (is_integer(C) andalso 0 =< C andalso C =< 16#ff)). options(Opts0) when is_list(Opts0) -> Opts = lists:foldr(fun expand_opt/2, [], Opts0), @@ -287,6 +291,8 @@ options(Opts0) when is_list(Opts0) -> WS = proplists:get_bool(return_white_spaces, Opts), Txt = proplists:get_bool(text, Opts), TxtFunOpt = proplists:get_value(text_fun, Opts, none), + Internal = proplists:get_value(compiler_internal, Opts, []), + Checks = proplists:get_bool(ssa_checks, Internal), DefTxtFun = fun(_, _) -> Txt end, {HasFun, TxtFun} = if @@ -298,7 +304,8 @@ options(Opts0) when is_list(Opts0) -> comment = Comment, ws = WS, text_fun = TxtFun, - has_fun = HasFun}; + has_fun = HasFun, + checks = Checks}; options(Opt) -> options([Opt]). @@ -330,8 +337,8 @@ expand_opt(O, Os) -> tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof -> case Fun(Cs, St, Line, Col, Toks, Any) of - {more,{Cs0,Ncol,Ntoks,Nline,Nany,Nfun}} -> - {more,{erl_scan_continuation,Cs0,Ncol,Ntoks,Nline,St,Nany,Nfun}}; + {more,{Cs0,Nst,Ncol,Ntoks,Nline,Nany,Nfun}} -> + {more,{erl_scan_continuation,Cs0,Ncol,Ntoks,Nline,Nst,Nany,Nfun}}; {ok,Toks0,eof,Nline,Ncol} -> Res = case Toks0 of [] -> @@ -348,8 +355,8 @@ tokens1(Cs, St, Line, Col, Toks, Fun, Any) when ?STRING(Cs); Cs =:= eof -> string1(Cs, St, Line, Col, Toks) -> case scan1(Cs, St, Line, Col, Toks) of - {more,{Cs0,Ncol,Ntoks,Nline,Any,Fun}} -> - case Fun(Cs0++eof, St, Nline, Ncol, Ntoks, Any) of + {more,{Cs0,Nst,Ncol,Ntoks,Nline,Any,Fun}} -> + case Fun(Cs0++eof, Nst, Nline, Ncol, Ntoks, Any) of {ok,Toks1,_Rest,Line2,Col2} -> {ok,lists:reverse(Toks1),location(Line2, Col2)}; {{error,_,_}=Error,_Rest} -> @@ -363,7 +370,7 @@ string1(Cs, St, Line, Col, Toks) -> Error end. -scan(Cs, St, Line, Col, Toks, _) -> +scan(Cs, #erl_scan{}=St, Line, Col, Toks, _) -> scan1(Cs, St, Line, Col, Toks). scan1([$\s|Cs], St, Line, Col, Toks) when St#erl_scan.ws -> @@ -374,10 +381,6 @@ scan1([$\n|Cs], St, Line, Col, Toks) when St#erl_scan.ws -> scan_newline(Cs, St, Line, Col, Toks); scan1([$\n|Cs], St, Line, Col, Toks) -> skip_white_space(Cs, St, Line+1, new_column(Col, 1), Toks, 0); -scan1([C|Cs], St, Line, Col, Toks) when C >= $A, C =< $Z -> - scan_variable(Cs, St, Line, Col, Toks, [C]); -scan1([C|Cs], St, Line, Col, Toks) when C >= $a, C =< $z -> - scan_atom(Cs, St, Line, Col, Toks, [C]); %% Optimization: some very common punctuation characters: scan1([$,|Cs], St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ",", ',', 1); @@ -397,21 +400,29 @@ scan1([$;|Cs], St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ";", ';', 1); scan1([$_=C|Cs], St, Line, Col, Toks) -> scan_variable(Cs, St, Line, Col, Toks, [C]); -%% More punctuation characters below. +scan1([$\%=C|Cs], St, Line, Col, Toks) when St#erl_scan.checks -> + scan_check(Cs, St, Line, Col, Toks, [C]); scan1([$\%|Cs], St, Line, Col, Toks) when not St#erl_scan.comment -> skip_comment(Cs, St, Line, Col, Toks, 1); scan1([$\%=C|Cs], St, Line, Col, Toks) -> scan_comment(Cs, St, Line, Col, Toks, [C]); +%% More punctuation characters below. +scan1([C|_], _St, _Line, _Col0, _Toks) when not ?CHAR(C) -> + error({not_character,C}); +scan1([C|Cs], St, Line, Col, Toks) when C >= $A, C =< $Z -> + scan_variable(Cs, St, Line, Col, Toks, [C]); +scan1([C|Cs], St, Line, Col, Toks) when C >= $a, C =< $z -> + scan_atom(Cs, St, Line, Col, Toks, [C]); scan1([C|Cs], St, Line, Col, Toks) when ?DIGIT(C) -> scan_number(Cs, St, Line, Col, Toks, [C], no_underscore); scan1("..."++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "...", '...', 3); -scan1(".."=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1(".."=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; scan1(".."++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "..", '..', 2); -scan1("."=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("."=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; scan1([$.=C|Cs], St, Line, Col, Toks) -> scan_dot(Cs, St, Line, Col, Toks, [C]); scan1([$"|Cs], St, Line, Col, Toks) -> %" Emacs @@ -443,8 +454,8 @@ scan1([C|Cs], St, Line, Col, Toks) when ?WHITE_SPACE(C) -> %% ?= for the maybe ... else ... end construct scan1("?="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "?=", '?=', 2); -scan1("?"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("?"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% << <- <= scan1("<<"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "<<", '<<', 2); @@ -452,62 +463,62 @@ scan1("<-"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "<-", '<-', 2); scan1("<="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "<=", '<=', 2); -scan1("<"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("<"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% >> >= scan1(">>"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ">>", '>>', 2); scan1(">="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ">=", '>=', 2); -scan1(">"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1(">"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% -> -- scan1("->"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "->", '->', 2); scan1("--"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "--", '--', 2); -scan1("-"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("-"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% ++ scan1("++"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "++", '++', 2); -scan1("+"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("+"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% =:= =/= =< == => scan1("=:="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "=:=", '=:=', 3); -scan1("=:"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("=:"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; scan1("=/="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "=/=", '=/=', 3); -scan1("=/"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("=/"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; scan1("=<"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "=<", '=<', 2); scan1("=>"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "=>", '=>', 2); scan1("=="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "==", '==', 2); -scan1("="=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("="=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% /= scan1("/="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "/=", '/=', 2); -scan1("/"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("/"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% || scan1("||"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "||", '||', 2); -scan1("|"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1("|"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% := scan1(":="++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, ":=", ':=', 2); %% :: for typed records scan1("::"++Cs, St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "::", '::', 2); -scan1(":"=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1(":"=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; %% Optimization: punctuation characters less than 127: scan1([$=|Cs], St, Line, Col, Toks) -> tok2(Cs, St, Line, Col, Toks, "=", '=', 1); @@ -552,44 +563,54 @@ scan1([C|Cs], St, Line, Col, Toks) when ?UNI255(C) -> scan1([C|Cs], _St, Line, Col, _Toks) when ?CHAR(C) -> Ncol = incr_column(Col, 1), scan_error({illegal,character}, Line, Col, Line, Ncol, Cs); -scan1([]=Cs, _St, Line, Col, Toks) -> - {more,{Cs,Col,Toks,Line,[],fun scan/6}}; +scan1([]=Cs, St, Line, Col, Toks) -> + {more,{Cs,St,Col,Toks,Line,[],fun scan/6}}; scan1(eof=Cs, _St, Line, Col, Toks) -> {ok,Toks,Cs,Line,Col}. +scan_atom_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_atom(Cs, St, Line, Col, Toks, Ncs). + scan_atom(Cs0, St, Line, Col, Toks, Ncs0) -> case scan_name(Cs0, Ncs0) of {more,Ncs} -> - {more,{[],Col,Toks,Line,Ncs,fun scan_atom/6}}; + {more,{[],St,Col,Toks,Line,Ncs,fun scan_atom_fun/6}}; {Wcs,Cs} -> - case catch list_to_atom(Wcs) of - Name when is_atom(Name) -> + try list_to_atom(Wcs) of + Name -> case (St#erl_scan.resword_fun)(Name) of true -> tok2(Cs, St, Line, Col, Toks, Wcs, Name); false -> tok3(Cs, St, Line, Col, Toks, atom, Wcs, Name) - end; - _Error -> + end + catch + _:_ -> Ncol = incr_column(Col, length(Wcs)), scan_error({illegal,atom}, Line, Col, Line, Ncol, Cs) end end. +scan_variable_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_variable(Cs, St, Line, Col, Toks, Ncs). + scan_variable(Cs0, St, Line, Col, Toks, Ncs0) -> case scan_name(Cs0, Ncs0) of {more,Ncs} -> - {more,{[],Col,Toks,Line,Ncs,fun scan_variable/6}}; + {more,{[],St,Col,Toks,Line,Ncs,fun scan_variable_fun/6}}; {Wcs,Cs} -> - case catch list_to_atom(Wcs) of - Name when is_atom(Name) -> - tok3(Cs, St, Line, Col, Toks, var, Wcs, Name); - _Error -> + try list_to_atom(Wcs) of + Name -> + tok3(Cs, St, Line, Col, Toks, var, Wcs, Name) + catch + _:_ -> Ncol = incr_column(Col, length(Wcs)), scan_error({illegal,var}, Line, Col, Line, Ncol, Cs) end end. +scan_name([C|_]=Cs, Ncs) when not ?CHAR(C) -> + {lists:reverse(Ncs),Cs}; scan_name([C|Cs], Ncs) when C >= $a, C =< $z -> scan_name(Cs, [C|Ncs]); scan_name([C|Cs], Ncs) when C >= $A, C =< $Z -> @@ -616,6 +637,9 @@ scan_name(Cs, Ncs) -> false -> [] end). +scan_dot([C|_]=Cs, St, Line, Col, Toks, Ncs) + when St#erl_scan.in_check, C =/= $. -> + tok2(Cs, St#erl_scan{in_check=false}, Line, Col, Toks, Ncs, '.', 1); scan_dot([$%|_]=Cs, St, Line, Col, Toks, Ncs) -> Anno = anno(Line, Col, St, ?STR(dot, St, Ncs)), {ok,[{dot,Anno}|Toks],Cs,Line,incr_column(Col, 1)}; @@ -658,25 +682,36 @@ scan_newline([$\r|Cs], St, Line, Col, Toks) -> newline_end(Cs, St, Line, Col, Toks, 2, "\n\r"); scan_newline([$\f|Cs], St, Line, Col, Toks) -> newline_end(Cs, St, Line, Col, Toks, 2, "\n\f"); -scan_newline([], _St, Line, Col, Toks) -> - {more,{[$\n],Col,Toks,Line,[],fun scan/6}}; +scan_newline([], St, Line, Col, Toks) -> + {more,{[$\n],St,Col,Toks,Line,[],fun scan/6}}; scan_newline(Cs, St, Line, Col, Toks) -> scan_nl_white_space(Cs, St, Line, Col, Toks, "\n"). +scan_nl_spcs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N) -> + scan_nl_spcs(Cs, St, Line, Col, Toks, N). + scan_nl_spcs([$\s|Cs], St, Line, Col, Toks, N) when N < 17 -> scan_nl_spcs(Cs, St, Line, Col, Toks, N+1); -scan_nl_spcs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_nl_spcs/6}}; +scan_nl_spcs([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun scan_nl_spcs_fun/6}}; scan_nl_spcs(Cs, St, Line, Col, Toks, N) -> newline_end(Cs, St, Line, Col, Toks, N, nl_spcs(N)). +scan_nl_tabs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N) -> + scan_nl_tabs(Cs, St, Line, Col, Toks, N). + scan_nl_tabs([$\t|Cs], St, Line, Col, Toks, N) when N < 11 -> scan_nl_tabs(Cs, St, Line, Col, Toks, N+1); -scan_nl_tabs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_nl_tabs/6}}; +scan_nl_tabs([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun scan_nl_tabs_fun/6}}; scan_nl_tabs(Cs, St, Line, Col, Toks, N) -> newline_end(Cs, St, Line, Col, Toks, N, nl_tabs(N)). +scan_nl_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_nl_white_space(Cs, St, Line, Col, Toks, Ncs). + %% Note: returning {more,Cont} is meaningless here; one could just as %% well return several tokens. But since tokens() scans up to a full %% stop anyway, nothing is gained by not collecting all white spaces. @@ -689,10 +724,11 @@ scan_nl_white_space([$\n|Cs], St, Line, Col, Toks, Ncs0) -> Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)), Token = {white_space,Anno,Ncs}, scan_newline(Cs, St, Line+1, new_column(Col, length(Ncs)), [Token|Toks]); -scan_nl_white_space([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) -> +scan_nl_white_space([C|Cs], St, Line, Col, Toks, Ncs) + when ?WHITE_SPACE(C) -> scan_nl_white_space(Cs, St, Line, Col, Toks, [C|Ncs]); -scan_nl_white_space([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_nl_white_space/6}}; +scan_nl_white_space([]=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_nl_white_space_fun/6}}; scan_nl_white_space(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Ncs) -> Anno = anno(Line), @@ -706,40 +742,54 @@ scan_nl_white_space(Cs, St, Line, Col, Toks, Ncs0) -> newline_end(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _N, Ncs) -> scan1(Cs, St, Line+1, Col, [{white_space,anno(Line),Ncs}|Toks]); -newline_end(Cs, St, Line, Col, Toks, N, Ncs) -> +newline_end(Cs, #erl_scan{}=St, Line, Col, Toks, N, Ncs) -> Anno = anno(Line, Col, St, ?STR(white_space, St, Ncs)), scan1(Cs, St, Line+1, new_column(Col, N), [{white_space,Anno,Ncs}|Toks]). +scan_spcs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N), N >= 1 -> + scan_spcs(Cs, St, Line, Col, Toks, N). + scan_spcs([$\s|Cs], St, Line, Col, Toks, N) when N < 16 -> scan_spcs(Cs, St, Line, Col, Toks, N+1); -scan_spcs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_spcs/6}}; +scan_spcs([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun scan_spcs_fun/6}}; scan_spcs(Cs, St, Line, Col, Toks, N) -> white_space_end(Cs, St, Line, Col, Toks, N, spcs(N)). +scan_tabs_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) + when is_integer(N), N >= 1 -> + scan_tabs(Cs, St, Line, Col, Toks, N). + scan_tabs([$\t|Cs], St, Line, Col, Toks, N) when N < 10 -> scan_tabs(Cs, St, Line, Col, Toks, N+1); -scan_tabs([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun scan_tabs/6}}; +scan_tabs([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun scan_tabs_fun/6}}; scan_tabs(Cs, St, Line, Col, Toks, N) -> white_space_end(Cs, St, Line, Col, Toks, N, tabs(N)). +skip_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) -> + skip_white_space(Cs, St, Line, Col, Toks, N). + skip_white_space([$\n|Cs], St, Line, Col, Toks, _N) -> skip_white_space(Cs, St, Line+1, new_column(Col, 1), Toks, 0); skip_white_space([C|Cs], St, Line, Col, Toks, N) when ?WHITE_SPACE(C) -> skip_white_space(Cs, St, Line, Col, Toks, N+1); -skip_white_space([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun skip_white_space/6}}; +skip_white_space([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun skip_white_space_fun/6}}; skip_white_space(Cs, St, Line, Col, Toks, N) -> scan1(Cs, St, Line, incr_column(Col, N), Toks). +scan_white_space_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_white_space(Cs, St, Line, Col, Toks, Ncs). + %% Maybe \t and \s should break the loop. scan_white_space([$\n|_]=Cs, St, Line, Col, Toks, Ncs) -> white_space_end(Cs, St, Line, Col, Toks, length(Ncs), lists:reverse(Ncs)); scan_white_space([C|Cs], St, Line, Col, Toks, Ncs) when ?WHITE_SPACE(C) -> scan_white_space(Cs, St, Line, Col, Toks, [C|Ncs]); -scan_white_space([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_white_space/6}}; +scan_white_space([]=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_white_space_fun/6}}; scan_white_space(Cs, St, Line, Col, Toks, Ncs) -> white_space_end(Cs, St, Line, Col, Toks, length(Ncs), lists:reverse(Ncs)). @@ -751,7 +801,7 @@ white_space_end(Cs, St, Line, Col, Toks, N, Ncs) -> scan_char([$\\|Cs]=Cs0, St, Line, Col, Toks) -> case scan_escape(Cs, incr_column(Col, 2)) of more -> - {more,{[$$|Cs0],Col,Toks,Line,[],fun scan/6}}; + {more,{[$$|Cs0],St,Col,Toks,Line,[],fun scan/6}}; {error,Ncs,Error,Ncol} -> scan_error(Error, Line, Col, Line, Ncol, Ncs); {eof,Ncol} -> @@ -773,16 +823,16 @@ scan_char([C|Cs], St, Line, Col, Toks) when ?UNICODE(C) -> scan1(Cs, St, Line, incr_column(Col, 2), [{char,Anno,C}|Toks]); scan_char([C|_Cs], _St, Line, Col, _Toks) when ?CHAR(C) -> scan_error({illegal,character}, Line, Col, Line, incr_column(Col, 1), eof); -scan_char([], _St, Line, Col, Toks) -> - {more,{[$$],Col,Toks,Line,[],fun scan/6}}; +scan_char([], St, Line, Col, Toks) -> + {more,{[$$],St,Col,Toks,Line,[],fun scan/6}}; scan_char(eof, _St, Line, Col, _Toks) -> scan_error(char, Line, Col, Line, incr_column(Col, 1), eof). -scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> +scan_string(Cs, #erl_scan{}=St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> case scan_string0(Cs, St, Line, Col, $\", Str, Wcs) of %" {more,Ncs,Nline,Ncol,Nstr,Nwcs} -> State = {Nwcs,Nstr,Line0,Col0}, - {more,{Ncs,Ncol,Toks,Nline,State,fun scan_string/6}}; + {more,{Ncs,St,Ncol,Toks,Nline,State,fun scan_string/6}}; {char_error,Ncs,Error,Nline,Ncol,EndCol} -> scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs); {error,Nline,Ncol,Nwcs,Ncs} -> @@ -793,22 +843,23 @@ scan_string(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> scan1(Ncs, St, Nline, Ncol, [{string,Anno,Nwcs}|Toks]) end. -scan_qatom(Cs, St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> +scan_qatom(Cs, #erl_scan{}=St, Line, Col, Toks, {Wcs,Str,Line0,Col0}) -> case scan_string0(Cs, St, Line, Col, $\', Str, Wcs) of %' {more,Ncs,Nline,Ncol,Nstr,Nwcs} -> State = {Nwcs,Nstr,Line0,Col0}, - {more,{Ncs,Ncol,Toks,Nline,State,fun scan_qatom/6}}; + {more,{Ncs,St,Ncol,Toks,Nline,State,fun scan_qatom/6}}; {char_error,Ncs,Error,Nline,Ncol,EndCol} -> scan_error(Error, Nline, Ncol, Nline, EndCol, Ncs); {error,Nline,Ncol,Nwcs,Ncs} -> Estr = string:slice(Nwcs, 0, 16), % Expanded escape chars. scan_error({string,$\',Estr}, Line0, Col0, Nline, Ncol, Ncs); %' - {Ncs,Nline,Ncol,Nstr,Nwcs} -> - case catch list_to_atom(Nwcs) of + {Ncs,Nline,Ncol,Nstr,Nwcs} -> + try list_to_atom(Nwcs) of A when is_atom(A) -> Anno = anno(Line0, Col0, St, ?STR(atom, St, Nstr)), - scan1(Ncs, St, Nline, Ncol, [{atom,Anno,A}|Toks]); - _ -> + scan1(Ncs, St, Nline, Ncol, [{atom,Anno,A}|Toks]) + catch + _:_ -> scan_error({illegal,atom}, Line0, Col0, Nline, Ncol, Ncs) end end. @@ -884,10 +935,11 @@ scan_string1([]=Cs, Line, Col, _Q, Str, Wcs) -> scan_string1(eof, Line, Col, _Q, _Str, Wcs) -> {error,Line,Col,lists:reverse(Wcs),eof}. --define(OCT(C), C >= $0, C =< $7). --define(HEX(C), C >= $0 andalso C =< $9 orelse - C >= $A andalso C =< $F orelse - C >= $a andalso C =< $f). +-define(OCT(C), (is_integer(C) andalso $0 =< C andalso C =< $7)). +-define(HEX(C), (is_integer(C) andalso + (C >= $0 andalso C =< $9 orelse + C >= $A andalso C =< $F orelse + C >= $a andalso C =< $f))). %% \<1-3> octal digits scan_escape([O1,O2,O3|Cs], Col) when ?OCT(O1), ?OCT(O2), ?OCT(O3) -> @@ -917,12 +969,14 @@ scan_escape([$x,H1], _Col) when ?HEX(H1) -> more; scan_escape([$x|Cs], Col) -> {error,Cs,{illegal,character},incr_column(Col, 1)}; -%% \^X -> CTL-X -scan_escape([$^=C0,$\n=C|Cs], Col) -> - {nl,C,[C0,C],Cs,new_column(Col, 1)}; +%% \^X -> Control-X scan_escape([$^=C0,C|Cs], Col) when ?CHAR(C) -> - Val = C band 31, - {Val,[C0,C],Cs,incr_column(Col, 2)}; + case caret_char_code(C) of + error -> + {error,[C|Cs],{illegal,character},incr_column(Col, 1)}; + Code -> + {Code,[C0,C],Cs,incr_column(Col, 2)} + end; scan_escape([$^], _Col) -> more; scan_escape([$^|eof], Col) -> @@ -939,26 +993,31 @@ scan_escape([], _Col) -> scan_escape(eof, Col) -> {eof,Col}. -scan_hex([C|Cs], no_col=Col, Wcs) when ?HEX(C) -> - scan_hex(Cs, Col, [C|Wcs]); scan_hex([C|Cs], Col, Wcs) when ?HEX(C) -> - scan_hex(Cs, Col+1, [C|Wcs]); + scan_hex(Cs, incr_column(Col, 1), [C|Wcs]); scan_hex(Cs, Col, Wcs) -> - scan_esc_end(Cs, Col, Wcs, 16, "x{"). + scan_hex_end(Cs, Col, Wcs, "x{"). -scan_esc_end([$}|Cs], Col, Wcs0, B, Str0) -> +scan_hex_end([$}|Cs], Col, [], _Str) -> + %% Empty escape sequence. + {error,Cs,{illegal,character},incr_column(Col, 1)}; +scan_hex_end([$}|Cs], Col, Wcs0, Str0) -> Wcs = lists:reverse(Wcs0), - case catch erlang:list_to_integer(Wcs, B) of + try list_to_integer(Wcs, 16) of Val when ?UNICODE(Val) -> {Val,Str0++Wcs++[$}],Cs,incr_column(Col, 1)}; - _ -> + _Val -> + {error,Cs,{illegal,character},incr_column(Col, 1)} + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. {error,Cs,{illegal,character},incr_column(Col, 1)} end; -scan_esc_end([], _Col, _Wcs, _B, _Str0) -> +scan_hex_end([], _Col, _Wcs, _Str0) -> more; -scan_esc_end(eof, Col, _Wcs, _B, _Str0) -> +scan_hex_end(eof, Col, _Wcs, _Str0) -> {eof,Col}; -scan_esc_end(Cs, Col, _Wcs, _B, _Str0) -> +scan_hex_end(Cs, Col, _Wcs, _Str0) -> {error,Cs,{illegal,character},Col}. escape_char($n) -> $\n; % \n = LF @@ -972,7 +1031,11 @@ escape_char($s) -> $\s; % \s = SPC escape_char($d) -> $\d; % \d = DEL escape_char(C) -> C. -scan_number(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +caret_char_code($?) -> 16#7f; +caret_char_code(C) when $@ =< C, C =< $_; $a =< C, C =< $z -> C band 16#1f; +caret_char_code(_) -> error. + +scan_number(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_number(Cs, St, Line, Col, Toks, Ncs, Us). scan_number([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -980,30 +1043,36 @@ scan_number([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> scan_number([$_,Next|Cs], St, Line, Col, Toks, [Prev|_]=Ncs, _Us) when ?DIGIT(Next) andalso ?DIGIT(Prev) -> scan_number(Cs, St, Line, Col, Toks, [Next,$_|Ncs], with_underscore); -scan_number([$_]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; +scan_number([$_]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; scan_number([$.,C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> scan_fraction(Cs, St, Line, Col, Toks, [C,$.|Ncs], Us); -scan_number([$.]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; +scan_number([$.]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; scan_number([$#|Cs]=Cs0, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_integer(remove_digit_separators(Ncs, Us)) of - B when B >= 2, B =< 1+$Z-$A+10 -> + try list_to_integer(remove_digit_separators(Ncs, Us)) of + B when is_integer(B), 2 =< B, B =< 1+$Z-$A+10 -> Bcs = Ncs++[$#], scan_based_int(Cs, St, Line, Col, Toks, B, [], Bcs, no_underscore); - B -> + B when is_integer(B) -> Len = length(Ncs), scan_error({base,B}, Line, Col, Line, incr_column(Col, Len), Cs0) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. + scan_error({illegal,base}, Line, Col, Line, Col, Cs0) end; -scan_number([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; +scan_number([]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_number/6}}; scan_number(Cs, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_integer(remove_digit_separators(Ncs, Us)) of - N when is_integer(N) -> - tok3(Cs, St, Line, Col, Toks, integer, Ncs, N); - _ -> + try list_to_integer(remove_digit_separators(Ncs, Us), 10) of + N -> + tok3(Cs, St, Line, Col, Toks, integer, Ncs, N) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. Ncol = incr_column(Col, length(Ncs)), scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs) end. @@ -1014,11 +1083,14 @@ remove_digit_separators(Number, with_underscore) -> [C || C <- Number, C =/= $_]. -define(BASED_DIGIT(C, B), - ((?DIGIT(C) andalso C < $0 + B) - orelse (C >= $A andalso B > 10 andalso C < $A + B - 10) - orelse (C >= $a andalso B > 10 andalso C < $a + B - 10))). - -scan_based_int(Cs, St, Line, Col, Toks, {B,NCs,BCs,Us}) -> + (is_integer(C) + andalso + ((?DIGIT(C) andalso C < $0 + B) + orelse (C >= $A andalso B > 10 andalso C < $A + B - 10) + orelse (C >= $a andalso B > 10 andalso C < $a + B - 10)))). + +scan_based_int(Cs, #erl_scan{}=St, Line, Col, Toks, {B,NCs,BCs,Us}) + when is_integer(B), 2 =< B, B =< 1+$Z-$A+10 -> scan_based_int(Cs, St, Line, Col, Toks, B, NCs, BCs, Us). scan_based_int([C|Cs], St, Line, Col, Toks, B, Ncs, Bcs, Us) when @@ -1028,22 +1100,29 @@ scan_based_int([$_,Next|Cs], St, Line, Col, Toks, B, [Prev|_]=Ncs, Bcs, _Us) when ?BASED_DIGIT(Next, B) andalso ?BASED_DIGIT(Prev, B) -> scan_based_int(Cs, St, Line, Col, Toks, B, [Next,$_|Ncs], Bcs, with_underscore); -scan_based_int([$_]=Cs, _St, Line, Col, Toks, B, NCs, BCs, Us) -> - {more,{Cs,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; -scan_based_int([]=Cs, _St, Line, Col, Toks, B, NCs, BCs, Us) -> - {more,{Cs,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; -scan_based_int(Cs, St, Line, Col, Toks, B, Ncs0, Bcs, Us) -> +scan_based_int([$_]=Cs, St, Line, Col, Toks, B, NCs, BCs, Us) -> + {more,{Cs,St,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; +scan_based_int([]=Cs, St, Line, Col, Toks, B, NCs, BCs, Us) -> + {more,{Cs,St,Col,Toks,Line,{B,NCs,BCs,Us},fun scan_based_int/6}}; +scan_based_int(Cs, _St, Line, Col, _Toks, _B, [], Bcs, _Us) -> + %% No actual digits following the base. + Len = length(Bcs), + Ncol = incr_column(Col, Len), + scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs); +scan_based_int(Cs, St, Line, Col, Toks, B, Ncs0, [_|_]=Bcs, Us) -> Ncs = lists:reverse(Ncs0), - case catch erlang:list_to_integer(remove_digit_separators(Ncs, Us), B) of - N when is_integer(N) -> - tok3(Cs, St, Line, Col, Toks, integer, Bcs++Ncs, N); - _ -> + try list_to_integer(remove_digit_separators(Ncs, Us), B) of + N -> + tok3(Cs, St, Line, Col, Toks, integer, Bcs++Ncs, N) + catch + error:system_limit -> + %% Extremely unlikely to occur in practice. Len = length(Bcs)+length(Ncs), Ncol = incr_column(Col, Len), scan_error({illegal,integer}, Line, Col, Line, Ncol, Cs) end. -scan_fraction(Cs, St, Line, Col, Toks, {Ncs,Us}) -> +scan_fraction(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs,Us}) -> scan_fraction(Cs, St, Line, Col, Toks, Ncs, Us). scan_fraction([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -1051,27 +1130,27 @@ scan_fraction([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> scan_fraction([$_,Next|Cs], St, Line, Col, Toks, [Prev|_]=Ncs, _Us) when ?DIGIT(Next) andalso ?DIGIT(Prev) -> scan_fraction(Cs, St, Line, Col, Toks, [Next,$_|Ncs], with_underscore); -scan_fraction([$_]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_fraction/6}}; +scan_fraction([$_]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_fraction/6}}; scan_fraction([E|Cs], St, Line, Col, Toks, Ncs, Us) when E =:= $e; E =:= $E -> scan_exponent_sign(Cs, St, Line, Col, Toks, [E|Ncs], Us); -scan_fraction([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_fraction/6}}; +scan_fraction([]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_fraction/6}}; scan_fraction(Cs, St, Line, Col, Toks, Ncs, Us) -> float_end(Cs, St, Line, Col, Toks, Ncs, Us). -scan_exponent_sign(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +scan_exponent_sign(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_exponent_sign(Cs, St, Line, Col, Toks, Ncs, Us). scan_exponent_sign([C|Cs], St, Line, Col, Toks, Ncs, Us) when C =:= $+; C =:= $- -> scan_exponent(Cs, St, Line, Col, Toks, [C|Ncs], Us); -scan_exponent_sign([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_exponent_sign/6}}; +scan_exponent_sign([]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_exponent_sign/6}}; scan_exponent_sign(Cs, St, Line, Col, Toks, Ncs, Us) -> scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us). -scan_exponent(Cs, St, Line, Col, Toks, {Ncs, Us}) -> +scan_exponent(Cs, #erl_scan{}=St, Line, Col, Toks, {Ncs, Us}) -> scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us). scan_exponent([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> @@ -1079,23 +1158,27 @@ scan_exponent([C|Cs], St, Line, Col, Toks, Ncs, Us) when ?DIGIT(C) -> scan_exponent([$_,Next|Cs], St, Line, Col, Toks, [Prev|_]=Ncs, _) when ?DIGIT(Next) andalso ?DIGIT(Prev) -> scan_exponent(Cs, St, Line, Col, Toks, [Next,$_|Ncs], with_underscore); -scan_exponent([$_]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_exponent/6}}; -scan_exponent([]=Cs, _St, Line, Col, Toks, Ncs, Us) -> - {more,{Cs,Col,Toks,Line,{Ncs,Us},fun scan_exponent/6}}; +scan_exponent([$_]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_exponent/6}}; +scan_exponent([]=Cs, St, Line, Col, Toks, Ncs, Us) -> + {more,{Cs,St,Col,Toks,Line,{Ncs,Us},fun scan_exponent/6}}; scan_exponent(Cs, St, Line, Col, Toks, Ncs, Us) -> float_end(Cs, St, Line, Col, Toks, Ncs, Us). float_end(Cs, St, Line, Col, Toks, Ncs0, Us) -> Ncs = lists:reverse(Ncs0), - case catch list_to_float(remove_digit_separators(Ncs, Us)) of - F when is_float(F) -> - tok3(Cs, St, Line, Col, Toks, float, Ncs, F); - _ -> + try list_to_float(remove_digit_separators(Ncs, Us)) of + F -> + tok3(Cs, St, Line, Col, Toks, float, Ncs, F) + catch + _:_ -> Ncol = incr_column(Col, length(Ncs)), scan_error({illegal,float}, Line, Col, Line, Ncol, Cs) end. +skip_comment_fun(Cs, #erl_scan{}=St, Line, Col, Toks, N) -> + skip_comment(Cs, St, Line, Col, Toks, N). + skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) -> case ?UNICODE(C) of true -> @@ -1104,12 +1187,16 @@ skip_comment([C|Cs], St, Line, Col, Toks, N) when C =/= $\n, ?CHAR(C) -> Ncol = incr_column(Col, N+1), scan_error({illegal,character}, Line, Col, Line, Ncol, Cs) end; -skip_comment([]=Cs, _St, Line, Col, Toks, N) -> - {more,{Cs,Col,Toks,Line,N,fun skip_comment/6}}; +skip_comment([]=Cs, St, Line, Col, Toks, N) -> + {more,{Cs,St,Col,Toks,Line,N,fun skip_comment_fun/6}}; skip_comment(Cs, St, Line, Col, Toks, N) -> scan1(Cs, St, Line, incr_column(Col, N), Toks). -scan_comment([C|Cs], St, Line, Col, Toks, Ncs) when C =/= $\n, ?CHAR(C) -> +scan_comment_fun(Cs, #erl_scan{}=St, Line, Col, Toks, Ncs) -> + scan_comment(Cs, St, Line, Col, Toks, Ncs). + +scan_comment([C|Cs], St, Line, Col, Toks, Ncs) + when C =/= $\n, ?CHAR(C) -> case ?UNICODE(C) of true -> scan_comment(Cs, St, Line, Col, Toks, [C|Ncs]); @@ -1117,34 +1204,76 @@ scan_comment([C|Cs], St, Line, Col, Toks, Ncs) when C =/= $\n, ?CHAR(C) -> Ncol = incr_column(Col, length(Ncs)+1), scan_error({illegal,character}, Line, Col, Line, Ncol, Cs) end; -scan_comment([]=Cs, _St, Line, Col, Toks, Ncs) -> - {more,{Cs,Col,Toks,Line,Ncs,fun scan_comment/6}}; +scan_comment([]=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_comment_fun/6}}; scan_comment(Cs, St, Line, Col, Toks, Ncs0) -> Ncs = lists:reverse(Ncs0), tok3(Cs, St, Line, Col, Toks, comment, Ncs, Ncs). +scan_check("%%ssa%" ++ Cs, St, Line, Col, Toks, _Ncs) -> + scan_check1(Cs, St, Line, Toks, Col, 7); +scan_check("%%ssa"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%%ss"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%%s"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%%"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%ssa%" ++ Cs, St, Line, Col, Toks, _Ncs) -> + scan_check1(Cs, St, Line, Toks, Col, 6); +scan_check("%ssa"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%ss"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("%s"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("ssa%" ++ Cs, St, Line, Col, Toks, _Ncs) -> + scan_check1(Cs, St, Line, Toks, Col, 5); +scan_check("ssa"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("ss"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check("s"=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check([]=Cs, St, Line, Col, Toks, Ncs) -> + {more,{Cs,St,Col,Toks,Line,Ncs,fun scan_check/6}}; +scan_check(Cs, St=#erl_scan{comment=true}, Line, Col, Toks, Ncs) -> + scan_comment(Cs, St, Line, Col, Toks, Ncs); +scan_check(Cs, St, Line, Col, Toks, _Ncs) -> + skip_comment(Cs, St, Line, Col, Toks, 1). + +scan_check1(Cs, St=#erl_scan{in_check=true}, Line, Toks, Col, NoofCols) -> + %% Skip as we are already in the check mode + scan1(Cs, St, Line, incr_column(Col, NoofCols), Toks); +scan_check1(Cs, St, Line, Toks, Col, NoofCols) -> + tok2(Cs, St#erl_scan{in_check=true}, Line, + Col, Toks, "%ssa%", '%ssa%', NoofCols). + tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P) -> scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]); -tok2(Cs, St, Line, Col, Toks, Wcs, P) -> +tok2(Cs, #erl_scan{}=St, Line, Col, Toks, Wcs, P) -> Anno = anno(Line, Col, St, ?STR(P, St, Wcs)), scan1(Cs, St, Line, incr_column(Col, length(Wcs)), [{P,Anno}|Toks]). tok2(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, _Wcs, P, _N) -> scan1(Cs, St, Line, Col, [{P,anno(Line)}|Toks]); -tok2(Cs, St, Line, Col, Toks, Wcs, P, N) -> +tok2(Cs, #erl_scan{}=St, Line, Col, Toks, Wcs, P, N) -> Anno = anno(Line, Col, St, ?STR(P,St,Wcs)), scan1(Cs, St, Line, incr_column(Col, N), [{P,Anno}|Toks]). tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item, _S, Sym) -> scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]); -tok3(Cs, St, Line, Col, Toks, Item, String, Sym) -> +tok3(Cs, #erl_scan{}=St, Line, Col, Toks, Item, String, Sym) -> Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym}, scan1(Cs, St, Line, incr_column(Col, length(String)), [Token|Toks]). tok3(Cs, #erl_scan{has_fun = false}=St, Line, no_col=Col, Toks, Item, _String, Sym, _Length) -> scan1(Cs, St, Line, Col, [{Item,anno(Line),Sym}|Toks]); -tok3(Cs, St, Line, Col, Toks, Item, String, Sym, Length) -> +tok3(Cs, #erl_scan{}=St, Line, Col, Toks, Item, String, Sym, Length) -> Token = {Item,anno(Line, Col, St, ?STR(Item, St, String)),Sym}, scan1(Cs, St, Line, incr_column(Col, Length), [Token|Toks]). |