Skip to content

Instantly share code, notes, and snippets.

@aturon
Created September 9, 2011 20:34
Show Gist options
  • Save aturon/1207265 to your computer and use it in GitHub Desktop.
Save aturon/1207265 to your computer and use it in GitHub Desktop.
The Burke-Fisher functor
signature PARSER =
sig
type token
val exampleToks: token list
type span = (int * int)
type 'stream lexer = 'stream -> token * span * 'stream
type result
exception ParseError of span
val parse: 'stream lexer -> 'stream -> result
end
functor BurkeFisher (P: PARSER) =
struct
open P (* we'll shadow result and parse *)
(* instantiate Dave Herman's pearl to get delimited control *)
structure C = GreatEscape(type ans = P.result)
type repair = token * span * token
datatype result
= REPAIR of repair
| RESULT of P.result
fun tryToks cpt [] = NONE
| tryToks cpt (tok::toks) =
let val ((oldTok, span, strm'), k) = cpt
in k (tok, span, strm');
SOME (oldTok, span, tok)
end
handle ParseError _ => tryToks cpt toks
fun tryCpts [] = NONE
| tryCpts (cpt::cpts) =
case tryToks cpt exampleToks
of NONE => tryCpts cpts
| repair => repair
fun parse lex strm =
let val cpts = ref []
fun push cpt = cpts := cpt :: !cpts
fun cptLex strm =
let val lr = lex strm
in C.shift (fn k => (push (lr, k); k lr))
end
in RESULT (C.reset (fn () => P.parse cptLex strm))
handle ParseError span =>
case tryCpts (!cpts)
of SOME r => REPAIR r
| NONE => raise ParseError span
end
end: PARSER
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment