src/Pure/Syntax/parser.ML
author wenzelm
Fri, 08 Oct 1993 14:29:55 +0100
changeset 46 f0f4978af183
parent 18 c9ec452ff08f
child 237 a7d3e712767a
permissions -rw-r--r--
*** empty log message ***
wenzelm@18
     1
(*  Title:      Pure/Syntax/parser.ML
wenzelm@46
     2
    ID:         $Id$
wenzelm@18
     3
    Author:     Sonia Mahjoub and Markus Wenzel, TU Muenchen
wenzelm@18
     4
wenzelm@18
     5
Isabelle's main parser (used for terms and typs).
wenzelm@18
     6
wenzelm@18
     7
TODO:
wenzelm@18
     8
  ~1 --> chain_pri
wenzelm@18
     9
  rename T, NT
wenzelm@18
    10
  improve syntax error
wenzelm@18
    11
  fix ambiguous grammar problem
wenzelm@18
    12
*)
wenzelm@18
    13
wenzelm@18
    14
signature PARSER =
wenzelm@18
    15
sig
wenzelm@18
    16
  structure XGram: XGRAM
wenzelm@18
    17
  structure ParseTree: PARSE_TREE
wenzelm@18
    18
  local open XGram ParseTree ParseTree.Lexicon in
wenzelm@18
    19
    type gram
wenzelm@18
    20
    val empty_gram: gram
wenzelm@18
    21
    val extend_gram: gram -> string list -> string prod list -> gram
wenzelm@18
    22
    val mk_gram: string list -> string prod list -> gram
wenzelm@18
    23
    val parse: gram -> string -> token list -> parsetree
wenzelm@18
    24
  end
wenzelm@18
    25
end;
wenzelm@18
    26
wenzelm@18
    27
functor ParserFun(structure Symtab: SYMTAB and XGram: XGRAM
wenzelm@18
    28
  and ParseTree: PARSE_TREE)(*: PARSER *) =  (* FIXME *)
wenzelm@18
    29
struct
wenzelm@18
    30
wenzelm@18
    31
structure XGram = XGram;
wenzelm@18
    32
structure ParseTree = ParseTree;
wenzelm@18
    33
structure Lexicon = ParseTree.Lexicon;
wenzelm@18
    34
open XGram ParseTree Lexicon;
wenzelm@18
    35
wenzelm@18
    36
wenzelm@18
    37
(** datatype gram **)
wenzelm@18
    38
wenzelm@18
    39
datatype symb = T of token | NT of string * int;
wenzelm@18
    40
wenzelm@18
    41
datatype gram =
wenzelm@18
    42
  Gram of string list * (symb list * string * int) list Symtab.table;
wenzelm@18
    43
wenzelm@18
    44
wenzelm@18
    45
(* empty_gram *)
wenzelm@18
    46
wenzelm@18
    47
val empty_gram = Gram ([], Symtab.null);
wenzelm@18
    48
wenzelm@18
    49
wenzelm@18
    50
(* extend_gram *)
wenzelm@18
    51
wenzelm@18
    52
(*prods are stored in reverse order*)
wenzelm@18
    53
wenzelm@18
    54
fun extend_gram (Gram (roots, tab)) new_roots xprods =
wenzelm@18
    55
  let
wenzelm@18
    56
    fun symb_of (Terminal s) = Some (T (Token s))
wenzelm@18
    57
      | symb_of (Nonterminal (s, p)) =
wenzelm@18
    58
          (case predef_term s of
wenzelm@18
    59
            EndToken => Some (NT (s, p))
wenzelm@18
    60
          | tk => Some (T tk))
wenzelm@18
    61
      | symb_of _ = None;
wenzelm@18
    62
wenzelm@18
    63
    fun prod_of (Prod (s, xsyms, c, p)) = (s, mapfilter symb_of xsyms, c, p);
wenzelm@18
    64
wenzelm@18
    65
    fun add_prod (tab, (s, syms, c, p)) =
wenzelm@18
    66
      (case Symtab.lookup (tab, s) of
wenzelm@18
    67
        None => Symtab.update ((s, [(syms, c, p)]), tab)
wenzelm@18
    68
      | Some prods => Symtab.update ((s, (syms, c, p) :: prods), tab));
wenzelm@18
    69
  in
wenzelm@18
    70
    Gram (new_roots union roots,
wenzelm@18
    71
      Symtab.balance (foldl add_prod (tab, map prod_of xprods)))
wenzelm@18
    72
  end;
wenzelm@18
    73
wenzelm@18
    74
wenzelm@18
    75
(* mk_gram *)
wenzelm@18
    76
wenzelm@18
    77
val mk_gram = extend_gram empty_gram;
wenzelm@18
    78
wenzelm@18
    79
wenzelm@18
    80
(* get_prods *)
wenzelm@18
    81
wenzelm@18
    82
fun get_prods tab s pred =
wenzelm@18
    83
  let
wenzelm@18
    84
    fun rfilter [] ys = ys
wenzelm@18
    85
      | rfilter (x :: xs) ys = rfilter xs (if pred x then x :: ys else ys);
wenzelm@18
    86
  in
wenzelm@18
    87
    (case Symtab.lookup (tab, s) of
wenzelm@18
    88
      Some prods => rfilter prods []
wenzelm@18
    89
    | None => [])
wenzelm@18
    90
  end;
wenzelm@18
    91
wenzelm@18
    92
wenzelm@18
    93
wenzelm@18
    94
(** parse **)
wenzelm@18
    95
wenzelm@18
    96
type state =
wenzelm@18
    97
  string * int
wenzelm@18
    98
    * parsetree list    (*before point*)
wenzelm@18
    99
    * symb list         (*after point*)
wenzelm@18
   100
    * string * int;
wenzelm@18
   101
wenzelm@18
   102
type earleystate = state list Array.array;
wenzelm@18
   103
wenzelm@18
   104
wenzelm@18
   105
wenzelm@18
   106
fun getProductions tab A i =
wenzelm@18
   107
  get_prods tab A (fn (_, _, j) => j >= i orelse j = ~1);
wenzelm@18
   108
wenzelm@18
   109
fun getProductions' tab A i k =
wenzelm@18
   110
  get_prods tab A (fn (_, _, j) => (j >= i andalso j < k) orelse j = ~1);
wenzelm@18
   111
wenzelm@18
   112
wenzelm@18
   113
wenzelm@18
   114
fun mkState i jj A ([NT(B,~1)],id,~1) =
wenzelm@18
   115
                     (A,max_pri,[],[NT (B,jj)],id,i)
wenzelm@18
   116
  | mkState i jj A (ss,id,j) = (A,j,[],ss,id,i) ;
wenzelm@18
   117
wenzelm@18
   118
wenzelm@18
   119
wenzelm@18
   120
fun conc (t,(k:int)) [] = (None, [(t,k)])
wenzelm@18
   121
  | conc (t,k) ((t',k')::ts) =
wenzelm@18
   122
      if (t = t')
wenzelm@18
   123
      then (Some k', ( if k' >= k
wenzelm@18
   124
                       then (t',k')::ts
wenzelm@18
   125
                       else (t,k)::ts )
wenzelm@18
   126
           )
wenzelm@18
   127
      else let val (n, ts') = conc (t,k) ts
wenzelm@18
   128
           in (n, (t',k')::ts')
wenzelm@18
   129
           end;
wenzelm@18
   130
wenzelm@18
   131
wenzelm@18
   132
fun update_tree ((B,(i,ts))::used) (A,t) =
wenzelm@18
   133
      if   (A = B)
wenzelm@18
   134
      then
wenzelm@18
   135
          let val (n,ts') = conc t ts
wenzelm@18
   136
          in  ((A,(i,ts'))::used, n)
wenzelm@18
   137
          end
wenzelm@18
   138
      else
wenzelm@18
   139
          let val (used', n) = update_tree used (A,t)
wenzelm@18
   140
          in  ((B,(i,ts)) :: used', n)
wenzelm@18
   141
          end;
wenzelm@18
   142
wenzelm@18
   143
wenzelm@18
   144
wenzelm@18
   145
fun update_index ((B,(i,ts))::used) (A,j) =
wenzelm@18
   146
      if   (A = B)
wenzelm@18
   147
      then (A,(j,ts)) :: used
wenzelm@18
   148
      else (B,(i,ts)) :: (update_index used (A,j));
wenzelm@18
   149
wenzelm@18
   150
wenzelm@18
   151
wenzelm@18
   152
fun getS A i Si =
wenzelm@18
   153
       filter (fn (_,_,_,(NT(B,j))::_,_,_)
wenzelm@18
   154
                                    => (A=B andalso j<=i)
wenzelm@18
   155
               |      _             => false
wenzelm@18
   156
              ) Si;
wenzelm@18
   157
wenzelm@18
   158
wenzelm@18
   159
wenzelm@18
   160
fun getS' A k n Si =
wenzelm@18
   161
       filter (fn (_,_,_,(NT(B,j))::_,_,_) => (A=B andalso
wenzelm@18
   162
                                               j<=k andalso
wenzelm@18
   163
                                               j>n )
wenzelm@18
   164
               |      _                    => false
wenzelm@18
   165
              ) Si;
wenzelm@18
   166
wenzelm@18
   167
wenzelm@18
   168
wenzelm@18
   169
fun getStates Estate i ii A k =
wenzelm@18
   170
       filter (fn (_,_,_,(NT(B,j))::_,_,_)
wenzelm@18
   171
                                    => (A=B andalso j<=k)
wenzelm@18
   172
               |      _             => false
wenzelm@18
   173
              )
wenzelm@18
   174
              (Array.sub (Estate, ii))
wenzelm@18
   175
;
wenzelm@18
   176
wenzelm@18
   177
wenzelm@18
   178
wenzelm@18
   179
(* MMW *)(* FIXME *)
wenzelm@18
   180
fun movedot_term (A,j,ts,T a::sa,id,i) c =
wenzelm@18
   181
                   if (valued_token c)
wenzelm@18
   182
                   then (A,j,(ts@[Tip c]),sa,id,i)
wenzelm@18
   183
                   else (A,j,ts,sa,id,i) ;
wenzelm@18
   184
wenzelm@18
   185
wenzelm@18
   186
wenzelm@18
   187
fun movedot_nonterm ts  (A,j,tss,NT(B,k) ::sa,id,i) =
wenzelm@18
   188
                         (A,j,tss@ts,sa,id,i) ;
wenzelm@18
   189
wenzelm@18
   190
wenzelm@18
   191
wenzelm@18
   192
fun movedot_lambda  _  [] = []
wenzelm@18
   193
  | movedot_lambda (B,j,tss,(NT(A,k))::sa,id,i) ((t,ki)::ts) =
wenzelm@18
   194
    if k <= ki
wenzelm@18
   195
    then (B,j,tss@t,sa,id,i) ::
wenzelm@18
   196
         (movedot_lambda (B,j,tss,(NT(A,k))::sa,id,i) ts)
wenzelm@18
   197
    else movedot_lambda (B,j,tss,(NT(A,k))::sa,id,i) ts
wenzelm@18
   198
  ;
wenzelm@18
   199
wenzelm@18
   200
wenzelm@18
   201
wenzelm@18
   202
wenzelm@18
   203
fun PROCESSS Estate grammar i c states =
wenzelm@18
   204
wenzelm@18
   205
let
wenzelm@18
   206
fun processS used [] (Si,Sii) = (Si,Sii)
wenzelm@18
   207
 |  processS used (S::States) (Si,Sii) =
wenzelm@18
   208
     ( case S of
wenzelm@18
   209
wenzelm@18
   210
        (_,_,_,(NT (A,j))::_,_,_)  =>
wenzelm@18
   211
          let
wenzelm@18
   212
            val (used_neu, States_neu) =
wenzelm@18
   213
              ( case assoc (used, A) of
wenzelm@18
   214
                 Some (k,l) =>         (* A gehoert zu used *)
wenzelm@18
   215
wenzelm@18
   216
                   if (k <= j)          (* Prioritaet wurde
wenzelm@18
   217
                                           behandelt  *)
wenzelm@18
   218
                   then
wenzelm@18
   219
                        (used, movedot_lambda S l)
wenzelm@18
   220
wenzelm@18
   221
                   else         (* Prioritaet wurde noch nicht
wenzelm@18
   222
                                        behandelt  *)
wenzelm@18
   223
                        let val L =
wenzelm@18
   224
                                getProductions' grammar A j k
wenzelm@18
   225
                            val States' = map (mkState i j A) L
wenzelm@18
   226
                        in
wenzelm@18
   227
                            (update_index used (A,j),
wenzelm@18
   228
                             States'@ movedot_lambda S l
wenzelm@18
   229
                            )
wenzelm@18
   230
                        end
wenzelm@18
   231
wenzelm@18
   232
                | None =>       (* A gehoert nicht zu used *)
wenzelm@18
   233
                      let val L = getProductions grammar A j
wenzelm@18
   234
                          val States' = map (mkState i j A) L
wenzelm@18
   235
                      in
wenzelm@18
   236
                          ((A,(j,[]))::used, States')
wenzelm@18
   237
                      end
wenzelm@18
   238
              )
wenzelm@18
   239
          in
wenzelm@18
   240
             processS used_neu (States @ States_neu) (S::Si,Sii)
wenzelm@18
   241
          end
wenzelm@18
   242
wenzelm@18
   243
     |  (_,_,_,(T a)::_,_,_)  =>
wenzelm@18
   244
                processS used States
wenzelm@18
   245
                    (S::Si, if (matching_tokens (a, c))
wenzelm@18
   246
                            then  (movedot_term S c)::Sii   (* MMW *)(* FIXME *)
wenzelm@18
   247
                            else Sii
wenzelm@18
   248
                    )
wenzelm@18
   249
wenzelm@18
   250
wenzelm@18
   251
     |  (A,k,ts,[],id,j) =>
wenzelm@18
   252
          let val tt = if id = ""
wenzelm@18
   253
                       then ts
wenzelm@18
   254
                       else [Node(id,ts)]
wenzelm@18
   255
          in
wenzelm@18
   256
             if (j = i)
wenzelm@18
   257
             then
wenzelm@18
   258
                let val (used',O) = update_tree used (A,(tt,k))
wenzelm@18
   259
                in ( case O of
wenzelm@18
   260
                      None =>
wenzelm@18
   261
                         let val Slist = getS A k Si
wenzelm@18
   262
                             val States' =
wenzelm@18
   263
                              map (movedot_nonterm tt ) Slist
wenzelm@18
   264
                         in  processS used'
wenzelm@18
   265
                             (States @ States') (S::Si,Sii)
wenzelm@18
   266
                         end
wenzelm@18
   267
                   |  Some n =>
wenzelm@18
   268
                         if (n >= k)
wenzelm@18
   269
                         then
wenzelm@18
   270
                            processS used' States (S::Si,Sii)
wenzelm@18
   271
                         else
wenzelm@18
   272
                            let val Slist = getS' A k n Si
wenzelm@18
   273
                                val States' =
wenzelm@18
   274
                              map (movedot_nonterm tt ) Slist
wenzelm@18
   275
                            in
wenzelm@18
   276
                              processS used'
wenzelm@18
   277
                              (States @ States') (S::Si,Sii)
wenzelm@18
   278
                            end
wenzelm@18
   279
                   )
wenzelm@18
   280
                end
wenzelm@18
   281
wenzelm@18
   282
              else
wenzelm@18
   283
                processS used (States @
wenzelm@18
   284
                               map (movedot_nonterm tt)
wenzelm@18
   285
                               (getStates Estate i j A k))
wenzelm@18
   286
                (S::Si,Sii)
wenzelm@18
   287
           end
wenzelm@18
   288
     )
wenzelm@18
   289
in
wenzelm@18
   290
   processS [] states ([],[])
wenzelm@18
   291
end;
wenzelm@18
   292
wenzelm@18
   293
wenzelm@18
   294
wenzelm@18
   295
fun syntax_error toks =
wenzelm@18
   296
  error ("Syntax error at: " ^ space_implode " " (map str_of_token toks));
wenzelm@18
   297
wenzelm@18
   298
fun Produce grammar stateset i indata =
wenzelm@18
   299
      case (Array.sub (stateset,i)) of
wenzelm@18
   300
         [] => syntax_error indata (* MMW *)(* FIXME *)
wenzelm@18
   301
      |  s  =>
wenzelm@18
   302
           (case indata of
wenzelm@18
   303
                []  => Array.sub (stateset,i)
wenzelm@18
   304
             |  (c::cs) =>
wenzelm@18
   305
                       let val (si,sii) =
wenzelm@18
   306
                           PROCESSS stateset grammar i c s
wenzelm@18
   307
                       in
wenzelm@18
   308
                           Array.update (stateset,i,si);
wenzelm@18
   309
                           Array.update (stateset,i+1,sii);
wenzelm@18
   310
                           Produce grammar stateset (i+1) cs
wenzelm@18
   311
                       end
wenzelm@18
   312
           );
wenzelm@18
   313
wenzelm@18
   314
wenzelm@18
   315
fun get_trees [] = []
wenzelm@18
   316
  | get_trees ((_,_,pt_lst,_,_,_) :: stateset) =
wenzelm@18
   317
       let val l = get_trees stateset
wenzelm@18
   318
       in case pt_lst of
wenzelm@18
   319
            [ptree] => ptree :: l
wenzelm@18
   320
          |   _     => l
wenzelm@18
   321
       end;
wenzelm@18
   322
wenzelm@18
   323
wenzelm@18
   324
wenzelm@18
   325
fun earley grammar startsymbol indata =
wenzelm@18
   326
   let  val S0 =
wenzelm@18
   327
       [("S'",0,[],[NT (startsymbol,0), T EndToken],"",0)]
wenzelm@18
   328
        val s = length indata + 1     (* MMW *)(* FIXME was .. + 2 *)
wenzelm@18
   329
        val Estate = Array.array (s, [])
wenzelm@18
   330
   in   Array.update (Estate,0,S0);
wenzelm@18
   331
        let val l = Produce grammar Estate 0 indata    (* MMW *)(* FIXME was .. @ [EndToken] *)
wenzelm@18
   332
            val p_trees = get_trees l
wenzelm@18
   333
        in p_trees
wenzelm@18
   334
        end
wenzelm@18
   335
   end;
wenzelm@18
   336
wenzelm@18
   337
wenzelm@18
   338
(* FIXME demo *)
wenzelm@18
   339
fun parse (Gram (roots, prod_tab)) root toks =
wenzelm@18
   340
  if root mem roots then
wenzelm@18
   341
    (case earley prod_tab root toks of
wenzelm@18
   342
      [] => error "parse: no parse trees"
wenzelm@18
   343
    | pt :: _ => pt)
wenzelm@18
   344
  else error ("Unparsable category: " ^ root);
wenzelm@18
   345
wenzelm@18
   346
wenzelm@18
   347
end;
wenzelm@18
   348