~ubuntu-branches/ubuntu/oneiric/haxe/oneiric

« back to all changes in this revision

Viewing changes to haxe/parser.ml

  • Committer: Bazaar Package Importer
  • Author(s): Jens Peter Secher
  • Date: 2008-06-15 11:04:09 UTC
  • mfrom: (2.1.6 intrepid)
  • Revision ID: james.westby@ubuntu.com-20080615110409-7pyykgwmk5v0cues
Tags: 1:1.19-3
* Remove bashism in script.
  (Closes: #484390)
* Upgrade to Policy 3.8.0 by including a README.source explaining how to
  use dpatch.

Show diffs side-by-side

added added

removed removed

Lines of Context:
27
27
        | Missing_type
28
28
 
29
29
exception Error of error_msg * pos
 
30
exception TypePath of string list
 
31
exception Display of expr
30
32
 
31
33
let error_msg = function
32
34
        | Unexpected t -> "Unexpected "^(s_token t)
41
43
 
42
44
let cache = ref (DynArray.create())
43
45
let doc = ref None
 
46
let use_doc = ref false
 
47
let resume_display = ref null_pos
44
48
 
45
49
let last_token s =
46
50
        let n = Stream.count s in
48
52
 
49
53
let serror() = raise (Stream.Error "")
50
54
 
 
55
let do_resume() = !resume_display <> null_pos
 
56
 
 
57
let display e = raise (Display e)
 
58
 
 
59
let is_resuming p =
 
60
        let p2 = !resume_display in
 
61
        p.pmax = p2.pmin && (!Plugin.get_full_path) p.pfile = p2.pfile
 
62
 
51
63
let priority = function
52
64
        | OpAssign | OpAssignOp _ -> -4
53
65
        | OpBoolOr -> -3
79
91
        | EBinop (_op,_e,_e2) when can_swap _op op && (is_not_assign _op || is_not_assign op) ->
80
92
                let _e = make_binop op e _e in
81
93
                EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2)
 
94
        | ETernary (e1,e2,e3) when is_not_assign op ->
 
95
                let e = make_binop op e e1 in
 
96
                ETernary (e,e2,e3) , punion (pos e) (pos e3)
82
97
        | _ ->
83
98
                EBinop (op,e,e2) , punion (pos e) (pos e2)
84
99
 
135
150
        else
136
151
                match s with parser
137
152
                | [< '(Semicolon,p) >] -> p
138
 
                | [< s >] -> error Missing_semicolon (snd (last_token s))
 
153
                | [< s >] ->
 
154
                        let pos = snd (last_token s) in
 
155
                        if do_resume() then pos else error Missing_semicolon pos
139
156
 
140
157
let rec parse_file s =
141
158
        doc := None;
145
162
 
146
163
and parse_type_decl s =
147
164
        match s with parser
148
 
        | [< '(Kwd Import,p1); p, t, s = parse_import; p2 = semicolon >] -> EImport (p,t,s) , punion p1 p2
 
165
        | [< '(Kwd Import,p1); p, t, s = parse_import []; p2 = semicolon >] -> EImport (p,t,s) , punion p1 p2
149
166
        | [< c = parse_common_flags; s >] ->
150
167
                match s with parser
151
168
                | [< n , p1 = parse_enum_flags; doc = get_doc; '(Const (Type name),_); tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] ->
156
173
                                d_flags = List.map snd c @ n;
157
174
                                d_data = l
158
175
                        }, punion p1 p2)
159
 
                | [< n , p1 = parse_class_flags; doc = get_doc; '(Const (Type name),_); tl = parse_constraint_params; hl = psep Comma parse_class_herit; '(BrOpen,_); fl = plist parse_class_field; '(BrClose,p2) >] ->
 
176
                | [< n , p1 = parse_class_flags; doc = get_doc; '(Const (Type name),_); tl = parse_constraint_params; hl = psep Comma parse_class_herit; '(BrOpen,_); fl = parse_class_field_resume; s >] ->
 
177
                        let p2 = (match s with parser
 
178
                                | [< '(BrClose,p2) >] -> p2
 
179
                                | [< >] -> if do_resume() then p1 else serror()
 
180
                        ) in
160
181
                        (EClass {
161
182
                                d_name = name;
162
183
                                d_doc = doc;
164
185
                                d_flags = List.map fst c @ n @ hl;
165
186
                                d_data = fl;
166
187
                        }, punion p1 p2)
167
 
                | [< '(Kwd Typedef,p1); doc = get_doc; '(Const (Type name),p2); tl = parse_constraint_params; '(Binop OpAssign,_); t = parse_type_path >] ->
 
188
                | [< '(Kwd Typedef,p1); doc = get_doc; '(Const (Type name),p2); tl = parse_constraint_params; '(Binop OpAssign,_); t = parse_type_path; s >] ->
 
189
                        (match s with parser
 
190
                        | [< '(Semicolon,_) >] -> ()
 
191
                        | [< >] -> ());
168
192
                        (ETypedef {
169
193
                                d_name = name;
170
194
                                d_doc = doc;
175
199
 
176
200
and parse_package s = psep Dot ident s
177
201
 
178
 
and parse_import = parser
179
 
        | [< '(Const (Ident k),_); '(Dot,_); p, t, s = parse_import >] -> (k :: p), t, s
 
202
and parse_class_field_resume s =
 
203
        if not (do_resume()) then
 
204
                plist parse_class_field s
 
205
        else
 
206
                (* junk all tokens until we reach next variable/function or next type declaration *)
 
207
                let rec loop() =
 
208
                        (match List.map fst (Stream.npeek 2 s) with
 
209
                        | Kwd Public :: _ | Kwd Static :: _ | Kwd Var :: _ | Kwd Override :: _ ->
 
210
                                raise Exit
 
211
                        | [] | Eof :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ ->
 
212
                                raise Not_found
 
213
                        | [Kwd Private; Kwd Function]
 
214
                        | [Kwd Private; Kwd Var] ->
 
215
                                raise Exit
 
216
                        | [Kwd Private; Kwd Class]
 
217
                        | [Kwd Private; Kwd Interface]
 
218
                        | [Kwd Private; Kwd Enum]
 
219
                        | [Kwd Private; Kwd Typedef] ->
 
220
                                raise Not_found
 
221
                        | [Kwd Function; Const _]
 
222
                        | [Kwd Function; Kwd New] ->
 
223
                                raise Exit
 
224
                        | _ -> ());
 
225
                        Stream.junk s;
 
226
                        loop();
 
227
                in
 
228
                try
 
229
                        loop();
 
230
                with
 
231
                        | Not_found ->
 
232
                                []
 
233
                        | Exit ->
 
234
                                try
 
235
                                        let c = parse_class_field s in
 
236
                                        c :: parse_class_field_resume s
 
237
                                with
 
238
                                        Stream.Error _ | Stream.Failure -> parse_class_field_resume s
 
239
 
 
240
and parse_import acc = parser
 
241
        | [< '(Const (Ident k),_); '(Dot,p); s >] ->
 
242
                if is_resuming p then raise (TypePath (List.rev (k :: acc)));
 
243
                parse_import (k :: acc) s
180
244
        | [< '(Const (Type t),_); s >] ->
181
 
                [] , t , match s with parser
 
245
                List.rev acc , t , match s with parser
182
246
                        | [< '(Dot,_); '(Const (Type s),_) >] -> Some s
183
247
                        | [< >] -> None
184
248
 
206
270
                        | [< '(Binop OpGt,_); t = parse_type_path_normal; '(Comma,_); s >] ->
207
271
                                (match s with parser
208
272
                                | [< name = any_ident; l = parse_type_anonymous_resume name >] -> TPExtend (t,l)
209
 
                                | [< l = plist parse_signature_field; '(BrClose,_) >] -> TPExtend (t,l))
210
 
                        | [< l = plist parse_signature_field; '(BrClose,_) >] -> TPAnonymous l
 
273
                                | [< l = plist (parse_signature_field None); '(BrClose,_) >] -> TPExtend (t,l)
 
274
                                | [< >] -> serror())
 
275
                        | [< l = plist (parse_signature_field None); '(BrClose,_) >] -> TPAnonymous l
211
276
                        | [< >] -> serror()
212
277
                ) in
213
278
                parse_type_path_next t s
216
281
and parse_type_path_normal s = parse_type_path1 [] s
217
282
 
218
283
and parse_type_path1 pack = parser
219
 
        | [< '(Const (Ident name),_); '(Dot,_); t = parse_type_path1 (name :: pack) >] -> t
 
284
        | [< '(Const (Ident name),_); '(Dot,p); s >] ->
 
285
                if is_resuming p then
 
286
                        raise  (TypePath (List.rev (name :: pack)))
 
287
                else
 
288
                        parse_type_path1 (name :: pack) s
220
289
        | [< '(Const (Type name),_); s >] ->
221
290
                let params = (match s with parser
222
 
                        | [< '(Binop OpLt,_); l = psep Comma parse_type_path_variance; '(Binop OpGt,_) >] -> l
 
291
                        | [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,_) >] -> l
223
292
                        | [< >] -> []
224
293
                ) in
225
294
                {
228
297
                        tparams = params
229
298
                }
230
299
 
231
 
and parse_type_path_variance = parser
232
 
        | [< '(Binop OpAdd,_); t = parse_type_path >] -> VCo, t
233
 
        | [< '(Binop OpSub,_); t = parse_type_path >] -> VContra, t
234
 
        | [< '(Binop OpMult,_); t = parse_type_path >] -> VBi, t
235
 
        | [< t = parse_type_path >] -> VNo, t
 
300
and parse_type_path_or_const = parser
 
301
        | [< '(Const (String s),_); >] -> TPConst (String s)
 
302
        | [< '(Const (Int i),_); >] -> TPConst (Int i)
 
303
        | [< '(Const (Float f),_); >] -> TPConst (Float f)
 
304
        | [< t = parse_type_path >] -> TPType t
236
305
 
237
306
and parse_type_path_next t = parser
238
307
        | [< '(Arrow,_); t2 = parse_type_path >] ->
245
314
 
246
315
and parse_type_anonymous_resume name = parser
247
316
        | [< '(DblDot,p); t = parse_type_path; s >] ->
248
 
                (name, AFVar t, p) ::
 
317
                (name, None, AFVar t, p) ::
249
318
                match s with parser
250
319
                | [< '(BrClose,_) >] -> []
251
 
                | [< '(Comma,_); l = psep Comma parse_type_anonymous; '(BrClose,_) >] -> l
 
320
                | [< '(Comma,_) >] ->
 
321
                        (match s with parser
 
322
                        | [< '(BrClose,_) >] -> []
 
323
                        | [< name = any_ident; s >] -> parse_type_anonymous_resume name s
 
324
                        | [< >] -> serror());
252
325
                | [< >] -> serror()
253
326
 
254
 
and parse_type_anonymous = parser
255
 
        | [< name = any_ident; '(DblDot,p); t = parse_type_path >] -> (name, AFVar t, p)
256
 
 
257
327
and parse_enum s =
258
328
        doc := None;
259
329
        match s with parser
278
348
                                (FProp (name,doc,l,i1,i2,t),punion p1 p2)
279
349
                        | [< t = parse_type_opt; s >] ->
280
350
                                let e , p2 = (match s with parser
281
 
                                | [< '(Binop OpAssign,_) when List.mem AStatic l; e = expr; p2 = semicolon >] -> Some e , p2
 
351
                                | [< '(Binop OpAssign,_) when List.mem AStatic l; e = toplevel_expr; p2 = semicolon >] -> Some e , p2
282
352
                                | [< '(Semicolon,p2) >] -> None , p2
283
353
                                | [< >] -> serror()
284
354
                                ) in
285
355
                                (FVar (name,doc,l,t,e),punion p1 p2))
286
356
                | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
287
357
                        let e = (match s with parser
288
 
                                | [< e = expr >] -> e
 
358
                                | [< e = toplevel_expr >] -> e
289
359
                                | [< '(Semicolon,p) >] -> (EBlock [],p)
290
360
                                | [< >] -> serror()
291
361
                        ) in
298
368
                | [< >] ->
299
369
                        if l = [] && doc = None then raise Stream.Failure else serror()
300
370
 
301
 
and parse_signature_field = parser
 
371
and parse_signature_field flag = parser
302
372
        | [< '(Kwd Var,p1); name = any_ident; s >] ->
303
373
                (match s with parser
304
 
                | [< '(DblDot,_); t = parse_type_path; p2 = semicolon >] -> (name,AFVar t,punion p1 p2)
305
 
                | [< '(POpen,_); i1 = property_ident; '(Comma,_); i2 = property_ident; '(PClose,_); '(DblDot,_); t = parse_type_path; p2 = semicolon >] -> (name,AFProp (t,i1,i2),punion p1 p2))
 
374
                | [< '(DblDot,_); t = parse_type_path; p2 = semicolon >] -> (name,flag,AFVar t,punion p1 p2)
 
375
                | [< '(POpen,_); i1 = property_ident; '(Comma,_); i2 = property_ident; '(PClose,_); '(DblDot,_); t = parse_type_path; p2 = semicolon >] -> (name,flag,AFProp (t,i1,i2),punion p1 p2)
 
376
                | [< >] -> serror())
306
377
        | [< '(Kwd Function,p1); name = any_ident; '(POpen,_); al = psep Comma parse_fun_param_type; '(PClose,_); '(DblDot,_); t = parse_type_path; p2 = semicolon >] ->
307
 
                (name,AFFun (al,t),punion p1 p2)
 
378
                (name,flag,AFFun (al,t),punion p1 p2)
 
379
        | [< '(Kwd Private,_) when flag = None; s >] -> parse_signature_field (Some false) s
 
380
        | [< '(Kwd Public,_) when flag = None; s >] -> parse_signature_field (Some true) s
308
381
 
309
382
and parse_cf_rights allow_static l = parser
310
383
        | [< '(Kwd Static,_) when allow_static; l = parse_cf_rights false (AStatic :: l) >] -> l
312
385
        | [< '(Kwd Private,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights allow_static (APrivate :: l) >] -> l
313
386
        | [< '(Kwd Override,_) when allow_static; l = parse_cf_rights false (AOverride :: l) >] -> l
314
387
        | [< '(Kwd F9Dynamic,_) when not (List.mem AF9Dynamic l); l = parse_cf_rights false (AF9Dynamic :: l) >] -> l
 
388
        | [< '(Kwd Inline,_); l = parse_cf_rights allow_static (AInline :: l) >] -> l
315
389
        | [< >] -> l
316
390
 
317
391
and parse_fun_name = parser
332
406
        | [< >] -> []
333
407
 
334
408
and parse_constraint_param = parser
335
 
        | [< '(Binop OpAdd,_); '(Const (Type name),_); s >] -> parse_constraint_param_next VCo name s
336
 
        | [< '(Binop OpSub,_); '(Const (Type name),_); s >] -> parse_constraint_param_next VContra name s
337
 
        | [< '(Binop OpMult,_); '(Const (Type name),_); s >] -> parse_constraint_param_next VBi name s
338
 
        | [< '(Const (Type name),_); s >] -> parse_constraint_param_next VNo name s
339
 
 
340
 
and parse_constraint_param_next v name = parser
341
 
        | [< '(DblDot,_); s >] ->
342
 
                (match s with parser
343
 
                | [< '(POpen,_); l = psep Comma parse_type_path_normal; '(PClose,_) >] -> (v,name,l)
344
 
                | [< t = parse_type_path_normal >] -> (v,name,[t])
345
 
                | [< >] -> serror())
346
 
        | [< >] -> (v,name,[])
 
409
        | [< '(Const (Type name),_); s >] ->
 
410
                match s with parser
 
411
                | [< '(DblDot,_); s >] ->
 
412
                        (match s with parser
 
413
                        | [< '(POpen,_); l = psep Comma parse_type_path_normal; '(PClose,_) >] -> (name,l)
 
414
                        | [< t = parse_type_path_normal >] -> (name,[t])
 
415
                        | [< >] -> serror())
 
416
                | [< >] -> (name,[])
347
417
 
348
418
and parse_class_herit = parser
349
419
        | [< '(Kwd Extends,_); t = parse_type_path_normal >] -> HExtends t
352
422
and block1 = parser
353
423
        | [< '(Const (Ident name),p); s >] -> block2 name true p s
354
424
        | [< '(Const (Type name),p); s >] -> block2 name false p s
355
 
        | [< b = block >] -> EBlock b
 
425
        | [< b = block [] >] -> EBlock b
356
426
 
357
427
and block2 name ident p = parser
358
428
        | [< '(DblDot,_); e = expr; l = parse_obj_decl >] -> EObjectDecl ((name,e) :: l)
359
429
        | [< e = expr_next (EConst (if ident then Ident name else Type name),p); s >] ->
360
430
                try
361
431
                        let _ = semicolon s in
362
 
                        let b = block s in
363
 
                        EBlock (e :: b)
 
432
                        let b = block [e] s in
 
433
                        EBlock b
364
434
                with
365
 
                        | Error (e,p) ->
366
 
                                (!display_error) e p;
367
 
                                EBlock (block s)
 
435
                        | Error (err,p) ->
 
436
                                (!display_error) err p;
 
437
                                EBlock (block [e] s)
368
438
 
369
 
and block s =
 
439
and block acc s =
370
440
        try
371
441
                let e = parse_block_elt s in
372
 
                e :: block s
 
442
                block (e :: acc) s
373
443
        with
 
444
                | Display e ->
 
445
                        display (EBlock (List.rev (e :: acc)),snd e)
374
446
                | Stream.Failure ->
375
 
                        []
 
447
                        List.rev acc
376
448
                | Stream.Error _ ->
377
449
                        let tk , pos = (match Stream.peek s with None -> last_token s | Some t -> t) in
378
450
                        (!display_error) (Unexpected tk) pos;
379
 
                        block s
 
451
                        block acc s
380
452
        | Error (e,p) ->
381
453
                        (!display_error) e p;
382
 
                        block s
 
454
                        block acc s
383
455
 
384
456
and parse_block_elt = parser
385
457
        | [< '(Kwd Var,p1); vl = psep Comma parse_var_decl; p2 = semicolon >] -> (EVars vl,punion p1 p2)
407
479
                | [< >] -> (name,t,None)
408
480
 
409
481
and expr = parser
410
 
        | [< '(BrOpen,p1); e = block1; '(BrClose,p2) >] -> (e,punion p1 p2)
 
482
        | [< '(BrOpen,p1); b = block1; '(BrClose,p2); s >] ->
 
483
                let e = (b,punion p1 p2) in
 
484
                (match b with
 
485
                | EObjectDecl _ -> expr_next e s
 
486
                | _ -> e)
411
487
        | [< '(Const c,p); s >] -> expr_next (EConst c,p) s
412
488
        | [< '(Kwd This,p); s >] -> expr_next (EConst (Ident "this"),p) s
 
489
        | [< '(Kwd Callback,p); s >] -> expr_next (EConst (Ident "callback"),p) s
413
490
        | [< '(Kwd Cast,p1); s >] ->
414
491
                (match s with parser
415
492
                | [< '(POpen,_); e = expr; s >] ->
416
493
                        (match s with parser
417
494
                        | [< '(Comma,_); t = parse_type_path; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s
418
 
                        | [< >] -> expr_next (ECast (e,None),punion p1 (pos e)) s)
419
 
                | [< e = expr; s >] -> expr_next (ECast (e,None),punion p1 (pos e)) s)
 
495
                        | [< '(PClose,p2); s >] -> expr_next (ECast (e,None),punion p1 (pos e)) s
 
496
                        | [< >] -> serror())
 
497
                | [< e = expr; s >] -> expr_next (ECast (e,None),punion p1 (pos e)) s
 
498
                | [< >] -> serror())
420
499
        | [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p)
421
 
        | [< '(Kwd New,p1); t = parse_type_path_normal; '(POpen,_); al = psep Comma expr; '(PClose,p2); s >] -> expr_next (ENew (t,al),punion p1 p2) s
 
500
        | [< '(Kwd New,p1); t = parse_type_path_normal; '(POpen,p); s >] ->
 
501
                if is_resuming p then display (EDisplayNew t,punion p1 p);
 
502
                (match s with parser
 
503
                | [< al = psep Comma expr; '(PClose,p2); s >] -> expr_next (ENew (t,al),punion p1 p2) s
 
504
                | [< >] -> serror())
422
505
        | [< '(POpen,p1); e = expr; '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s
423
506
        | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s
424
 
        | [< '(Kwd Function,p1); '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; e = expr; s >] ->
425
 
                let f = {
426
 
                        f_type = t;
427
 
                        f_args = al;
428
 
                        f_expr = e;
429
 
                } in
430
 
                expr_next (EFunction f, punion p1 (pos e)) s
 
507
        | [< '(Kwd Function,p1); '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
 
508
                let make e =
 
509
                        let f = {
 
510
                                f_type = t;
 
511
                                f_args = al;
 
512
                                f_expr = e;
 
513
                        } in
 
514
                        EFunction f, punion p1 (pos e)
 
515
                in
 
516
                (try
 
517
                        expr_next (make (expr s)) s
 
518
                with
 
519
                        Display e -> display (make e))
431
520
        | [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1
432
521
        | [< '(Binop OpSub,p1); e = expr >] -> make_unop Neg e p1
433
 
        | [< '(Kwd For,p); '(POpen,_); name = any_ident; '(Kwd In,_); it = expr; '(PClose,_); e = expr; s >] ->
434
 
                expr_next (EFor (name,it,e),punion p (pos e)) s
 
522
        | [< '(Kwd For,p); '(POpen,_); name = any_ident; '(Kwd In,_); it = expr; '(PClose,_); s >] ->
 
523
                (try
 
524
                        let e = expr s in
 
525
                        expr_next (EFor (name,it,e),punion p (pos e)) s
 
526
                with
 
527
                        Display e -> display (EFor (name,it,e),punion p (pos e)))
435
528
        | [< '(Kwd If,p); '(POpen,_); cond = expr; '(PClose,_); e1 = expr; s >] ->
436
529
                let e2 , s = (match s with parser
437
530
                        | [< '(Kwd Else,_); e2 = expr; s >] -> Some e2 , s
438
531
                        | [< >] ->
439
 
                                match Stream.npeek 2 s with
440
 
                                | [(Semicolon,_);(Kwd Else,_)] ->
441
 
                                        Stream.junk s;
442
 
                                        Stream.junk s;
443
 
                                        (match s with parser
444
 
                                        | [< e2 = expr; s >] -> Some e2, s
445
 
                                        | [< >] -> serror())
 
532
                                (* 
 
533
                                        we can't directly npeek 2 elements because this might
 
534
                                        remove some documentation tag.
 
535
                                *)
 
536
                                match Stream.npeek 1 s with
 
537
                                | [(Semicolon,_)] ->
 
538
                                        (match Stream.npeek 2 s with
 
539
                                        | [(Semicolon,_); (Kwd Else,_)] ->
 
540
                                                Stream.junk s;
 
541
                                                Stream.junk s;
 
542
                                                (match s with parser
 
543
                                                | [< e2 = expr; s >] -> Some e2, s
 
544
                                                | [< >] -> serror())
 
545
                                        | _ -> None , s)
446
546
                                | _ ->
447
547
                                        None , s
448
548
                ) in
450
550
        | [< '(Kwd Return,p); e = popt expr >] -> (EReturn e, match e with None -> p | Some e -> punion p (pos e))
451
551
        | [< '(Kwd Break,p) >] -> (EBreak,p)
452
552
        | [< '(Kwd Continue,p) >] -> (EContinue,p)
453
 
        | [< '(Kwd While,p1); '(POpen,_); cond = expr; '(PClose,_); e = expr; s >] -> expr_next (EWhile (cond,e,NormalWhile),punion p1 (pos e)) s
 
553
        | [< '(Kwd While,p1); '(POpen,_); cond = expr; '(PClose,_); s >] ->
 
554
                (try
 
555
                        let e = expr s in
 
556
                        expr_next (EWhile (cond,e,NormalWhile),punion p1 (pos e)) s
 
557
                with
 
558
                        Display e -> display (EWhile (cond,e,NormalWhile),punion p1 (pos e)))
454
559
        | [< '(Kwd Do,p1); e = expr; '(Kwd While,_); '(POpen,_); cond = expr; '(PClose,_); s >] -> expr_next (EWhile (cond,e,DoWhile),punion p1 (pos e)) s
455
 
        | [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases; '(BrClose,p2); s >] -> expr_next (ESwitch (e,cases,def),punion p1 p2) s
456
 
        | [< '(Kwd Try,p1); e = expr; cl = plist parse_catch; s >] -> expr_next (ETry (e,cl),p1) s
 
560
        | [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases e []; '(BrClose,p2); s >] -> expr_next (ESwitch (e,cases,def),punion p1 p2) s
 
561
        | [< '(Kwd Try,p1); e = expr; cl = plist (parse_catch e); s >] -> expr_next (ETry (e,cl),p1) s
457
562
        | [< '(IntInterval i,p1); e2 = expr >] -> make_binop OpInterval (EConst (Int i),p1) e2
458
563
        | [< '(Kwd Untyped,p1); e = expr >] -> (EUntyped e,punion p1 (pos e))
459
564
 
460
565
and expr_next e1 = parser
461
 
        | [< '(Dot,_); s >] ->
462
 
                (match s with parser
463
 
                | [< '(Const (Ident f),p); s >] -> expr_next (EField (e1,f) , punion (pos e1) p) s
464
 
                | [< '(Const (Type t),p); s >] -> expr_next (EType (e1,t) , punion (pos e1) p) s
465
 
                | [< >] -> serror())
466
 
        | [< '(POpen,p1); params = psep Comma expr; '(PClose,p2); s >] ->
467
 
                expr_next (ECall (e1,params) , punion (pos e1) p2) s
 
566
        | [< '(Dot,p); s >] ->
 
567
                if is_resuming p then display (EDisplay e1,p);
 
568
                (match s with parser
 
569
                | [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s
 
570
                | [< '(Const (Type t),p2) when p.pmax = p2.pmin; s >] -> expr_next (EType (e1,t) , punion (pos e1) p2) s
 
571
                | [< >] -> serror())
 
572
        | [< '(POpen,p1); s >] ->
 
573
                if is_resuming p1 then display (EDisplay e1,p1);
 
574
                (match s with parser
 
575
                | [< params = psep Comma expr; '(PClose,p2); s >] -> expr_next (ECall (e1,params) , punion (pos e1) p2) s
 
576
                | [< >] -> serror())
468
577
        | [< '(BkOpen,_); e2 = expr; '(BkClose,p2); s >] ->
469
578
                expr_next (EArray (e1,e2), punion (pos e1) p2) s
470
579
        | [< '(Binop OpGt,_); s >] ->
490
599
                make_binop op e1 e2
491
600
        | [< '(Unop op,p) when is_postfix e1 op; s >] ->
492
601
                expr_next (EUnop (op,Postfix,e1), punion (pos e1) p) s
 
602
        | [< '(Question,_); e2 = expr; '(DblDot,_); e3 = expr >] ->
 
603
                (ETernary (e1,e2,e3),punion (pos e1) (pos e3))
493
604
        | [< >] -> e1
494
605
 
495
 
and parse_switch_cases = parser
496
 
        | [< '(Kwd Default,p1); '(DblDot,_); e = block1; l , def = parse_switch_cases >] ->
 
606
and parse_switch_cases eswitch cases = parser
 
607
        | [< '(Kwd Default,p1); '(DblDot,_); s >] ->
 
608
                let b = (try block1 s with Display e -> display (ESwitch (eswitch,cases,Some e),p1)) in
 
609
                let l , def = parse_switch_cases eswitch cases s in
497
610
                (match def with None -> () | Some (e,p) -> error Duplicate_default p);
498
 
                l , Some (e , p1)
499
 
        | [< '(Kwd Case,p1); e = expr; '(DblDot,_); b = block1; l , def = parse_switch_cases >] ->
500
 
                (e,(b,p1)) :: l , def
 
611
                l , Some (b,p1)
 
612
        | [< '(Kwd Case,p1); el = psep Comma expr; '(DblDot,_); s >] ->
 
613
                let b = (try block1 s with Display e -> display (ESwitch (eswitch,List.rev ((el,e) :: cases),None),p1)) in
 
614
                parse_switch_cases eswitch ((el,(b,p1)) :: cases) s
501
615
        | [< >] ->
502
 
                [] , None
 
616
                List.rev cases , None
503
617
 
504
 
and parse_catch = parser
505
 
        | [< '(Kwd Catch,_); '(POpen,_); name = any_ident; s >] ->
 
618
and parse_catch etry = parser
 
619
        | [< '(Kwd Catch,p); '(POpen,_); name = any_ident; s >] ->
506
620
                match s with parser
507
 
                | [< '(DblDot,_); t = parse_type_path; '(PClose,_); e = expr >] -> (name,t,e)
 
621
                | [< '(DblDot,_); t = parse_type_path; '(PClose,_); s >] ->
 
622
                        (try
 
623
                                match s with parser
 
624
                                | [< e = expr >] ->     (name,t,e)
 
625
                                | [< >] -> serror()
 
626
                        with
 
627
                                Display e -> display (ETry (etry,[name,t,e]),p))
508
628
                | [< '(_,p) >] -> error Missing_type p
509
629
 
 
630
and toplevel_expr s =
 
631
        try
 
632
                expr s
 
633
        with
 
634
                Display e -> e
 
635
 
510
636
let parse code file =
511
637
        let old = Lexer.save() in
512
638
        let old_cache = !cache in
519
645
        and process_token tk =
520
646
                match fst tk with
521
647
                | Comment s ->
522
 
                        let l = String.length s in
523
 
                        if l > 2 && s.[0] = '*' && s.[l-1] = '*' then doc := Some (String.sub s 1 (l-2));
 
648
                        if !use_doc then begin
 
649
                                let l = String.length s in
 
650
                                if l > 0 && s.[0] = '*' then doc := Some (String.sub s 1 (l - (if l > 1 && s.[l-1] = '*' then 2 else 1)));
 
651
                        end;
524
652
                        next_token()
525
653
                | CommentLine s ->
526
654
                        next_token()
538
666
                                process_token (skip_tokens false))
539
667
                | Macro "if" ->
540
668
                        process_token (enter_macro())
 
669
                | Macro "line" ->
 
670
                        let line = (match next_token() with
 
671
                                | (Const (Int s),_) -> int_of_string s
 
672
                                | (t,p) -> error (Unexpected t) p
 
673
                        ) in
 
674
                        Lexer.cur_line := line - 1;
 
675
                        next_token();
541
676
                | _ ->
542
677
                        tk
543
678