123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142(* Yoann Padioleau
*
* Copyright (C) 2011 Facebook
* Copyright (C) 2006, 2007, 2008 Ecole des Mines de Nantes
*
* 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.
*)openCommonmoduleFlag=Flag_parsingmodulePI=Parse_infomoduleT=Parser_cppmoduleTH=Token_helpers_cpp(*****************************************************************************)(* Wrappers *)(*****************************************************************************)letpr2_err,_pr2_once=Common2.mk_pr2_wrappersFlag.verbose_parsingletpr2_errs=pr2_err("ERROR_RECOV: "^s)(*****************************************************************************)(* Helpers *)(*****************************************************************************)(*****************************************************************************)(* Skipping stuff, find next "synchronisation" point *)(*****************************************************************************)(* todo: do something if find T.Eof ? *)letrecfind_next_synchro~next~already_passed=(* Maybe because not enough }, because for example an ifdef contains
* in both branch some opening {, we later eat too much, "on deborde
* sur la fonction d'apres". So already_passed may be too big and
* looking for next synchro point starting from next may not be the
* best. So maybe we can find synchro point inside already_passed
* instead of looking in next.
*
* But take care! must progress. We must not stay in infinite loop!
* For instance now I have as a error recovery to look for
* a "start of something", corresponding to start of function,
* but must go beyond this start otherwise will loop.
* So look at premier(external_declaration2) in parser.output and
* pass at least those first tokens.
*
* I have chosen to start search for next synchro point after the
* first { I found, so quite sure we will not loop. *)letlast_round=List.revalready_passedinletis_define=letxs=last_round|>List.filterTH.is_not_commentinmatchxswith|T.TDefine_::_->true|_->falseinifis_definethenfind_next_synchro_define(last_round@next)[]elselet(before,after)=last_round|>Common.span(funtok->matchtokwith(* by looking at TOBrace we are sure that the "start of something"
* will not arrive too early
*)|T.TOBrace_->false|T.TDefine_->false|_->true)infind_next_synchro_orig(after@next)(List.revbefore)andfind_next_synchro_definenextalready_passed=matchnextwith|[]->pr2_err"end of file while in recovery mode";already_passed,[]|(T.TCommentNewline_DefineEndOfMacro_asv)::xs->pr2_err(spf"found sync end of #define at line %d"(TH.line_of_tokv));v::already_passed,xs|v::xs->find_next_synchro_definexs(v::already_passed)andfind_next_synchro_orignextalready_passed=matchnextwith|[]->pr2_err"end of file while in recovery mode";already_passed,[]|(T.TCBraceiasv)::xswhenPI.col_of_infoi=0->pr2_err(spf"found sync '}' at line %d"(PI.line_of_infoi));(matchxswith|[]->raiseImpossible(* there is a EOF token normally *)(* still useful: now parser.mly allow empty ';' so normally no pb *)|T.TPtVirgiptvirg::xs->pr2_err"found sync bis, eating } and ;";(T.TPtVirgiptvirg)::v::already_passed,xs|T.TIdentx::T.TPtVirgiptvirg::xs->pr2_err"found sync bis, eating ident, }, and ;";(T.TPtVirgiptvirg)::(T.TIdentx)::v::already_passed,xs|T.TCommentSpacesp::T.TIdentx::T.TPtVirgiptvirg::xs->pr2_err"found sync bis, eating ident, }, and ;";(T.TCommentSpacesp)::(T.TPtVirgiptvirg)::(T.TIdentx)::v::already_passed,xs|_->v::already_passed,xs)|v::xs->letinfo=TH.info_of_tokvinifPI.col_of_infoinfo=0&&TH.is_start_of_somethingvthenbeginpr2_err(spf"found sync col 0 at line %d "(PI.line_of_infoinfo));already_passed,v::xsendelsefind_next_synchro_origxs(v::already_passed)