1 (* Heavily modified from the SML/NJ sources. *)
3 (* Copyright 1996 by AT&T Bell Laboratories *)
6 functor PrecedenceParse (S: PRECEDENCE_PARSE_STRUCTS): PRECEDENCE_PARSE =
12 in structure Exp = Exp
13 structure Fixity = Fixity
14 structure Fixop = Fixop
15 structure Longvid = Longvid
23 fun apply {func, arg} = Exp.app (func, arg)
24 fun applyInfix {func, argl, argr} =
26 val arg = Exp.tuple (Vector.new2 (argl, argr))
28 Exp.makeRegion (Exp.App (func, arg),
37 fun finishApply {func, arg, region, ctxt} =
39 Pat.Var {name, ...} =>
40 Pat.makeRegion (Pat.App (Longvid.toLongcon name, arg),
47 Layout.str "non-constructor applied to argument in pattern",
53 fun apply ctxt {func, arg} =
54 finishApply {func = func, arg = arg,
55 region = Region.append (Pat.region func, Pat.region arg),
57 fun applyInfix ctxt {func, argl, argr} =
59 val arg = Pat.tuple (Vector.new2 (argl, argr))
61 finishApply {func = func, arg = arg,
62 region = Pat.region arg,
70 datatype t = Nonfix | Infix of int * int
72 fun eval (f: Fixity.t): t =
74 Fixity.Infix NONE => Infix (0, 1)
75 | Fixity.Infix (SOME n) => Infix (n+n, n+n+1)
76 | Fixity.Infixr NONE => Infix (1, 0)
77 | Fixity.Infixr (SOME n) => Infix (n+n+1, n+n)
78 | Fixity.Nonfix => Nonfix
80 fun make ({name: Longvid.t, fixop: Fixop.t}, E: Env.t): t =
81 case (fixop, Longvid.split name) of
82 (Fixop.None, ([], vid)) =>
83 (case Env.peekFix (E, vid) of
88 fun makePat (p: Pat.t, E: Env.t): t =
90 Pat.Var r => make (r, E)
93 fun makeExp (e: Exp.t, E: Env.t): t =
95 Exp.Var r => make (r, E)
99 (*---------------------------------------------------*)
100 (* from elaborate/precedence.sml *)
101 (*---------------------------------------------------*)
103 datatype 'a precStack =
104 INf of int * 'a * 'a precStack
105 | NONf of 'a * 'a precStack
108 fun 'a parse {apply: {func: 'a, arg: 'a} -> 'a,
109 applyInfix: {func: 'a, argl: 'a, argr: 'a} -> 'a,
110 ctxt: unit -> Layout.t,
111 fixval: 'a -> Fixval.t,
114 region: 'a -> Region.t,
115 toString: 'a -> string}: 'a =
117 fun error (r: Region.t, msg: string) =
118 Control.error (r, Layout.str msg, ctxt ())
119 fun ensureNONf ((e, f), p, start) =
128 then name ^ " starts with infix identifier: "
129 else "identifier must be used infix: ",
134 fun start token = ensureNONf (token, NILf, true)
135 (* parse an expression *)
136 fun parse (stack: 'a precStack, (item: 'a, fixval: Fixval.t)) =
137 case (stack, (item, fixval)) of
138 (NONf (e, r), (e', Fixval.Nonfix)) => NONf (apply {func = e, arg = e'}, r)
139 | (p as INf _, token) => ensureNONf (token, p, false)
140 | (p as NONf (e1, INf (bp, e2, NONf (e3, r))),
141 (e4, f as Fixval.Infix (lbp, rbp))) =>
142 if lbp > bp then INf (rbp, e4, p)
144 then error (Region.append (region e2, region e4),
145 concat ["infix identifiers with equal precedence but mixed associativity: ", toString e2, ", ", toString e4])
147 parse (NONf (applyInfix {func = e2, argl = e3, argr = e1},
150 | (p as NONf _, (e', Fixval.Infix (_, rbp))) => INf (rbp, e', p)
151 | _ => Error.bug "PrecedenceParse.parse.parse"
152 (* clean up the stack *)
155 NONf (e1, INf (_, e2, NONf (e3, r))) =>
156 finish (NONf (applyInfix {func = e2, argl = e3, argr = e1},
158 | NONf (e1, NILf) => e1
159 | INf (_, e1, NONf (e2, p)) =>
160 (error (region e1, concat [name, " ends with infix identifier: ", toString e1])
161 ; finish (NONf (apply {func = e2, arg = e1}, p)))
162 | NILf => Error.bug "PrecedenceParse.parse.finish: NILf"
163 | _ => Error.bug "PrecedenceParse.parse.finish"
164 fun getfix x = (x, fixval x)
166 if Vector.isEmpty items
168 Error.bug "PrecedenceParse.parse"
171 val item = Vector.first items
173 finish (Vector.foldFrom
174 (items, 1, start (getfix item), fn (item, state) =>
175 parse (state, getfix item)))
179 fun parsePat (ps, E, ctxt) =
180 parse {apply = Pat.apply ctxt,
181 applyInfix = Pat.applyInfix ctxt,
183 fixval = fn p => Fixval.makePat (p, E),
187 toString = Layout.toString o Pat.layout}
190 Trace.trace ("PrecedenceParse.parsePat",
191 fn (ps, _, _) => Vector.layout Pat.layout ps,
195 fun parseExp (es, E, ctxt) =
196 parse {apply = Exp.apply,
197 applyInfix = Exp.applyInfix,
199 fixval = fn e => Fixval.makeExp (e, E),
203 toString = Layout.toString o Exp.layout}
206 Trace.trace ("PrecedenceParse.parseExp",
207 fn (es, _, _) => Vector.layout Exp.layout es,
211 (*---------------------------------------------------*)
213 (*---------------------------------------------------*)
215 structure ClausePat =
218 Apply of {func: t, arg: t}
219 | ApplyInfix of {func: t, argl: t, argr: t}
225 Region.append (region func, region arg)
226 | ApplyInfix {argl, argr, ...} =>
227 Region.append (region argl, region argr)
228 | Pat p => Pat.region p
235 val func = toPat func
239 (Pat.FlatApp (Vector.new2 (func, arg)),
240 Region.append (Pat.region func, Pat.region arg))
242 | ApplyInfix {func, argl, argr} =>
244 val func = toPat func
245 val argl = toPat argl
246 val argr = toPat argr
249 (Pat.FlatApp (Vector.new3 (argl, func, argr)),
250 Region.append (Pat.region argl, Pat.region argr))
254 val layout = Pat.layout o toPat
258 fun parseClausePats (ps, E, ctxt) =
259 parse {apply = ClausePat.Apply,
260 applyInfix = ClausePat.ApplyInfix,
262 fixval = fn ClausePat.Pat p => Fixval.makePat (p, E)
263 | _ => Fixval.Nonfix,
264 items = Vector.map (ps, ClausePat.Pat),
265 name = "function clause",
266 region = ClausePat.region,
267 toString = Layout.toString o ClausePat.layout}
269 fun parseClause (pats: Pat.t vector, E: Env.t, ctxt) =
271 fun error (region, msg) =
272 Control.error (region, msg, ctxt ())
273 fun improper region =
275 (region, Layout.str "function clause with improper infix pattern")
280 | ClausePat.Apply {func, arg} =>
284 | ClausePat.ApplyInfix {func, argl, argr} =>
292 | _ => (improper (ClausePat.region p)
298 ClausePat.Apply {func, arg} =>
299 loop (func, (toPatTop arg)::args)
300 | _ => (toPatTop p)::args
305 fun done (func: Pat.t, args: Pat.t list) =
308 (error (Pat.region func,
309 Layout.seq [Layout.str "function clause with illegal name: ",
313 case Pat.node func of
314 Pat.Var {name, ...} =>
315 (case Longvid.split name of
316 ([], x) => Vid.toVar x
317 | _ => illegalName ())
318 | _ => illegalName ()
319 val args = Vector.fromList args
321 if Vector.isEmpty args
322 then error (Region.append (Pat.region (Vector.sub (pats, 0)),
323 Pat.region (Vector.last pats)),
324 Layout.str "function clause with no arguments")
327 {func = func, args = args}
329 fun doneApplyInfix ({func, argl, argr}, rest) =
331 val func = toPatTop func
332 val argl = toPatTop argl
333 val argr = toPatTop argr
335 done (func, (Pat.tuple (Vector.new2 (argl, argr)))::rest)
338 case parseClausePats (pats, E, ctxt) of
339 ClausePat.ApplyInfix func_argl_argr =>
340 doneApplyInfix (func_argl_argr, [])
343 [] => Error.bug "PrecedenceParse.parseClause: empty"
346 val improper = fn () =>
347 (improper (Pat.region p)
348 ; done (Pat.var Ast.Var.bogus, rest))
354 (case parseClausePats (pats, E, ctxt) of
355 ClausePat.ApplyInfix func_argl_argr =>
356 doneApplyInfix (func_argl_argr, rest)
359 | _ => done (p, rest)