| author | ehmety | 
| Thu, 15 Nov 2001 16:46:38 +0100 | |
| changeset 12197 | d9320fb0a570 | 
| parent 11546 | 2b3f02227c35 | 
| child 12513 | 0ffb824dc95c | 
| permissions | -rw-r--r-- | 
| 240 | 1 | (* Title: Pure/Syntax/syn_ext.ML | 
| 2 | ID: $Id$ | |
| 911 
55754d6d399c
new in mixfix annotations: "' " (quote space) separates delimiters without
 wenzelm parents: 
865diff
changeset | 3 | Author: Markus Wenzel and Carsten Clasohm, TU Muenchen | 
| 240 | 4 | |
| 5 | Syntax extension (internal interface). | |
| 6 | *) | |
| 7 | ||
| 8 | signature SYN_EXT0 = | |
| 4050 | 9 | sig | 
| 6760 | 10 | val dddot_indexname: indexname | 
| 11 | val constrainC: string | |
| 240 | 12 | val typeT: typ | 
| 5690 | 13 | val max_pri: int | 
| 4050 | 14 | end; | 
| 240 | 15 | |
| 16 | signature SYN_EXT = | |
| 4050 | 17 | sig | 
| 240 | 18 | include SYN_EXT0 | 
| 1510 | 19 | val logic: string | 
| 20 | val args: string | |
| 21 | val cargs: string | |
| 22 | val any: string | |
| 23 | val sprop: string | |
| 24 | val typ_to_nonterm: typ -> string | |
| 25 | datatype xsymb = | |
| 26 | Delim of string | | |
| 27 | Argument of string * int | | |
| 28 | Space of string | | |
| 29 | Bg of int | Brk of int | En | |
| 30 | datatype xprod = XProd of string * xsymb list * string * int | |
| 31 | val chain_pri: int | |
| 4701 | 32 | val delims_of: xprod list -> string list list | 
| 1510 | 33 | datatype mfix = Mfix of string * typ * string * int list * int | 
| 34 | datatype syn_ext = | |
| 35 |     SynExt of {
 | |
| 36 | logtypes: string list, | |
| 37 | xprods: xprod list, | |
| 38 | consts: string list, | |
| 2913 | 39 | prmodes: string list, | 
| 1510 | 40 | parse_ast_translation: (string * (Ast.ast list -> Ast.ast)) list, | 
| 41 | parse_rules: (Ast.ast * Ast.ast) list, | |
| 42 | parse_translation: (string * (term list -> term)) list, | |
| 4146 | 43 | print_translation: (string * (bool -> typ -> term list -> term)) list, | 
| 1510 | 44 | print_rules: (Ast.ast * Ast.ast) list, | 
| 2694 | 45 | print_ast_translation: (string * (Ast.ast list -> Ast.ast)) list, | 
| 6322 | 46 | token_translation: (string * string * (string -> string * real)) list} | 
| 4054 | 47 | val mfix_args: string -> int | 
| 1510 | 48 | val mk_syn_ext: bool -> string list -> mfix list -> | 
| 49 | string list -> (string * (Ast.ast list -> Ast.ast)) list * | |
| 50 | (string * (term list -> term)) list * | |
| 4146 | 51 | (string * (bool -> typ -> term list -> term)) list * (string * (Ast.ast list -> Ast.ast)) list | 
| 6322 | 52 | -> (string * string * (string -> string * real)) list | 
| 1510 | 53 | -> (Ast.ast * Ast.ast) list * (Ast.ast * Ast.ast) list -> syn_ext | 
| 54 | val syn_ext: string list -> mfix list -> string list -> | |
| 55 | (string * (Ast.ast list -> Ast.ast)) list * (string * (term list -> term)) list * | |
| 4146 | 56 | (string * (bool -> typ -> term list -> term)) list * (string * (Ast.ast list -> Ast.ast)) list | 
| 6322 | 57 | -> (string * string * (string -> string * real)) list | 
| 1510 | 58 | -> (Ast.ast * Ast.ast) list * (Ast.ast * Ast.ast) list -> syn_ext | 
| 59 | val syn_ext_logtypes: string list -> syn_ext | |
| 60 | val syn_ext_const_names: string list -> string list -> syn_ext | |
| 61 | val syn_ext_rules: string list -> (Ast.ast * Ast.ast) list * (Ast.ast * Ast.ast) list -> syn_ext | |
| 4146 | 62 | val fix_tr': (term list -> term) -> bool -> typ -> term list -> term | 
| 1510 | 63 | val syn_ext_trfuns: string list -> | 
| 64 | (string * (Ast.ast list -> Ast.ast)) list * (string * (term list -> term)) list * | |
| 65 | (string * (term list -> term)) list * (string * (Ast.ast list -> Ast.ast)) list | |
| 66 | -> syn_ext | |
| 4146 | 67 | val syn_ext_trfunsT: string list -> | 
| 68 | (string * (bool -> typ -> term list -> term)) list -> syn_ext | |
| 2694 | 69 | val syn_ext_tokentrfuns: string list | 
| 6322 | 70 | -> (string * string * (string -> string * real)) list -> syn_ext | 
| 1510 | 71 | val pure_ext: syn_ext | 
| 4050 | 72 | end; | 
| 240 | 73 | |
| 1510 | 74 | structure SynExt : SYN_EXT = | 
| 240 | 75 | struct | 
| 76 | ||
| 2694 | 77 | |
| 240 | 78 | (** misc definitions **) | 
| 79 | ||
| 7472 | 80 | val dddot_indexname = ("dddot", 0);
 | 
| 6760 | 81 | val constrainC = "_constrain"; | 
| 82 | ||
| 83 | ||
| 240 | 84 | (* syntactic categories *) | 
| 85 | ||
| 86 | val logic = "logic"; | |
| 87 | val logicT = Type (logic, []); | |
| 88 | ||
| 89 | val args = "args"; | |
| 1178 | 90 | val cargs = "cargs"; | 
| 240 | 91 | |
| 330 
2fda15dd1e0f
changed the way a grammar is generated to allow the new parser to work;
 clasohm parents: 
240diff
changeset | 92 | val typeT = Type ("type", []);
 | 
| 240 | 93 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 94 | val sprop = "#prop"; | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 95 | val spropT = Type (sprop, []); | 
| 240 | 96 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 97 | val any = "any"; | 
| 624 | 98 | val anyT = Type (any, []); | 
| 99 | ||
| 780 | 100 | |
| 240 | 101 | |
| 102 | (** datatype xprod **) | |
| 103 | ||
| 104 | (*Delim s: delimiter s | |
| 105 | Argument (s, p): nonterminal s requiring priority >= p, or valued token | |
| 106 | Space s: some white space for printing | |
| 107 | Bg, Brk, En: blocks and breaks for pretty printing*) | |
| 108 | ||
| 109 | datatype xsymb = | |
| 110 | Delim of string | | |
| 111 | Argument of string * int | | |
| 112 | Space of string | | |
| 113 | Bg of int | Brk of int | En; | |
| 114 | ||
| 115 | ||
| 116 | (*XProd (lhs, syms, c, p): | |
| 117 | lhs: name of nonterminal on the lhs of the production | |
| 118 | syms: list of symbols on the rhs of the production | |
| 119 | c: head of parse tree | |
| 120 | p: priority of this production*) | |
| 121 | ||
| 122 | datatype xprod = XProd of string * xsymb list * string * int; | |
| 123 | ||
| 124 | val max_pri = 1000; (*maximum legal priority*) | |
| 125 | val chain_pri = ~1; (*dummy for chain productions*) | |
| 126 | ||
| 127 | ||
| 128 | (* delims_of *) | |
| 129 | ||
| 130 | fun delims_of xprods = | |
| 131 | let | |
| 132 | fun del_of (Delim s) = Some s | |
| 133 | | del_of _ = None; | |
| 134 | ||
| 135 | fun dels_of (XProd (_, xsymbs, _, _)) = | |
| 136 | mapfilter del_of xsymbs; | |
| 137 | in | |
| 4701 | 138 | map Symbol.explode (distinct (flat (map dels_of xprods))) | 
| 240 | 139 | end; | 
| 140 | ||
| 141 | ||
| 142 | ||
| 143 | (** datatype mfix **) | |
| 144 | ||
| 145 | (*Mfix (sy, ty, c, ps, p): | |
| 146 | sy: rhs of production as symbolic string | |
| 147 | ty: type description of production | |
| 148 | c: head of parse tree | |
| 149 | ps: priorities of arguments in sy | |
| 150 | p: priority of production*) | |
| 151 | ||
| 152 | datatype mfix = Mfix of string * typ * string * int list * int; | |
| 153 | ||
| 154 | ||
| 155 | (* typ_to_nonterm *) | |
| 156 | ||
| 865 | 157 | fun typ_to_nt _ (Type (c, _)) = c | 
| 158 | | typ_to_nt default _ = default; | |
| 159 | ||
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 160 | (*get nonterminal for rhs*) | 
| 865 | 161 | val typ_to_nonterm = typ_to_nt any; | 
| 240 | 162 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 163 | (*get nonterminal for lhs*) | 
| 865 | 164 | val typ_to_nonterm1 = typ_to_nt logic; | 
| 240 | 165 | |
| 166 | ||
| 4701 | 167 | (* read_mixfix, mfix_args *) | 
| 4050 | 168 | |
| 169 | local | |
| 170 |   fun is_meta c = c mem ["(", ")", "/", "_"];
 | |
| 171 | ||
| 4701 | 172 | val scan_delim_char = | 
| 173 | $$ "'" |-- Scan.one ((not o Symbol.is_blank) andf Symbol.not_eof) || | |
| 174 | Scan.one ((not o is_meta) andf (not o Symbol.is_blank) andf Symbol.not_eof); | |
| 4050 | 175 | |
| 176 | val scan_sym = | |
| 177 |     $$ "_" >> K (Argument ("", 0)) ||
 | |
| 4701 | 178 |     $$ "(" |-- Scan.any Symbol.is_digit >> (Bg o #1 o Term.read_int) ||
 | 
| 4050 | 179 | $$ ")" >> K En || | 
| 180 | $$ "/" -- $$ "/" >> K (Brk ~1) || | |
| 4701 | 181 | $$ "/" |-- Scan.any Symbol.is_blank >> (Brk o length) || | 
| 182 | Scan.any1 Symbol.is_blank >> (Space o implode) || | |
| 183 | Scan.repeat1 scan_delim_char >> (Delim o implode); | |
| 4050 | 184 | |
| 185 | val scan_symb = | |
| 186 | scan_sym >> Some || | |
| 4701 | 187 | $$ "'" -- Scan.one Symbol.is_blank >> K None; | 
| 4050 | 188 | |
| 4701 | 189 | val scan_symbs = Scan.repeat scan_symb --| Scan.ahead (Scan.one (not_equal "'")); | 
| 5870 | 190 | val read_symbs = mapfilter I o the o Scan.read Symbol.stopper scan_symbs; | 
| 4050 | 191 | in | 
| 4701 | 192 | val read_mixfix = read_symbs o Symbol.explode; | 
| 4050 | 193 | end; | 
| 194 | ||
| 4054 | 195 | fun mfix_args sy = | 
| 4701 | 196 | foldl (fn (i, Argument _) => i + 1 | (i, _) => i) (0, read_mixfix sy); | 
| 4050 | 197 | |
| 198 | ||
| 240 | 199 | (* mfix_to_xprod *) | 
| 200 | ||
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 201 | fun mfix_to_xprod convert logtypes (Mfix (sy, typ, const, pris, pri)) = | 
| 240 | 202 | let | 
| 203 | fun err msg = | |
| 4050 | 204 | (if msg = "" then () else error_msg msg; | 
| 205 |         error ("in mixfix annotation " ^ quote sy ^ " for " ^ quote const));
 | |
| 240 | 206 | |
| 207 | fun check_pri p = | |
| 208 | if p >= 0 andalso p <= max_pri then () | |
| 4050 | 209 |       else err ("Precedence out of range: " ^ string_of_int p);
 | 
| 240 | 210 | |
| 211 | fun blocks_ok [] 0 = true | |
| 212 | | blocks_ok [] _ = false | |
| 213 | | blocks_ok (Bg _ :: syms) n = blocks_ok syms (n + 1) | |
| 214 | | blocks_ok (En :: _) 0 = false | |
| 215 | | blocks_ok (En :: syms) n = blocks_ok syms (n - 1) | |
| 216 | | blocks_ok (_ :: syms) n = blocks_ok syms n; | |
| 217 | ||
| 218 | fun check_blocks syms = | |
| 219 | if blocks_ok syms 0 then () | |
| 4050 | 220 | else err "Unbalanced block parentheses"; | 
| 240 | 221 | |
| 222 | ||
| 223 | val cons_fst = apfst o cons; | |
| 224 | ||
| 225 | fun add_args [] ty [] = ([], typ_to_nonterm1 ty) | |
| 4050 | 226 | | add_args [] _ _ = err "Too many precedences" | 
| 240 | 227 |       | add_args (Argument _ :: syms) (Type ("fun", [ty, tys])) [] =
 | 
| 228 | cons_fst (Argument (typ_to_nonterm ty, 0)) (add_args syms tys []) | |
| 229 |       | add_args (Argument _ :: syms) (Type ("fun", [ty, tys])) (p :: ps) =
 | |
| 230 | cons_fst (Argument (typ_to_nonterm ty, p)) (add_args syms tys ps) | |
| 231 | | add_args (Argument _ :: _) _ _ = | |
| 4050 | 232 | err "More arguments than in corresponding type" | 
| 240 | 233 | | add_args (sym :: syms) ty ps = cons_fst sym (add_args syms ty ps); | 
| 234 | ||
| 235 | ||
| 236 | fun is_arg (Argument _) = true | |
| 237 | | is_arg _ = false; | |
| 238 | ||
| 239 | fun is_term (Delim _) = true | |
| 5690 | 240 | | is_term (Argument (s, _)) = Lexicon.is_terminal s | 
| 240 | 241 | | is_term _ = false; | 
| 242 | ||
| 243 | fun rem_pri (Argument (s, _)) = Argument (s, chain_pri) | |
| 244 | | rem_pri sym = sym; | |
| 245 | ||
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 246 | fun is_delim (Delim _) = true | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 247 | | is_delim _ = false; | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 248 | |
| 4054 | 249 | fun logify_types copy_prod (a as (Argument (s, p))) = | 
| 250 | if s mem logtypes then Argument (logic, p) else a | |
| 251 | | logify_types _ a = a; | |
| 240 | 252 | |
| 2364 | 253 | |
| 4701 | 254 | val raw_symbs = read_mixfix sy handle ERROR => err ""; | 
| 240 | 255 | val (symbs, lhs) = add_args raw_symbs typ pris; | 
| 2364 | 256 | val copy_prod = | 
| 257 | lhs mem ["prop", "logic"] | |
| 258 | andalso const <> "" | |
| 259 | andalso not (null symbs) | |
| 260 | andalso not (exists is_delim symbs); | |
| 261 | val lhs' = | |
| 262 | if convert andalso not copy_prod then | |
| 263 | (if lhs mem logtypes then logic | |
| 264 | else if lhs = "prop" then sprop else lhs) | |
| 265 | else lhs; | |
| 4054 | 266 | val symbs' = map (logify_types copy_prod) symbs; | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 267 | val xprod = XProd (lhs', symbs', const, pri); | 
| 240 | 268 | in | 
| 269 | seq check_pri pris; | |
| 270 | check_pri pri; | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 271 | check_blocks symbs'; | 
| 240 | 272 | |
| 5690 | 273 |     if Lexicon.is_terminal lhs' then err ("Illegal lhs: " ^ lhs')
 | 
| 240 | 274 | else if const <> "" then xprod | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 275 | else if length (filter is_arg symbs') <> 1 then | 
| 4050 | 276 | err "Copy production must have exactly one argument" | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 277 | else if exists is_term symbs' then xprod | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 278 | else XProd (lhs', map rem_pri symbs', "", chain_pri) | 
| 240 | 279 | end; | 
| 280 | ||
| 281 | ||
| 282 | (** datatype syn_ext **) | |
| 283 | ||
| 284 | datatype syn_ext = | |
| 285 |   SynExt of {
 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 286 | logtypes: string list, | 
| 240 | 287 | xprods: xprod list, | 
| 288 | consts: string list, | |
| 2913 | 289 | prmodes: string list, | 
| 1510 | 290 | parse_ast_translation: (string * (Ast.ast list -> Ast.ast)) list, | 
| 291 | parse_rules: (Ast.ast * Ast.ast) list, | |
| 240 | 292 | parse_translation: (string * (term list -> term)) list, | 
| 4146 | 293 | print_translation: (string * (bool -> typ -> term list -> term)) list, | 
| 1510 | 294 | print_rules: (Ast.ast * Ast.ast) list, | 
| 2694 | 295 | print_ast_translation: (string * (Ast.ast list -> Ast.ast)) list, | 
| 6322 | 296 | token_translation: (string * string * (string -> string * real)) list} | 
| 240 | 297 | |
| 298 | ||
| 299 | (* syn_ext *) | |
| 300 | ||
| 2694 | 301 | fun mk_syn_ext convert logtypes mfixes consts trfuns tokentrfuns rules = | 
| 240 | 302 | let | 
| 303 | val (parse_ast_translation, parse_translation, print_translation, | |
| 304 | print_ast_translation) = trfuns; | |
| 305 | val (parse_rules, print_rules) = rules; | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 306 | val logtypes' = logtypes \ "prop"; | 
| 240 | 307 | |
| 624 | 308 | val mfix_consts = distinct (map (fn (Mfix (_, _, c, _, _)) => c) mfixes); | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 309 | val xprods = map (mfix_to_xprod convert logtypes') mfixes; | 
| 240 | 310 | in | 
| 311 |     SynExt {
 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 312 | logtypes = logtypes', | 
| 624 | 313 | xprods = xprods, | 
| 11546 | 314 | consts = consts union_string mfix_consts, | 
| 2913 | 315 | prmodes = distinct (map (fn (m, _, _) => m) tokentrfuns), | 
| 240 | 316 | parse_ast_translation = parse_ast_translation, | 
| 317 | parse_rules = parse_rules, | |
| 318 | parse_translation = parse_translation, | |
| 319 | print_translation = print_translation, | |
| 320 | print_rules = print_rules, | |
| 2694 | 321 | print_ast_translation = print_ast_translation, | 
| 322 | token_translation = tokentrfuns} | |
| 240 | 323 | end; | 
| 324 | ||
| 2382 | 325 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 326 | val syn_ext = mk_syn_ext true; | 
| 240 | 327 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 328 | fun syn_ext_logtypes logtypes = | 
| 2694 | 329 | syn_ext logtypes [] [] ([], [], [], []) [] ([], []); | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 330 | |
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 331 | fun syn_ext_const_names logtypes cs = | 
| 2694 | 332 | syn_ext logtypes [] cs ([], [], [], []) [] ([], []); | 
| 555 
a7f397a14b16
removed idT, varT, tidT, tvarT (now in lexicon.ML);
 wenzelm parents: 
441diff
changeset | 333 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 334 | fun syn_ext_rules logtypes rules = | 
| 2694 | 335 | syn_ext logtypes [] [] ([], [], [], []) [] rules; | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 336 | |
| 4146 | 337 | fun fix_tr' f _ _ ts = f ts; | 
| 2382 | 338 | |
| 339 | fun syn_ext_trfuns logtypes (atrs, trs, tr's, atr's) = | |
| 2694 | 340 | syn_ext logtypes [] [] (atrs, trs, map (apsnd fix_tr') tr's, atr's) [] ([], []); | 
| 2382 | 341 | |
| 342 | fun syn_ext_trfunsT logtypes tr's = | |
| 2694 | 343 | syn_ext logtypes [] [] ([], [], tr's, []) [] ([], []); | 
| 344 | ||
| 345 | fun syn_ext_tokentrfuns logtypes tokentrfuns = | |
| 346 | syn_ext logtypes [] [] ([], [], [], []) tokentrfuns ([], []); | |
| 2382 | 347 | |
| 240 | 348 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 349 | (* pure_ext *) | 
| 240 | 350 | |
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 351 | val pure_ext = mk_syn_ext false [] | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 352 |   [Mfix ("_", spropT --> propT, "", [0], 0),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 353 |    Mfix ("_", logicT --> anyT, "", [0], 0),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 354 |    Mfix ("_", spropT --> anyT, "", [0], 0),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 355 |    Mfix ("'(_')", logicT --> logicT, "", [0], max_pri),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 356 |    Mfix ("'(_')", spropT --> spropT, "", [0], max_pri),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 357 |    Mfix ("_::_",  [logicT, typeT] ---> logicT, "_constrain", [4, 0], 3),
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 358 |    Mfix ("_::_",  [spropT, typeT] ---> spropT, "_constrain", [4, 0], 3)]
 | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 359 | [] | 
| 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 360 | ([], [], [], []) | 
| 2694 | 361 | [] | 
| 764 
b60e77395d1a
changed Pure's grammar and the way types are converted to nonterminals
 clasohm parents: 
624diff
changeset | 362 | ([], []); | 
| 240 | 363 | |
| 364 | end; |