Skip to content

Instantly share code, notes, and snippets.

@xhluca
Created April 9, 2019 02:36
Show Gist options
  • Save xhluca/012427a3b8b2f4a5b5dd7c639a976c21 to your computer and use it in GitHub Desktop.
Save xhluca/012427a3b8b2f4a5b5dd7c639a976c21 to your computer and use it in GitHub Desktop.
open Printf;;
type attribute =
| Class of string
| Href of string
| Src of string
| Style of string
| Alt of string
| Width of int
| Height of int
;;
type element =
| Elements of element list
| Text of string
| Br
| Body of element list
| Head of element list
| Html of element list
| Li of element list
| Title of element list
| A of element list * attribute list
| B of element list * attribute list
| Button of element list * attribute list
| Div of element list * attribute list
| Form of element list * attribute list
| H1 of element list * attribute list
| H2 of element list * attribute list
| H3 of element list * attribute list
| Img of element list * attribute list
| Ol of element list * attribute list
| P of element list * attribute list
| Ul of element list * attribute list
;;
(* Parsers *)
let parse_attr (attr: attribute): string =
let format_s name s = sprintf "%s=\"%s\"" name s in
let format_d name d = sprintf "%s=%d" name d in
match attr with
| Class(s) -> format_s "class" s
| Href(s) -> format_s "href" s
| Src(s) -> format_s "src" s
| Style(s) -> format_s "style" s
| Alt(s) -> format_s "alt" s
| Width(d) -> format_d "width" d
| Height(d) -> format_d "height" d
;;
let parse_attrs (attrs: attribute list): string =
String.concat " " (List.map parse_attr attrs)
;;
let rec parse_elem (elem: element): string =
let format tag child attrs =
sprintf "<%s %s>%s</%s>\n"
tag
(parse_attrs attrs)
(String.concat "" (List.map parse_elem child))
tag
in
let format_single tag =
sprintf "<%s>" tag
in
match elem with
| Text(t) -> t
| Br ->
format_single "br"
| Body(child) ->
format "body" child []
| Head(child) ->
format "head" child []
| Html(child) ->
format "html" child []
| Li(child) ->
format "li" child []
| Title(child) ->
format "title" child []
| A(child, attrs) ->
format "a" child attrs
| B(child, attrs) ->
format "b" child attrs
| Button(child, attrs) ->
format "button" child attrs
| Div(child, attrs) ->
format "div" child attrs
| Form(child, attrs) ->
format "form" child attrs
| H1(child, attrs) ->
format "h1" child attrs
| H2(child, attrs) ->
format "h2" child attrs
| H3(child, attrs) ->
format "h3" child attrs
| Img(child, attrs) ->
format "img" child attrs
| Ol(child, attrs) ->
format "ol" child attrs
| P(child, attrs) ->
format "p" child attrs
| Ul(child, attrs) ->
format "ul" child attrs
;;
(* For testing *)
let test_attrs = [
Class("my-class");
Href("https://ocaml.org/");
Src("https://ocaml.org/img/documentation-large.svg");
Style("color: red;");
Width(50);
Height(100)
];;
let test_html = Html([
Head(
[Title([Text("Page Title")])]
);
Body([
H1([Text("This is a heading")], []);
P([Text("This is a paragraph")], test_attrs)
])
])
;;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment