src/Pure/Syntax/earley0A.ML
author clasohm
Thu, 16 Sep 1993 12:20:38 +0200
changeset 0 a5a9c433f639
child 18 c9ec452ff08f
permissions -rw-r--r--
Initial revision
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     1
(*  Title:      Pure/Syntax/earley0A
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     2
    ID:         $Id$
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     3
    Author:     Tobias Nipkow
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     4
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     5
Changes:
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     6
  PARSER: renamed Prod to prod
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     7
  renamed mk_early_gram to mk_earley_gram
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     8
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
     9
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    10
signature PARSER =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    11
sig
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    12
  structure XGram: XGRAM
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    13
  structure ParseTree: PARSE_TREE
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    14
  local open XGram ParseTree ParseTree.Lexicon in
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    15
  type Gram
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    16
  val compile_xgram: string list * Token prod list -> Gram
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    17
  val parse: Gram * string * Token list -> ParseTree
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    18
  val parsable: Gram * string -> bool
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    19
  exception SYNTAX_ERR of Token list
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    20
  val print_gram: Gram * Lexicon -> unit
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    21
  end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    22
end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    23
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    24
functor EarleyFun(structure XGram:XGRAM and ParseTree:PARSE_TREE): PARSER =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    25
struct
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    26
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    27
structure XGram = XGram;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    28
structure ParseTree = ParseTree;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    29
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    30
(* Linked lists: *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    31
infix 5 &;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    32
datatype 'a LList = nilL | op & of 'a * ('a LListR)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    33
withtype 'a LListR = 'a LList ref;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    34
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    35
(* Apply proc to all elements in a linked list *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    36
fun seqll (proc: '_a -> unit) : ('_a LListR -> unit) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    37
    let fun seq (ref nilL) = () |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    38
            seq (ref((a:'_a)&l)) = (proc a; seq l)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    39
    in seq end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    40
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    41
fun llist_to_list (ref nilL) = [] |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    42
    llist_to_list (ref(a&ll)) = a::(llist_to_list ll);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    43
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    44
val len = length;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    45
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    46
local open Array XGram ParseTree ParseTree.Lexicon in
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    47
nonfix sub;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    48
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    49
fun forA(p: int -> unit, a: 'a array) : unit =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    50
    let val ub = length a
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    51
        fun step(i) = if i=ub then () else (p(i); step(i+1));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    52
    in step 0 end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    53
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    54
fun itA(a0:'a, b: 'b array)(f:'a * 'b -> 'a) : 'a =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    55
    let val ub = length b
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    56
        fun acc(a,i) = if i=ub then a else acc(f(a,sub(b,i)),i+1)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    57
    in acc(a0,0) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    58
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    59
(*
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    60
Gram: name of nt -> number, nt number -> productions array,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    61
      nt number -> list of nt's reachable via copy ops
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    62
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    63
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    64
datatype Symbol = T of Token | NT of int * int
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    65
     and Op = Op of OpSyn * string * int
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    66
withtype OpSyn = Symbol array
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    67
     and OpListA = Op array * int TokenMap
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    68
     and FastAcc = int TokenMap;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    69
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    70
type Gram = int Symtab.table * OpListA array * int list array;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    71
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    72
fun non_term(Nonterminal(s,_)) = if predef_term(s)=end_token then [s] else []
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    73
  | non_term(_) = [];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    74
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    75
fun non_terms(Prod(_,symbs,_,_)) = flat(map non_term symbs);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    76
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    77
(* mk_pre_grammar converts a list of productions in external format into an
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    78
internal Gram object. *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    79
val dummyTM:FastAcc = mkTokenMap[];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    80
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    81
fun mk_pre_grammar(prods): Gram =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    82
let fun same_res(Prod(t1,_,_,_), Prod(t2,_,_,_)) = t1=t2;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    83
    val partitioned0 = partition_eq same_res prods;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    84
    val nts0 = map (fn Prod(ty,_,_,_)::_ => ty) partitioned0;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    85
    val nts' = distinct(flat(map non_terms prods)) \\ nts0;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    86
    val nts = nts' @ nts0;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    87
    val partitioned = (replicate (len nts') []) @ partitioned0;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    88
    val ntis = nts ~~ (0 upto (len(nts)-1));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    89
    val tab = foldr Symtab.update (ntis,Symtab.null);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    90
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    91
    fun nt_or_vt(s,p) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    92
        (case predef_term(s) of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    93
           end_token => let val Some(i) = Symtab.lookup(tab,s) in NT(i,p) end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    94
         | tk => T(tk));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    95
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    96
    fun mksyn(Terminal(t)) = [T(t)]
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    97
      | mksyn(Nonterminal(t)) = [nt_or_vt t]
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    98
      | mksyn(_) = [];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
    99
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   100
    fun prod2op(Prod(nt,sy,opn,p)) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   101
        let val syA = arrayoflist(flat(map mksyn sy)) in Op(syA,opn,p) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   102
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   103
    fun mkops prods = (arrayoflist(map prod2op prods),dummyTM);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   104
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   105
    val opLA = arrayoflist(map mkops partitioned);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   106
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   107
    val subs = array(length opLA,[]) : int list array;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   108
    fun newcp v (a,Op(syA,_,p)) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   109
        if p=copy_pri
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   110
        then let val NT(k,_) = sub(syA,0)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   111
             in if k mem v then a else k ins a end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   112
        else a;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   113
    fun reach v i =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   114
        let val new = itA ([],#1(sub(opLA,i))) (newcp v)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   115
            val v' = new union v
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   116
        in flat(map (reach v') new) union v' end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   117
    fun rch(i) = update(subs,i,reach[i]i);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   118
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   119
in forA(rch,subs); (tab,opLA,subs) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   120
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   121
val RootPref = "__";
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   122
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   123
(* Lookahead tables for speeding up parsing. Lkhd is a mapping from
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   124
nonterminals (in the form of OpList) to sets (lists) of token strings *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   125
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   126
type Lkhd = Token list list list;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   127
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   128
(* subst_syn(s,k) syn = [ pref k ts | ts is a token string derivable from sy
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   129
                                      under substitution s ] *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   130
(* This is the general version.
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   131
fun cross l1 l2 = flat(map (fn e2 => (map (fn e1 => e1@e2) l1)) l2);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   132
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   133
(* pref k [x1,...,xn] is [x1,...,xk] if 0<=k<=n and [x1,...,xn] otherwise *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   134
fun pref 0 l = []
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   135
  | pref _ [] = []
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   136
  | pref k (e::l) = e::(pref (k-1) l);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   137
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   138
fun subst_syn(s:Lkhd,k) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   139
    let fun subst(ref(symb & syn)):Token list list =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   140
              let val l1 = case symb of T t => [[t]] |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   141
                         NT(oplr,_) => let val Some l = assoc(s,!oplr) in l end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   142
              in distinct(map (pref k) (cross l1 (subst syn))) end |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   143
            subst _ = [[]]
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   144
    in subst end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   145
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   146
(* This one is specialized to lookahead 1 and a bit too generous *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   147
fun subst_syn(s:Lkhd,1) syA =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   148
    let fun subst i = if i = length(syA) then [[]] else
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   149
              case sub(syA,i) of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   150
                NT(j,_) => let val pre = nth_elem(j,s)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   151
                         in if [] mem pre then (pre \ []) union subst(i+1)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   152
                            else pre end |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   153
               T(tk) => [[tk]];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   154
    in subst 0 end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   155
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   156
(* mk_lkhd(G,k) returns a table which associates with every nonterminal N in
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   157
G the list of pref k s for all token strings s with N -G->* s *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   158
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   159
fun mk_lkhd(opLA:OpListA array,k:int):Lkhd =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   160
    let fun step(s:Lkhd):Lkhd =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   161
            let fun subst_op(l,Op(sy,_,_)) = subst_syn(s,k)sy union l;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   162
                fun step2(l,(opA,_)) = l@[itA([],opA)subst_op];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   163
            in writeln"."; itA([],opLA)step2 end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   164
        fun iterate(s:Lkhd):Lkhd = let val s' = step s
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   165
              in if map len s = map len s' then s
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   166
                 else iterate s' end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   167
    in writeln"Computing lookahead tables ...";
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   168
       iterate (replicate (length opLA) []) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   169
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   170
(* create look ahead tables *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   171
fun mk_earley_gram(g as (tab,opLA,_):Gram):Gram =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   172
    let val lkhd = mk_lkhd(opLA,1);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   173
        fun mk_fa(i):FastAcc =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   174
            let val opA = #1(sub(opLA,i));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   175
                fun start(j) = let val Op(sy,_,_) = sub(opA,j);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   176
                                   val pre = subst_syn(lkhd,1) sy
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   177
                        in (j,if [] mem pre then [] else map hd pre) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   178
            in mkTokenMap(map start (0 upto(length(opA)-1))) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   179
        fun updt(i) = update(opLA,i,(#1(sub(opLA,i)),mk_fa(i)));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   180
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   181
    in forA(updt,opLA); g end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   182
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   183
fun compile_xgram(roots,prods) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   184
      let fun mk_root nt = Prod(RootPref^nt,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   185
                [Nonterminal(nt,0),Terminal(end_token)],"",0);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   186
          val prods' = (map mk_root roots) @ prods
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   187
      in mk_earley_gram(mk_pre_grammar(prods')) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   188
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   189
(* State: nonterminal#, production#, index in production,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   190
          index of originating state set,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   191
          parse trees generated so far,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   192
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   193
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   194
datatype State = St of int * int * int * int * ParseTree list
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   195
withtype StateSet  = State LListR * (State -> unit) LListR;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   196
type Compl = State -> unit;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   197
type StateSetList = StateSet array;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   198
(* Debugging:
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   199
val print_SL = seqll(fn St(nti,pi,ip,fs,ptl)=>
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   200
(print_int nti; prs" "; print_int pi; prs" "; print_int ip; prs" ";
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   201
print_int fs; prs" "; print_int(len ptl); prs"\n"));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   202
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   203
fun print_SS(s1,delr) = (writeln"================="; print_SL s1);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   204
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   205
fun count_ss(ref nilL) = 0
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   206
  | count_ss(ref(_ & ss)) = count_ss(ss)+1;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   207
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   208
fun print_stat(state_sets) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   209
    let fun pr i = let val(s1,_)=sub(state_sets,i)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   210
                in prs" "; print_int(count_ss s1) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   211
    in prs"["; forA(pr,state_sets); prs"]\n" end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   212
*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   213
fun mt_stateS():StateSet = (ref nilL, ref nilL);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   214
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   215
fun mt_states(n):StateSetList = array(n,mt_stateS());
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   216
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   217
fun ismt_stateS((ref nilL,_):StateSet) = true | ismt_stateS _ = false;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   218
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   219
fun fst_state((ref(st & _),_): StateSet) = st;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   220
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   221
fun apply_all_states(f,(slr,_):StateSet) = seqll f slr;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   222
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   223
fun add_state(nti,pi,ip,from,ptl,(sllr,delr):StateSet) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   224
      let fun add(ref(St(nti',pi',ip',from',_) & rest)) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   225
                if nti=nti' andalso pi=pi' andalso ip=ip' andalso from=from'
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   226
                then ()
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   227
                else add rest |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   228
              add(last as ref nilL) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   229
                let val newst = St(nti,pi,ip,from,ptl)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   230
                in last := newst & ref nilL;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   231
                   seqll (fn compl => compl newst) delr
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   232
                end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   233
      in add sllr end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   234
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   235
fun complete(nti,syA,opn,p,ptl,ss,si as (_,delr):StateSet,opLA,rchA) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   236
      let val pt = mk_pt(opn,ptl)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   237
          fun compl(St(ntj,pj,jp,from,ptl)) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   238
                let val Op(syj,_,_) = sub(fst(sub(opLA,ntj)),pj) in
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   239
                if jp=length(syj) then () else
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   240
                case sub(syj,jp) of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   241
                  NT(nt,p') => if p >= p' andalso nti mem sub(rchA,nt)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   242
                        then add_state(ntj,pj,jp+1,from,ptl@[pt], si)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   243
                        else ()
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   244
                | _ => ()
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   245
                end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   246
      in apply_all_states(compl,ss);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   247
         if length(syA)=0 (* delayed completion in case of empty production: *)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   248
         then delr := compl & ref(!delr) else ()
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   249
      end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   250
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   251
fun predict(tk,isi,si,p',opLA) = fn nti =>
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   252
    let val (opA,tm) = sub(opLA,nti);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   253
        fun add(pi) = let val opr as Op(syA,_,p) = sub(opA,pi)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   254
                in if p < p' then () else add_state(nti,pi,0,isi,[],si) end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   255
    in seq add (applyTokenMap(tm,tk)) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   256
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   257
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   258
fun parsable((tab,_,_):Gram, root:string) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   259
        not(Symtab.lookup(tab,RootPref^root) = None);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   260
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   261
exception SYNTAX_ERR of Token list;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   262
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   263
fun unknown c = error("System Error - Trying to parse unknown category "^c);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   264
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   265
fun parse((tab,opLA,rchA):Gram, root:string, tl: Token list): ParseTree =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   266
    let val tl' = tl@[end_token];
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   267
        val state_sets = mt_states(len tl' +1);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   268
        val s0 = mt_stateS();
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   269
        val rooti = case Symtab.lookup(tab,RootPref^root) of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   270
                Some(ri) => ri | None => unknown root;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   271
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   272
        fun lr (tl,isi,si,t) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   273
            if ismt_stateS(si) then raise SYNTAX_ERR(t::tl) else
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   274
            case tl of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   275
              [] => () |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   276
              t::tl =>
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   277
                let val si1 = mt_stateS();
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   278
                    fun process(St(nti,pi,ip,from,ptl)) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   279
                          let val opA = #1(sub(opLA,nti))
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   280
                              val Op(syA,opn,p) = sub(opA,pi) in
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   281
                        if ip = length(syA)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   282
                        then complete(nti,syA,opn,p,ptl,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   283
                                        sub(state_sets,from),si,opLA,rchA)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   284
                        else case sub(syA,ip) of
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   285
                          NT(ntj,p) =>
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   286
                                seq (predict(t,isi,si,p,opLA)) (sub(rchA,ntj))
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   287
                        | T(t') =>
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   288
                            if matching_tokens(t,t')
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   289
                            then add_state(nti,pi,ip+1,from,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   290
                                           if valued_token(t)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   291
                                           then ptl@[Tip(t)] else ptl,
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   292
                                           si1)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   293
                            else () end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   294
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   295
            in apply_all_states(process,si);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   296
               update(state_sets,isi+1,si1);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   297
               lr(tl,isi+1,si1,t) end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   298
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   299
    in update(state_sets,0,s0);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   300
       add_state(rooti,0,0,0,[],s0);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   301
       lr(tl',0,s0,end_token(*dummy*));
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   302
       (*print_stat state_sets;*)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   303
       let val St(_,_,_,_,[pt]) = fst_state(sub(state_sets,len tl'))
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   304
       in pt end
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   305
    end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   306
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   307
fun print_gram ((st,opAA,rchA):Gram,lex) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   308
    let val tts = Lexicon.name_of_token;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   309
        val al = map (fn (x,y)=>(y,x)) (Symtab.alist_of st);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   310
        fun nt i = let val Some(s) = assoc(al,i) in s end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   311
        fun print_sy(T(end_token)) = prs". " |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   312
            print_sy(T(tk)) = (prs(tts tk); prs" ") |
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   313
            print_sy(NT(i,p)) = (prs((nt i)^"[");print_int p;prs"] ");
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   314
        fun print_opA(i) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   315
                let val lhs = nt i;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   316
                    val (opA,_)=sub(opAA,i);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   317
                    fun print_op(j) =
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   318
                        let val Op(sy,n,p) = sub(opA,j)
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   319
                        in prs(lhs^" = "); forA(fn i=>print_sy(sub(sy,i)),sy);
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   320
                           if n="" then () else prs(" => \""^n^"\"");
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   321
                           prs" (";print_int p;prs")\n"
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   322
                        end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   323
                in forA(print_op,opA) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   324
        fun print_rch(i) = (print_int i; prs" -> ";
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   325
                            print_list("[","]\n",print_int) (sub(rchA,i)))
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   326
    in forA(print_opA,opAA) (*; forA(print_rch,rchA) *) end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   327
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   328
end;
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   329
a5a9c433f639 Initial revision
clasohm
parents:
diff changeset
   330
end;