Created
January 12, 2020 05:19
-
-
Save delbonis/eb413ef592f6bc3a215735fd0347c14a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(* | |
* parse_sexpr returns (sexpr elements, span pos, remaining toks). It's pretty neat | |
* because it's nice and tail recursive, hopefully. | |
* | |
* The "prev" is actually in reverse order until we finalize it at an RPAREN. | |
*) | |
let rec parse_sexpr (start : pos) (prev : pos sexp list) (toks : pos tok list) | |
: (pos sexp list * pos * pos tok list, string) result = | |
match toks with | |
| TSym(s, p)::t -> (parse_sexpr start (Sym(s, p)::prev) t) | |
| TInt(i, p)::t -> (parse_sexpr start (Int(i, p)::prev) t) | |
| TBool(b, p)::t -> (parse_sexpr start (Bool(b, p)::prev) t) | |
| LPAREN(p)::t -> | |
(* | |
* This is a bit tricky. We have to set up a new sexp parse context | |
* starting here, eval it, and then make that into a Nest and continue. | |
*) | |
(match (parse_sexpr p [] t) with | |
| Ok((subexpr, subrange, remaining)) -> | |
(parse_sexpr start (Nest(subexpr, subrange)::prev) remaining) | |
| Error(e) -> Error(e)) | |
(* | |
* This is where we actually finish up the sexpr and return it. | |
*) | |
| RPAREN(p)::t -> Ok(((List.rev prev), (pos_by_bounds start p), t)) | |
(* Error case, shouldn't get this normally. Gotta do some work to find the | |
* last token's position *) | |
| [] -> | |
let (_, _, el, ec) = | |
(match prev with | |
| f::_ -> sexp_info f | |
| [] -> start) in | |
Error(Printf.sprintf "unexpected end of input after %d,%d" el ec) | |
(* | |
* This is where the heavy lifting for the top level of the S-expr parser | |
* happens. Once we get to the end of the list we reverse the prev list and | |
* return that as "the" final list of expressions. | |
*) | |
let rec parse_toks_inner (prev : pos sexp list) (toks : pos tok list) : (pos sexp list, string) result = | |
match toks with | |
| TSym(s, p)::t -> (parse_toks_inner (Sym(s, p)::prev) t) | |
| TInt(i, p)::t -> (parse_toks_inner (Int(i, p)::prev) t) | |
| TBool(b, p)::t -> (parse_toks_inner (Bool(b, p)::prev) t) | |
| LPAREN(p)::t -> | |
(match (parse_sexpr p [] t) with | |
| Ok((subexpr, subrange, remaining)) -> | |
(parse_toks_inner (Nest(subexpr, subrange)::prev) remaining) | |
| Error(e) -> Error(e)) | |
| RPAREN((sl, sc, _, _))::_ -> Error(Printf.sprintf "unexpected RPAREN at %d,%d" sl sc) | |
| [] -> Ok(List.rev prev) | |
let rec parse_toks (toks : pos tok list) : (pos sexp list, string) result = | |
parse_toks_inner [] toks |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment