Skip to content

Commit

Permalink
Convert recognisers and parsers to use polymorphic variants.
Browse files Browse the repository at this point in the history
This simplifies the notation by allowing a flat sum
of the open forms using polymorphic variants, instead
of a tree structured sum using ordinary unions.

The union tech required indexing variant constructors
in expressions. The pv tech requires coercing them
instead.
  • Loading branch information
skaller committed Nov 17, 2017
1 parent ab2cfcd commit 0a1580f
Show file tree
Hide file tree
Showing 5 changed files with 130 additions and 123 deletions.
2 changes: 2 additions & 0 deletions src/compiler/flx_bind/flx_coerce.ml
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ print_endline ("Binding coercion " ^ sbe bsym_table x' ^ ": " ^ sbt bsym_table t
*)
if type_eq bsym_table state.Flx_lookup_state.counter t' t'' then x'
else
let t' = unfold "flx_coerce1" t' in
let t'' = unfold "flx_coerce1" t'' in
begin match t',t'' with
| BTYP_inst (i,[]),t when Flx_btype.islinear_type bsym_table t->
let n = Flx_btype.sizeof_linear_type bsym_table t in
Expand Down
88 changes: 45 additions & 43 deletions src/packages/grammars.fdoc
Original file line number Diff line number Diff line change
Expand Up @@ -41,24 +41,26 @@ fun generic_closure[T]
// NOTE: this depends on Recognisers, but Recognisers
// depends on Grammars. BAD BAD.

union open_prod_t[T] =
| Terminal of string * Recognisers::recog_t
| Nonterminal of string
| Epsilon
| Seq of list[T]
| Alt of list[T]
typedef open_prod_t[T] =
(
| `Terminal of string * Recognisers::recog_t
| `Nonterminal of string
| `Epsilon
| `Seq of list[T]
| `Alt of list[T]
)
;

typedef prod_t = open_prod_t[prod_t];

instance[T with Str[T]] Str[open_prod_t[T]]
{
fun str: open_prod_t[T] -> string =
| Terminal (s,r) => '"' + s + '"'
| Nonterminal name => name
| Epsilon => "Eps"
| Seq ss => "(" + catmap " " (str of T) ss + ")"
| Alt ss => "[" + catmap " | " (str of T) ss + "]"
| `Terminal (s,r) => '"' + s + '"'
| `Nonterminal name => name
| `Epsilon => "Eps"
| `Seq ss => "(" + catmap " " (str of T) ss + ")"
| `Alt ss => "[" + catmap " | " (str of T) ss + "]"
;
}

Expand All @@ -84,11 +86,11 @@ fun open_add_prod[T]
(acc:list[string]) (p: open_prod_t[T])
: list[string] =>
match p with
| Terminal _ => acc
| Nonterminal name => Cons (name, acc)
| Epsilon => acc
| Seq ps => fold_left aux acc ps
| Alt ps => fold_left aux acc ps
| `Terminal _ => acc
| `Nonterminal name => Cons (name, acc)
| `Epsilon => acc
| `Seq ps => fold_left aux acc ps
| `Alt ps => fold_left aux acc ps
endmatch
;

Expand All @@ -102,15 +104,15 @@ fun closure (g:grammar_t): list[string] =>

fun nullable_prod (lib:gramlib_t) (e:prod_t) (trail:list[string]) =>
match e with
| Terminal _ => false
| Seq es => fold_left (fun (acc:bool) (sym:prod_t) =>
| `Terminal _ => false
| `Seq es => fold_left (fun (acc:bool) (sym:prod_t) =>
acc and (nullable_prod lib sym trail)) true es

| Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
| `Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
acc or (nullable_prod lib sym trail)) false es

| Nonterminal nt => nullable_nt lib nt trail
| Epsilon => true
| `Nonterminal nt => nullable_nt lib nt trail
| `Epsilon => true
;

fun nullable_nt (lib: gramlib_t) (nt:string) (trail:list[string]) : bool =>
Expand All @@ -130,15 +132,15 @@ fun is_nullable_nt (lib:gramlib_t) (nt:string) =>

fun recursive_prod (lib:gramlib_t) (e:prod_t) (orig:string) (trail:list[string]) =>
match e with
| Terminal _ => false
| Seq es => fold_left (fun (acc:bool) (sym:prod_t) =>
| `Terminal _ => false
| `Seq es => fold_left (fun (acc:bool) (sym:prod_t) =>
acc or (recursive_prod lib sym orig trail)) false es

| Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
| `Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
acc or (recursive_prod lib sym orig trail)) false es

| Nonterminal nt => if nt == orig then true else recursive_nt lib nt orig trail
| Epsilon => false
| `Nonterminal nt => if nt == orig then true else recursive_nt lib nt orig trail
| `Epsilon => false
;

fun recursive_nt (lib: gramlib_t) (nt:string) (orig:string) (trail:list[string]) : bool =>
Expand All @@ -155,9 +157,9 @@ fun is_recursive_nt (lib:gramlib_t) (nt:string) =>

fun left_recursive_prod (lib:gramlib_t) (e:prod_t) (orig:string) (trail:list[string]) =>
match e with
| Terminal _ => false
| `Terminal _ => false

| Seq es =>
| `Seq es =>
let fun aux (es:list[prod_t]) =>
match es with
| Empty => false
Expand All @@ -169,14 +171,14 @@ fun left_recursive_prod (lib:gramlib_t) (e:prod_t) (orig:string) (trail:list[str
in
aux es

| Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
| `Alt es => fold_left (fun (acc:bool) (sym:prod_t) =>
acc or (left_recursive_prod lib sym orig trail)) false es

| Nonterminal nt =>
| `Nonterminal nt =>
if nt == orig then true
else left_recursive_nt lib nt orig trail

| Epsilon => false
| `Epsilon => false
;

fun left_recursive_nt (lib: gramlib_t) (nt:string) (orig:string) (trail:list[string]) : bool =>
Expand All @@ -196,30 +198,30 @@ fun unpack (fresh:1->string) (head:string, p:prod_t) : gramlib_t =
{
var out = Empty[gramentry_t];
match p with
| Epsilon => out = ([head,p]);
| Terminal _ => out = ([head,Seq ([p])]);
| Nonterminal s => out= ([head,Seq ([p])]);
| `Epsilon => out = ([head,p]);
| `Terminal _ => out = ([head,(`Seq ([p])) :>> prod_t]);
| `Nonterminal s => out= ([head,(`Seq ([p])) :>> prod_t]);

| Seq ps =>
| `Seq ps =>
var newseq = Empty[prod_t];
for term in ps do
match term with
| Epsilon => ;
| Nonterminal _ => newseq = term ! newseq;
| Terminal _ => newseq = term ! newseq;
| `Epsilon => ;
| `Nonterminal _ => newseq = term ! newseq;
| `Terminal _ => newseq = term ! newseq;
| _ =>
var newhead = fresh();
newseq = Nonterminal[prod_t] newhead ! newseq;
newseq = (`Nonterminal newhead ) :>> prod_t ! newseq;
out = unpack fresh (newhead,term);
endmatch;
done

match newseq with
| Empty => out = (head,Epsilon[prod_t]) ! out;
| _ => out = (head,Seq[prod_t] (rev newseq)) ! out;
| Empty => out = (head,(#`Epsilon) :>> prod_t ) ! out;
| _ => out = (head,(`Seq (rev newseq)) :>> prod_t) ! out;
endmatch;

| Alt ps =>
| `Alt ps =>
iter (proc (p:prod_t) { out = unpack fresh (head,p) + out; }) ps;
endmatch;
return out;
Expand Down Expand Up @@ -255,7 +257,7 @@ fun merge (var p:gramlib_t): gramlib_t =
}

proc dohead() { key = cur.0; alts = Empty[prod_t]; }
proc dofoot() { out = (key,Alt alts) ! out; }
proc dofoot() { out = (key,(`Alt alts) :>> prod_t ) ! out; }
proc dobreak() { dofoot; dohead; }
proc check() { if key != cur.0 call dobreak; }

Expand Down

0 comments on commit 0a1580f

Please sign in to comment.