Commit | Line | Data |
---|---|---|
978fd7e5 | 1 | (* Yoann Padioleau |
ae4735db C |
2 | * |
3 | * Copyright (C) 2010, University of Copenhagen DIKU and INRIA. | |
978fd7e5 C |
4 | * Copyright (C) 2006, 2007, 2008 Ecole des Mines de Nantes |
5 | * | |
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. | |
ae4735db | 9 | * |
978fd7e5 C |
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. | |
14 | *) | |
15 | ||
16 | open Common | |
17 | ||
ae4735db | 18 | module TH = Token_helpers |
978fd7e5 C |
19 | |
20 | (*****************************************************************************) | |
21 | (* Wrappers *) | |
22 | (*****************************************************************************) | |
ae4735db | 23 | let pr2_err, pr2_once = Common.mk_pr2_wrappers Flag_parsing_c.verbose_parsing |
978fd7e5 C |
24 | |
25 | (*****************************************************************************) | |
26 | (* Helpers *) | |
27 | (*****************************************************************************) | |
28 | ||
ae4735db | 29 | let is_defined_passed_bis last_round = |
978fd7e5 C |
30 | let xs = last_round +> List.filter TH.is_not_comment in |
31 | match xs with | |
32 | | Parser_c.TDefine _::_ -> true | |
33 | | _ -> false | |
34 | ||
35 | ||
36 | (*****************************************************************************) | |
37 | (* Skipping stuff, find next "synchronisation" point *) | |
38 | (*****************************************************************************) | |
39 | ||
40 | (* todo: do something if find Parser_c.Eof ? *) | |
41 | let rec find_next_synchro ~next ~already_passed = | |
42 | ||
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. | |
ae4735db | 49 | * |
978fd7e5 | 50 | * But take care! must progress. We must not stay in infinite loop! |
ae4735db | 51 | * For instance now I have as a error recovery to look for |
978fd7e5 C |
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. | |
ae4735db | 56 | * |
978fd7e5 C |
57 | * I have chosen to start search for next synchro point after the |
58 | * first { I found, so quite sure we will not loop. *) | |
59 | ||
60 | let last_round = List.rev already_passed in | |
ae4735db | 61 | if is_defined_passed_bis last_round |
978fd7e5 | 62 | then find_next_synchro_define (last_round ++ next) [] |
ae4735db | 63 | else |
978fd7e5 | 64 | |
ae4735db C |
65 | let (before, after) = |
66 | last_round +> Common.span (fun tok -> | |
978fd7e5 C |
67 | match tok with |
68 | (* by looking at TOBrace we are sure that the "start of something" | |
ae4735db | 69 | * will not arrive too early |
978fd7e5 C |
70 | *) |
71 | | Parser_c.TOBrace _ -> false | |
72 | | Parser_c.TDefine _ -> false | |
73 | | _ -> true | |
ae4735db | 74 | ) |
978fd7e5 C |
75 | in |
76 | find_next_synchro_orig (after ++ next) (List.rev before) | |
77 | ||
ae4735db | 78 | |
978fd7e5 C |
79 | |
80 | and find_next_synchro_define next already_passed = | |
81 | match next with | |
ae4735db C |
82 | | [] -> |
83 | pr2_err "ERROR-RECOV: end of file while in recovery mode"; | |
978fd7e5 | 84 | already_passed, [] |
ae4735db | 85 | | (Parser_c.TDefEOL i as v)::xs -> |
978fd7e5 C |
86 | pr2_err ("ERROR-RECOV: found sync end of #define, line "^i_to_s(TH.line_of_tok v)); |
87 | v::already_passed, xs | |
ae4735db | 88 | | v::xs -> |
978fd7e5 C |
89 | find_next_synchro_define xs (v::already_passed) |
90 | ||
91 | ||
ae4735db | 92 | |
978fd7e5 C |
93 | |
94 | and find_next_synchro_orig next already_passed = | |
95 | match next with | |
ae4735db C |
96 | | [] -> |
97 | pr2_err "ERROR-RECOV: end of file while in recovery mode"; | |
978fd7e5 C |
98 | already_passed, [] |
99 | ||
ae4735db | 100 | | (Parser_c.TCBrace i as v)::xs when TH.col_of_tok v =|= 0 -> |
978fd7e5 C |
101 | pr2_err ("ERROR-RECOV: found sync '}' at line "^i_to_s (TH.line_of_tok v)); |
102 | ||
103 | (match xs with | |
104 | | [] -> raise Impossible (* there is a EOF token normally *) | |
105 | ||
106 | (* still useful: now parser.mly allow empty ';' so normally no pb *) | |
ae4735db | 107 | | Parser_c.TPtVirg iptvirg::xs -> |
978fd7e5 C |
108 | pr2_err "ERROR-RECOV: found sync bis, eating } and ;"; |
109 | (Parser_c.TPtVirg iptvirg)::v::already_passed, xs | |
110 | ||
ae4735db | 111 | | Parser_c.TIdent x::Parser_c.TPtVirg iptvirg::xs -> |
978fd7e5 | 112 | pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;"; |
ae4735db | 113 | (Parser_c.TPtVirg iptvirg)::(Parser_c.TIdent x)::v::already_passed, |
978fd7e5 | 114 | xs |
ae4735db | 115 | |
978fd7e5 | 116 | | Parser_c.TCommentSpace sp::Parser_c.TIdent x::Parser_c.TPtVirg iptvirg |
ae4735db | 117 | ::xs -> |
978fd7e5 | 118 | pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;"; |
5626f154 C |
119 | (Parser_c.TPtVirg iptvirg):: |
120 | (Parser_c.TIdent x):: | |
978fd7e5 | 121 | (Parser_c.TCommentSpace sp):: |
978fd7e5 | 122 | v:: |
ae4735db | 123 | already_passed, |
978fd7e5 | 124 | xs |
ae4735db | 125 | |
978fd7e5 | 126 | | Parser_c.TCommentNewline sp::Parser_c.TIdent x::Parser_c.TPtVirg iptvirg |
ae4735db | 127 | ::xs -> |
978fd7e5 | 128 | pr2_err "ERROR-RECOV: found sync bis, eating ident, }, and ;"; |
5626f154 C |
129 | (Parser_c.TPtVirg iptvirg):: |
130 | (Parser_c.TIdent x):: | |
978fd7e5 | 131 | (Parser_c.TCommentNewline sp):: |
978fd7e5 | 132 | v:: |
ae4735db | 133 | already_passed, |
978fd7e5 | 134 | xs |
ae4735db C |
135 | |
136 | | _ -> | |
978fd7e5 C |
137 | v::already_passed, xs |
138 | ) | |
ae4735db | 139 | | v::xs when TH.col_of_tok v =|= 0 && TH.is_start_of_something v -> |
978fd7e5 C |
140 | pr2_err ("ERROR-RECOV: found sync col 0 at line "^ i_to_s(TH.line_of_tok v)); |
141 | already_passed, v::xs | |
ae4735db C |
142 | |
143 | | v::xs -> | |
978fd7e5 | 144 | find_next_synchro_orig xs (v::already_passed) |