Release coccinelle-0.1.8
[bpt/coccinelle.git] / parsing_c / comment_annotater_c.ml
1 (* Yoann Padioleau
2 *
3 * Copyright (C) 2009 University of Urbana Champaign
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License (GPL)
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * file license.txt for more details.
13 *)
14
15 open Common
16
17 module T = Token_c
18
19
20 (*****************************************************************************)
21 (* Prelude *)
22 (*****************************************************************************)
23
24 (* A trimmed down version of my comment_annotater of CComment. In CComment
25 * I was also trying to associate the comment to the relevant entity, not
26 * just the closest token (e.g. a function comment is not placed next to the
27 * identifier of the function but before its return type or storage).
28 *)
29
30
31 (*****************************************************************************)
32 (* Helpers *)
33 (*****************************************************************************)
34
35 let is_comment_or_space_or_stuff tok =
36 Token_helpers.is_not_in_ast tok && Token_helpers.is_origin tok
37
38 (* coupling with token_helpers.is_not_in_ast, and of course with tokens_c.ml *)
39 let convert_relevant_tokens x =
40 assert (Token_helpers.is_origin x);
41
42 match x with
43 | Parser_c.TCommentSpace info ->
44 Token_c.TCommentSpace, (Ast_c.parse_info_of_info info)
45 | Parser_c.TCommentNewline info ->
46 Token_c.TCommentNewline, (Ast_c.parse_info_of_info info)
47
48 | Parser_c.TComment info ->
49 Token_c.TComment, (Ast_c.parse_info_of_info info)
50
51 (* the passed tokens because of our limited handling of cpp *)
52 | Parser_c.TCommentCpp(cppcommentkind, info) ->
53 Token_c.TCommentCpp cppcommentkind, (Ast_c.parse_info_of_info info)
54
55 | _ -> raise Impossible
56
57
58 (*****************************************************************************)
59 (* Main entry *)
60 (*****************************************************************************)
61
62 (* right now we just add comment-like and origin-tok tokens,
63 * as explained in token_c.ml.
64 *
65 * This simplified comment_annotater (compared to CComment) is really
66 * simple as the tokens and the Ast_c.info in the asts actually share
67 * the same refs.
68 * So, modifying fields in the tokens will also modify the info in
69 * the ast. Sometimes side effects simplify programming ...
70 * We use similar tricks in unparse_c.ml. So really the asts argument
71 * is not needed.
72 *
73 * ex: C1 C2 T1 T2 C3 C4 T3 C5 T4.
74 * => infoT1(-C1C2,+), infoT2(-,+C3C4), infoT3(-C3C4,+C5), infoT4(-C5,+)
75 *)
76
77 (*
78 let (agglomerate_either:
79 ('a, 'a) Common.either list -> ('a list, 'a list) Common.either list) = fun xs ->
80 raise Todo
81
82 let (span_and_pack:
83 ('a -> ('a, 'a) Common.either) -> 'a list ->
84 ('a list, 'a list) Common.either list) = fun f_either xs ->
85 let xs' = List.map f_either xs in
86 agglomerate_either xs'
87 *)
88
89
90 (* the asts is not really used, we do all via side effect on the tokens,
91 * which share the info reference with the elements in the ast.
92 *)
93 let annotate_program toks asts =
94 (* Common.exclude_but_keep_attached gather all comments before a
95 * token and then associates to this token those comments. Note that
96 * if reverse the list of tokens then this function can also be used
97 * to gather all the comments after a token :)
98 *)
99
100 (* before phase *)
101 let toks_with_before =
102 Common.exclude_but_keep_attached is_comment_or_space_or_stuff
103 toks
104 in
105
106 (* after phase. trick: reverse the tokens and reuse previous func *)
107 let toks_with_after =
108 List.rev
109 (List.map
110 (function (x,l) -> (x,List.rev l))
111 (Common.exclude_but_keep_attached is_comment_or_space_or_stuff
112 (List.rev toks)))
113 in
114
115 (* merge *)
116 assert(List.length toks_with_after =|= List.length toks_with_before);
117
118 Common.zip toks_with_before toks_with_after
119 +> List.iter (fun ((t1, before), (t2, after)) ->
120
121 assert(t1 =*= t2);
122
123 let before' = before +> List.map convert_relevant_tokens in
124 let after' = after +> List.map convert_relevant_tokens in
125
126 let info = Token_helpers.info_of_tok t1 in
127 info.Ast_c.comments_tag :=
128 { Ast_c.mbefore = before';
129 Ast_c.mafter = after';
130 mbefore2 = [];
131 mafter2 = [];
132 };
133
134 );
135 (* modified via side effect. I return it just to have a
136 * clean signature.
137 *)
138 asts
139
140
141
142