Skip to content

Commit

Permalink
Add demo of how to make a domain specific language
Browse files Browse the repository at this point in the history
for arbitrary term construction.
  • Loading branch information
skaller committed Nov 29, 2023
1 parent 72ca5ca commit eedadd8
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions gtest.flx
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
SCHEME """(define (mklist es)`(ast_apply ,_sr (,(nos "list") (ast_tuple ,_sr ,es))))""";

syntax grammar {
x[let_pri]:= "grammar" xproduction* "endgrammar" =>#
"""`(ast_variant ("grammar" ,(mklist _2)))"""
;

xproduction := sname ":=" (xnonterminal | xterminal)* ";" =>#
"""
(let*
(
(cast (lambda (sym)`(ast_coercion ,_sr (,sym ,(nos "sym_t")))))
(mapcast (map cast _3))
)
`(ast_variant ("production" (ast_tuple ,_sr (,(stringof _1) ,(mklist mapcast)))))
)
"""
;

xnonterminal := sname =>#
"""`(ast_variant ("nonterminal" ,(stringof _1)))"""
;

xterminal := sstring =># // a string, to be interpreted as a regexp
"""`(ast_variant ("terminal" ,(stringof _1))))""";
}

open syntax grammar;
println$ "Grammar test";
var s = grammar
start := x y;
x := "Jello";
y := "world";
endgrammar;
println$ "Grammar spec parsed";
typedef gram_t = (
| `grammar of list[prod_t]
);
typedef prod_t = (
| `production of string * list[sym_t]
);
typedef sym_t = (
| `terminal of string
| `nonterminal of string
);

instance Str[sym_t] {
fun str(x:sym_t):string =>
match x with
| `terminal s => "(terminal " + s + ")"
| `nonterminal s => "(nonterminal " + s + ")"
endmatch
;
}
instance Str[prod_t] {
fun str(x:prod_t):string =>
match x with
| `production (name, ls) => " production " name + " := " + List::cat "," (List::map (str of sym_t) ls) + ";"
endmatch
;
}
instance Str[gram_t] {
fun str(x:gram_t):string =>
match x with
| `grammar ls => "grammar" + List::cat "\n" (List::map (str of prod_t) ls) +"\nendgrammar\n"
endmatch
;
}


println$ s.str;



0 comments on commit eedadd8

Please sign in to comment.