1%%
2%% %CopyrightBegin%
3%%
4%% Copyright Ericsson AB 2000-2015. All Rights Reserved.
5%%
6%% Licensed under the Apache License, Version 2.0 (the "License");
7%% you may not use this file except in compliance with the License.
8%% You may obtain a copy of the License at
9%%
10%%     http://www.apache.org/licenses/LICENSE-2.0
11%%
12%% Unless required by applicable law or agreed to in writing, software
13%% distributed under the License is distributed on an "AS IS" BASIS,
14%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15%% See the License for the specific language governing permissions and
16%% limitations under the License.
17%%
18%% %CopyrightEnd%
19%%
20
21-module(xref_scanner).
22
23-include("xref.hrl").
24
25-export([scan/1]).
26
27scan(Chars) ->
28    case erl_scan:string(Chars) of
29	{ok, Tokens, _Line}  ->
30	    {ok, lex(a1(Tokens))};
31	{error, {Line,Module,Info}, _EndLine} ->
32	    {error, Module:format_error(Info), Line}
33    end.
34
35a1([{'-',N},{integer,N,1} | L]) ->
36    [{integer,N,-1} | a1(L)];
37a1([T | L]) ->
38    [T | a1(L)];
39a1([]) ->
40    [].
41
42-define(MFA(M,F,A,N), {atom,N,M}, {':',_}, {atom,_,F}, {'/',_}, {integer,_,A}).
43-define(MFA2(M,F,A,N),
44	{'{',N},{atom,_,M},{',',_},{atom,_,F},{',',_},{integer,_,A},{'}',_}).
45-define(DECL(N1,N2,T), {':',N1},{var,N2,T}).
46
47lex([{atom,N,V1},{'->',_},{atom,_,V2} | L]) ->
48    Constant = {constant, unknown, edge, {V1,V2}},
49    [{edge,N,Constant} | lex(L)];
50lex([{'{',N},{atom,_,V1},{',',_},{atom,_,V2},{'}',_} | L]) ->
51    Constant = {constant, unknown, edge, {V1,V2}},
52    [{edge,N,Constant} | lex(L)];
53lex([?MFA(M,F,A,N),{'->',_},?MFA(M2,F2,A2,_) | L]) ->
54    Constant = {constant, 'Fun', edge, {{M,F,A},{M2,F2,A2}}},
55    [{edge,N,Constant} | lex(L)];
56lex([?MFA(M,F,A,N) | L]) ->
57    Constant = {constant, 'Fun', vertex, {M,F,A}},
58    [{vertex,N,Constant} | lex(L)];
59lex([{'{',N},?MFA2(M,F,A,_),{',',_},?MFA2(M2,F2,A2,_),{'}',_} | L]) ->
60    Constant = {constant, 'Fun', edge, {{M,F,A},{M2,F2,A2}}},
61    [{edge,N,Constant} | lex(L)];
62lex([?MFA2(M,F,A,N) | L]) ->
63    Constant = {constant, 'Fun', vertex, {M,F,A}},
64    [{vertex,N,Constant} | lex(L)];
65lex([?DECL(N1,N2,Decl) | L]) ->
66    case is_type(Decl) of
67	false -> [?DECL(N1, N2, Decl) | lex(L)];
68	true -> [{decl,N1,Decl} | lex(L)]
69    end;
70lex([{':',N},{'=',_} | L]) ->
71    [{':=',N} | lex(L)];
72lex([{'||',N},{'|',_} | L]) ->
73    [{'|||',N} | lex(L)];
74lex([V={var,N,Var} | L]) ->
75    T = case is_type(Var) of
76	    false -> V;
77	    true -> {cast,N,Var}
78	end,
79    [T | lex(L)];
80lex([T | Ts]) ->
81    [T | lex(Ts)];
82lex([]) ->
83    [{'$end', erl_anno:new(?XREF_END_LINE)}].
84
85is_type('Rel')         -> true;
86is_type('App')         -> true;
87is_type('Mod')         -> true;
88is_type('Fun')         -> true;
89is_type('Lin')         -> true;
90is_type('LLin')        -> true;
91is_type('XLin')        -> true;
92is_type('ELin')        -> true;
93is_type('XXL')         -> true;
94is_type(_)             -> false.
95