3 * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
4 * Copyright (C) 2006, 2007, 2008 Ecole des Mines de Nantes
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License (GPL)
8 * version 2 as published by the Free Software Foundation.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * file license.txt for more details.
18 module TH
= Token_helpers
20 (*****************************************************************************)
22 (*****************************************************************************)
23 let pr2_err, pr2_once
= Common.mk_pr2_wrappers
Flag_parsing_c.verbose_parsing
25 (*****************************************************************************)
27 (*****************************************************************************)
29 let is_defined_passed_bis last_round
=
30 let xs = last_round
+> List.filter
TH.is_not_comment
in
32 | Parser_c.TDefine _
::_
-> true
36 (*****************************************************************************)
37 (* Skipping stuff, find next "synchronisation" point *)
38 (*****************************************************************************)
40 (* todo: do something if find Parser_c.Eof ? *)
41 let rec find_next_synchro ~next ~already_passed
=
43 (* Maybe because not enough }, because for example an ifdef contains
44 * in both branch some opening {, we later eat too much, "on deborde
45 * sur la fonction d'apres". So already_passed may be too big and
46 * looking for next synchro point starting from next may not be the
47 * best. So maybe we can find synchro point inside already_passed
48 * instead of looking in next.
50 * But take care! must progress. We must not stay in infinite loop!
51 * For instance now I have as a error recovery to look for
52 * a "start of something", corresponding to start of function,
53 * but must go beyond this start otherwise will loop.
54 * So look at premier(external_declaration2) in parser.output and
55 * pass at least those first tokens.
57 * I have chosen to start search for next synchro point after the
58 * first { I found, so quite sure we will not loop. *)
60 let last_round = List.rev already_passed
in
61 if is_defined_passed_bis last_round
62 then find_next_synchro_define
(last_round ++ next
) []
66 last_round +> Common.span
(fun tok
->
68 (* by looking at TOBrace we are sure that the "start of something"
69 * will not arrive too early
71 | Parser_c.TOBrace _
-> false
72 | Parser_c.TDefine _
-> false
76 find_next_synchro_orig
(after
++ next
) (List.rev before
)
80 and find_next_synchro_define next already_passed
=
83 pr2_err "ERROR-RECOV: end of file while in recovery mode";
85 | (Parser_c.TDefEOL i
as v
)::xs ->
86 pr2_err ("ERROR-RECOV: found sync end of #define, line "^i_to_s
(TH.line_of_tok v
));
89 find_next_synchro_define
xs (v
::already_passed
)
94 and find_next_synchro_orig next already_passed
=
97 pr2_err "ERROR-RECOV: end of file while in recovery mode";
100 | (Parser_c.TCBrace i
as v
)::xs when TH.col_of_tok v
=|= 0 ->
101 pr2_err ("ERROR-RECOV: found sync '}' at line "^i_to_s
(TH.line_of_tok v
));
104 | [] -> raise Impossible
(* there is a EOF token normally *)
106 (* still useful: now parser.mly allow empty ';' so normally no pb *)
107 | Parser_c.TPtVirg iptvirg
::xs ->
108 pr2_err "ERROR-RECOV: found sync bis, eating } and ;";
109 (Parser_c.TPtVirg iptvirg
)::v
::already_passed
, xs
111 | Parser_c.TIdent x
::Parser_c.TPtVirg iptvirg
::xs ->
112 pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;";
113 (Parser_c.TPtVirg iptvirg
)::(Parser_c.TIdent x
)::v
::already_passed
,
116 | Parser_c.TCommentSpace sp
::Parser_c.TIdent x
::Parser_c.TPtVirg iptvirg
118 pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;";
119 (Parser_c.TPtVirg iptvirg
)::
120 (Parser_c.TIdent x
)::
121 (Parser_c.TCommentSpace sp
)::
126 | Parser_c.TCommentNewline sp
::Parser_c.TIdent x
::Parser_c.TPtVirg iptvirg
128 pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;";
129 (Parser_c.TPtVirg iptvirg
)::
130 (Parser_c.TIdent x
)::
131 (Parser_c.TCommentNewline sp
)::
137 v
::already_passed
, xs
139 | v
::xs when TH.col_of_tok v
=|= 0 && TH.is_start_of_something v
->
140 pr2_err ("ERROR-RECOV: found sync col 0 at line "^ i_to_s
(TH.line_of_tok v
));
141 already_passed
, v
::xs
144 find_next_synchro_orig
xs (v
::already_passed
)