Commit | Line | Data |
---|---|---|
0708f913 C |
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 *) | |
b1b2de81 | 116 | assert(List.length toks_with_after =|= List.length toks_with_before); |
0708f913 C |
117 | |
118 | Common.zip toks_with_before toks_with_after | |
119 | +> List.iter (fun ((t1, before), (t2, after)) -> | |
120 | ||
b1b2de81 | 121 | assert(t1 =*= t2); |
0708f913 C |
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'; | |
708f4980 C |
130 | mbefore2 = []; |
131 | mafter2 = []; | |
0708f913 C |
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 |