123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109(* Yoann Padioleau
*
* Copyright (C) 2019 r2c
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation, with the
* special exception on linking described in file license.txt.
*
* This library 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.
*)openCommonopenAst_genericmoduleAst=Ast_genericmoduleV=Visitor_astmoduleGG=Generic_vs_generic(*****************************************************************************)(* Prelude *)(*****************************************************************************)(* See https://github.com/facebook/pfff/wiki/Sgrep
*
*)(*****************************************************************************)(* Type *)(*****************************************************************************)(* right now only Expr and Stmt are supported *)typepattern=Ast.anytype('a,'b)matcher='a->'b->Metavars_generic.metavars_bindinglistletmatch_e_epatterne=letenv=GG.empty_environment()inGG.m_exprpatterneenvletmatch_st_stpatterne=letenv=GG.empty_environment()inGG.m_stmtpatterneenv(* for unit testing *)letmatch_any_anypatterne=letenv=GG.empty_environment()inGG.m_anypatterneenv(*****************************************************************************)(* Main entry point *)(*****************************************************************************)letsgrep_ast~hookpatternast=lethook=matchpatternwith(* depending on the pattern, we visit every relevant nodes
* and try the pattern on it.
*)|Epattern_expr->{V.default_visitorwithV.kexpr=(fun(k,_)x->letmatches_with_env=match_e_epattern_exprxinifmatches_with_env=[]thenkxelsebegin(* could also recurse to find nested matching inside
* the matched code itself.
*)letmatched_tokens=Lib_ast.ii_of_any(Ex)inmatches_with_env|>List.iter(funenv->hookenvmatched_tokens)end);}|Spattern->{V.default_visitorwithV.kstmt=(fun(k,_)x->letmatches_with_env=match_st_stpatternxinifmatches_with_env=[]thenkxelsebegin(* could also recurse to find nested matching inside
* the matched code itself.
*)letmatched_tokens=Lib_ast.ii_of_any(Sx)inmatches_with_env|>List.iter(funenv->hookenvmatched_tokens)end);}|_->failwith(spf"pattern not yet supported:")in(* TODO? opti: dont analyze certain ASTs if it does not contain
* certain constants that interect with the pattern?
* But this requires to analyze the pattern to extract those
* constants (name of function, field, etc.)
*)(V.mk_visitorhook)(Prast)