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