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