permit multiline comments and strings in macros
[bpt/coccinelle.git] / parsing_c / lexer_parser.ml
CommitLineData
0708f913 1(* Yoann Padioleau
ae4735db
C
2 *
3 * Copyright (C) 2010, University of Copenhagen DIKU and INRIA.
0708f913 4 * Copyright (C) 2002, 2006 Yoann Padioleau
34e49164
C
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 *
34e49164
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 *)
15open Common
16
17(* Tricks used to handle the ambiguity in the grammar with the typedef
18 * which impose a cooperation between the lexer and the parser.
ae4735db 19 *
34e49164
C
20 * An example by hughes casse: "in the symbol table, local
21 * definition must replace type definition in order to correctly parse
22 * local variable in functions body. This is the only way to correctly
23 * handle this kind of exception, that is,
ae4735db 24 *
34e49164
C
25 * typedef ... ID; int f(int *p) {int ID; return (ID) * *p;} If ID
26 * isn't overload, last expression is parsed as a type cast, if it
27 * isn't, this a multiplication."
ae4735db 28 *
34e49164
C
29 * Why parse_typedef_fix2 ? Cos when introduce new variable, for
30 * instance when declare parameters for a function such as int var_t,
31 * then the var_t must not be lexed as a typedef, so we must disable
32 * temporaly the typedef mechanism to allow variable with same name as
33 * a typedef. *)
34
35(* parse_typedef_fix *)
36let _handle_typedef = ref true
37
708f4980
C
38let _always_look_typedef = ref false
39
34e49164
C
40(* parse_typedef_fix2 *)
41let enable_typedef () = _handle_typedef := true
42let disable_typedef () = _handle_typedef := false
43
44let is_enabled_typedef () = !_handle_typedef
45
46
47
48
49type identkind = TypeDefI | IdentI
50
51(* Ca marche ce code ? on peut avoir un typedef puis un ident puis
ae4735db
C
52 * un typedef nested ? oui car Hashtbl (dans scoped_h_env) gere l'historique.
53 *
54 * oldsimple: but slow, take 2 secondes on some C files
34e49164
C
55 * let (typedef: typedef list list ref) = ref [[]]
56 *)
ae4735db 57let (_typedef : (string, identkind) Common.scoped_h_env ref) =
34e49164 58 ref (Common.empty_scoped_h_env ())
ae4735db 59
65038c61
C
60let is_typedef s =
61 if !_handle_typedef || !_always_look_typedef then
34e49164
C
62 (match (Common.optionise (fun () -> Common.lookup_h_env s !_typedef)) with
63 | Some TypeDefI -> true
64 | Some IdentI -> false
65 | None -> false
66 )
67 else false
68
69let new_scope() = Common.new_scope_h _typedef
70let del_scope() = Common.del_scope_h _typedef
71
1b9ae606
C
72let add_typedef s =
73 Common.add_in_scope_h _typedef (s, TypeDefI)
34e49164
C
74let add_ident s = Common.add_in_scope_h _typedef (s, IdentI)
75
ae4735db 76let add_typedef_root s =
34e49164 77 if !Flag_parsing_c.add_typedef_root
ae4735db 78 then
34e49164
C
79 Hashtbl.add !_typedef.scoped_h s TypeDefI
80 else add_typedef s (* have far more .failed without this *)
81
82
83(* Used by parse_c when do some error recovery. The parse error may
84 * have some bad side effects on typedef hash, so recover this.
85 *)
86let _old_state = ref (Common.clone_scoped_h_env !_typedef)
87
ae4735db 88let save_typedef_state () =
34e49164
C
89 _old_state := Common.clone_scoped_h_env !_typedef
90
ae4735db 91let restore_typedef_state () =
34e49164 92 _typedef := !_old_state
34e49164
C
93
94
95
ae4735db
C
96
97type context =
485bce71
C
98 | InTopLevel
99 | InFunction
100 | InStruct
101 | InParameter
102 | InInitializer
103 | InEnum
ae4735db
C
104(* InExpr ? but then orthogonal to InFunction. Could assign InExpr for
105 * instance after a '=' as in 'a = (irq_t) b;'
91eba41f 106 *)
485bce71
C
107
108let is_top_or_struct = function
109 | InTopLevel
ae4735db 110 | InStruct
485bce71
C
111 -> true
112 | _ -> false
113
ae4735db 114type lexer_hint = {
485bce71
C
115 mutable context_stack: context Common.stack;
116 }
34e49164 117
ae4735db 118let default_hint () = {
485bce71 119 context_stack = [InTopLevel];
34e49164
C
120}
121
122let _lexer_hint = ref (default_hint())
123
ae4735db
C
124let current_context () = List.hd !_lexer_hint.context_stack
125let push_context ctx =
485bce71 126 !_lexer_hint.context_stack <- ctx::!_lexer_hint.context_stack
ae4735db 127let pop_context () =
485bce71
C
128 !_lexer_hint.context_stack <- List.tl !_lexer_hint.context_stack
129
130
34e49164 131
ca417fcf 132let lexer_reset_typedef saved_typedefs =
34e49164 133 begin
ca417fcf
C
134 _handle_typedef := true;
135 (match saved_typedefs with
136 None -> _typedef := Common.empty_scoped_h_env ()
137 | Some t -> _typedef := t);
138 _lexer_hint := (default_hint ());
34e49164 139 end