diff options
author | Hans Bolinder <[email protected]> | 2010-06-22 09:42:44 +0200 |
---|---|---|
committer | Hans Bolinder <[email protected]> | 2011-03-10 12:57:37 +0100 |
commit | 8052b98f596db048467c0c57cbaac1d3a27687ad (patch) | |
tree | 144fcf14894c8a5c7df3778d7b1d91fa6a72a1cb /lib/edoc/src/edoc_parser.yrl | |
parent | cc5885e81da81dc52bd7890ff3612a48d2f4a9f2 (diff) | |
download | otp-8052b98f596db048467c0c57cbaac1d3a27687ad.tar.gz otp-8052b98f596db048467c0c57cbaac1d3a27687ad.tar.bz2 otp-8052b98f596db048467c0c57cbaac1d3a27687ad.zip |
Make Erlang specifications and types available in EDoc
It is now possible to use Erlang specifications and types in EDoc
documentation. Erlang specifications and types will be used unless
there is also a function specification (@spec) or a type alias (@type)
with the same name. In the current implementation the placement of
-spec matters: it should be placed where the @spec would otherwise
have been placed.
Not all Erlang types are included in the documentation, but only those
exported by some export_type declaration or used by some documented
Erlang specification (-spec).
There is currently no support for overloaded Erlang specifications.
The syntax definitions of EDoc have been augmented to cope with most
of the Erlang types. (But we recommend that Erlang types should be
used instead.)
edoc:read_source() takes one new option, report_missing_types.
edoc_layout:module() takes one new option, pretty_printer.
Diffstat (limited to 'lib/edoc/src/edoc_parser.yrl')
-rw-r--r-- | lib/edoc/src/edoc_parser.yrl | 106 |
1 files changed, 79 insertions, 27 deletions
diff --git a/lib/edoc/src/edoc_parser.yrl b/lib/edoc/src/edoc_parser.yrl index 91ee5a1b2b..6943f1bdb8 100644 --- a/lib/edoc/src/edoc_parser.yrl +++ b/lib/edoc/src/edoc_parser.yrl @@ -24,21 +24,22 @@ %% %% Author contact: [email protected] %% -%% $Id$ +%% $Id $ %% %% ===================================================================== Nonterminals start spec func_type utype_list utype_tuple utypes utype ptypes ptype -nutype function_name where_defs defs def typedef etype throws qname ref -aref mref lref pref var_list vars fields field. +nutype function_name where_defs defs defs2 def typedef etype +throws qname ref aref mref lref pref var_list vars fields field +futype_list bin_base_type bin_unit_type. Terminals -atom float integer var string start_spec start_typedef start_throws +atom float integer var an_var string start_spec start_typedef start_throws start_ref '(' ')' ',' '.' '->' '{' '}' '[' ']' '|' '+' ':' '::' '=' '/' '//' '*' -'#' 'where'. +'#' 'where' '<<' '>>' '..' '...'. Rootsymbol start. @@ -52,9 +53,9 @@ qname -> atom: [tok_val('$1')]. qname -> qname '.' atom: [tok_val('$3') | '$1']. spec -> func_type where_defs: - #t_spec{type = '$1', defs = lists:reverse('$2')}. + #t_spec{type = '$1', defs = '$2'}. spec -> function_name func_type where_defs: - #t_spec{name = '$1', type = '$2', defs = lists:reverse('$3')}. + #t_spec{name = '$1', type = '$2', defs = '$3'}. where_defs -> 'where' defs: '$2'. where_defs -> defs: '$1'. @@ -66,13 +67,15 @@ func_type -> utype_list '->' utype: %% Paired with line number, for later error reporting -utype_list -> '(' ')' : {[], tok_line('$1')}. utype_list -> '(' utypes ')' : {lists:reverse('$2'), tok_line('$1')}. -utype_tuple -> '{' '}' : []. +futype_list -> utype_list : '$1'. +futype_list -> '(' '...' ')' : {[#t_var{name = '...'}], tok_line('$1')}. + utype_tuple -> '{' utypes '}' : lists:reverse('$2'). %% Produced in reverse order. +utypes -> '$empty' : []. utypes -> utype : ['$1']. utypes -> utypes ',' utype : ['$3' | '$1']. @@ -90,20 +93,25 @@ ptypes -> ptypes '|' ptype : ['$3' | '$1']. ptype -> var : #t_var{name = tok_val('$1')}. ptype -> atom : #t_atom{val = tok_val('$1')}. ptype -> integer: #t_integer{val = tok_val('$1')}. +ptype -> integer '..' integer: #t_integer_range{from = tok_val('$1'), + to = tok_val('$3')}. ptype -> float: #t_float{val = tok_val('$1')}. ptype -> utype_tuple : #t_tuple{types = '$1'}. ptype -> '[' ']' : #t_nil{}. ptype -> '[' utype ']' : #t_list{type = '$2'}. +ptype -> '[' utype ',' '...' ']' : #t_nonempty_list{type = '$2'}. ptype -> utype_list: - if length(element(1, '$1')) == 1 -> + if length(element(1, '$1')) == 1 -> %% there must be exactly one utype in the list hd(element(1, '$1')); + %% Replace last line when releasing next major release: + %% #t_paren{type = hd(element(1, '$1'))}; length(element(1, '$1')) == 0 -> return_error(element(2, '$1'), "syntax error before: ')'"); true -> return_error(element(2, '$1'), "syntax error before: ','") end. -ptype -> utype_list '->' ptype: +ptype -> futype_list '->' ptype: #t_fun{args = element(1, '$1'), range = '$3'}. ptype -> '#' atom '{' '}' : #t_record{name = #t_atom{val = tok_val('$2')}}. @@ -111,17 +119,45 @@ ptype -> '#' atom '{' fields '}' : #t_record{name = #t_atom{val = tok_val('$2')}, fields = lists:reverse('$4')}. ptype -> atom utype_list: - #t_type{name = #t_name{name = tok_val('$1')}, - args = element(1, '$2')}. -ptype -> qname ':' atom utype_list : + case {tok_val('$1'), element(1, '$2')} of + {nil, []} -> + %% Prefer '[]' before 'nil(). Due to + %% compatibility with Erlang types, which do not + %% separate '[]' from 'nil()'. + #t_nil{}; + {list, [T]} -> + %% Prefer '[T]' before 'list(T). Due to + %% compatibility with Erlang types, which do not + %% separate '[T]' from 'list(T)'. + #t_list{type = T}; + {'fun', [#t_fun{}=Fun]} -> + %% An incompatible change as compared to EDOc 0.7.6.6. + %% Due to compatibility with Erlang types. + Fun; + {'fun', []} -> + #t_type{name = #t_name{name = function}}; + {Name, Args} -> + #t_type{name = #t_name{name = Name}, + args = Args} + end. +ptype -> qname ':' atom utype_list : #t_type{name = #t_name{module = qname('$1'), name = tok_val('$3')}, args = element(1, '$4')}. -ptype -> '//' atom '/' qname ':' atom utype_list : +ptype -> '//' atom '/' qname ':' atom utype_list : #t_type{name = #t_name{app = tok_val('$2'), module = qname('$4'), name = tok_val('$6')}, args = element(1, '$7')}. +ptype -> '<<' '>>' : #t_binary{}. +ptype -> '<<' bin_base_type '>>' : #t_binary{base_size = '$2'}. +ptype -> '<<' bin_unit_type '>>' : #t_binary{unit_size = '$2'}. +ptype -> '<<' bin_base_type ',' bin_unit_type '>>' : + #t_binary{base_size = '$2', unit_size = '$4'}. + +bin_base_type -> an_var ':' integer: tok_val('$3'). + +bin_unit_type -> an_var ':' an_var '*' integer : tok_val('$5'). %% Produced in reverse order. fields -> field : ['$1']. @@ -130,18 +166,19 @@ fields -> fields ',' field : ['$3' | '$1']. field -> atom '=' utype : #t_field{name = #t_atom{val = tok_val('$1')}, type = '$3'}. -%% Produced in reverse order. defs -> '$empty' : []. -defs -> defs def : ['$2' | '$1']. -defs -> defs ',' def : ['$3' | '$1']. +defs -> def defs2 : ['$1' | lists:reverse('$2')]. + +%% Produced in reverse order. +defs2 -> '$empty' : []. +defs2 -> defs2 def : ['$2' | '$1']. +defs2 -> defs2 ',' def : ['$3' | '$1']. def -> var '=' utype: #t_def{name = #t_var{name = tok_val('$1')}, type = '$3'}. -def -> atom var_list '=' utype: - #t_def{name = #t_type{name = #t_name{name = tok_val('$1')}, - args = '$2'}, - type = '$4'}. +def -> atom '(' utypes ')' '=' utype: + build_def(tok_val('$1'), '$2', '$3', '$6'). var_list -> '(' ')' : []. var_list -> '(' vars ')' : lists:reverse('$2'). @@ -153,12 +190,12 @@ vars -> vars ',' var : [#t_var{name = tok_val('$3')} | '$1']. typedef -> atom var_list where_defs: #t_typedef{name = #t_name{name = tok_val('$1')}, args = '$2', - defs = lists:reverse('$3')}. + defs = '$3'}. typedef -> atom var_list '=' utype where_defs: #t_typedef{name = #t_name{name = tok_val('$1')}, args = '$2', type = '$4', - defs = lists:reverse('$5')}. + defs = '$5'}. %% References @@ -195,7 +232,7 @@ etype -> utype: '$1'. throws -> etype where_defs: #t_throws{type = '$1', - defs = lists:reverse('$2')}. + defs = '$2'}. %% (commented out for now) %% Header @@ -297,7 +334,22 @@ union(Ts) -> end. annotate(T, A) -> ?add_t_ann(T, A). - + +build_def(S, P, As, T) -> + case all_vars(As) of + true -> + #t_def{name = #t_type{name = #t_name{name = S}, + args = lists:reverse(As)}, + type = T}; + false -> + return_error(element(2, P), "variable expected after '('") + end. + +all_vars([#t_var{} | As]) -> + all_vars(As); +all_vars(As) -> + As =:= []. + %% --------------------------------------------------------------------- %% @doc EDoc type specification parsing. Parses the content of @@ -379,7 +431,7 @@ parse_param(S, L) -> {S1, S2} = edoc_lib:split_at_space(edoc_lib:strip_space(S)), case edoc_lib:strip_space(S1) of "" -> throw_error(parse_param, L); - Name -> + Name -> Text = edoc_lib:strip_space(S2), {list_to_atom(Name), edoc_wiki:parse_xml(Text, L)} end. |