File: expr.ml

package info (click to toggle)
ocaml-doc 3.09-1
  • links: PTS
  • area: non-free
  • in suites: etch, etch-m68k
  • size: 10,428 kB
  • ctags: 4,963
  • sloc: ml: 9,244; makefile: 2,413; ansic: 122; sh: 49; asm: 17
file content (94 lines) | stat: -rw-r--r-- 3,153 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
(***********************************************************************)
(*                                                                     *)
(*                           Objective Caml                            *)
(*                                                                     *)
(*               Pierre Weis, projet Cristal, INRIA Rocquencourt       *)
(*                                                                     *)
(*  Copyright 2001 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  only by permission.                                                *)
(*                                                                     *)
(***********************************************************************)
open List;;

type expr =
  | Epsilon
  | Caractres of char list
  | Alternative of expr * expr
  | Squence of expr * expr
  | Rptition of expr;;

let subtract l1 l2 =
  match l1, l2 with
  | _, [] | [], _ -> l1
  | _ ->
     let rec sub = function
       | [] -> []
       | elem :: l -> if mem elem l2 then sub l else elem :: sub l in
     sub l1;;

let union l1 l2 =
  fold_right (fun e res -> if mem e res then res else e :: res) l1 l2;;

let intervalle c1 c2 =
  let rec interv n1 n2 =
    if n1 > n2 then [] else char_of_int n1 :: interv (n1 + 1) n2 in
  interv (int_of_char c1) (int_of_char c2);;

let tous_car = intervalle '\000' '\255';;

let rec lire_expr = parser
  | [< r1 = lire_sq; r2 = lire_alternative r1 >] -> r2

and lire_alternative r1 = parser
  | [< ''|'; r2 = lire_expr >] -> Alternative(r1,r2)
  | [< >] -> r1

and lire_sq = parser
  | [< r1 = lire_rpt; r2 = lire_fin_sq r1 >] -> r2

and lire_fin_sq r1 = parser
  | [< r2 = lire_sq >] -> Squence(r1,r2)
  | [< >] -> r1

and lire_rpt = parser
  | [< r1 = lire_simple; r2 = lire_fin_rpt r1 >] -> r2

and lire_fin_rpt r1 = parser
  | [< ''*' >] -> Rptition r1
  | [< ''+' >] -> Squence(r1, Rptition r1)
  | [< ''?' >] -> Alternative(r1, Epsilon)
  | [< >] -> r1

and lire_simple = parser
  | [< ''.' >] -> Caractres tous_car
  | [< ''['; cl = lire_classe >] -> Caractres cl
  | [< ''('; r = lire_expr; '')' >] -> r
  | [< ''\\'; 'c >] -> Caractres [c]
  | [< 'c when c <> '|' && c <> ')' && c <> '$' >] ->
      Caractres [c]

and lire_classe = parser
  | [< ''^'; cl = lire_ensemble >] -> subtract tous_car cl
  | [< cl = lire_ensemble >] -> cl

and lire_ensemble = parser
  | [< '']' >] -> []
  | [< c1 = lire_car; c2 = lire_intervalle c1 >] -> c2

and lire_intervalle c1 = parser
  | [< ''-'; c2 = lire_car; reste = lire_ensemble >] ->
        union (intervalle c1 c2) reste
  | [< reste = lire_ensemble >] -> union [c1] reste

and lire_car = parser
  | [< ''\\'; 'c >] -> c
  | [< 'c >] -> c;;

let lire = parser
  | [< chapeau = (parser | [< ''^' >] -> true | [< >] -> false);
       r = lire_expr;
       dollar = (parser | [< ''$' >] -> true | [< >] -> false) >] ->
      let r1 =
       if dollar then r else Squence(r, Rptition(Caractres tous_car)) in
      if chapeau then r1 else Squence(Rptition(Caractres tous_car), r1);;