[Ur] Hamlet like XML, structured by indentation with tag autoclosing
Gabriel Riba
gabriel at xarxaire.com
Wed Jun 17 13:37:55 EDT 2015
I have worked out the feasibility of Haskell's Hamlet style xml.
(https://hackage.haskell.org/package/hamlet)
<ixml>
<body>
<h3> title
$if {null item_list_expr}
<p> Sorry, no items
$else
<ul>
$for {item} <- {item_list_expr}
<li> <b>{[item]}</b>
</ixml>
Are you interested?
I made it work.
Other logic control statements are harder to work out.
(* ----- *)
Here are some details:
Auto-closing of line-beginning tags is done on the lexer, emitting
closing tags for precedent lines with same or deeper indentation.
To emit extra tokens on a specific input the rule can be re-executed by
rewinding the next character pointer (yybufpos) to the precedent position:
yybufpos := (!yybufpos) - size yytext
New lexer states:
1.IXML state between <ixml></ixml> accepting XML state like inputs.
2.IXML_TAG similar to XMLTAG where to distinguish indented tags to
close from empty tags. (pending)
3.IXML_LOGIC where to look for logic parameters
A new stack variable of indented Tags/Logic.
Every new indented line will emit closing tokens
for deeper or equal indented items on the stack
(variable ixml_indents: (int * ixml_item) list)
Prevent nesting of IXML states, with an isIXML variable.
(pending)
To distinguish indented empty tags,
a tag to close must be pushed at the first only '>' IXML_TAG state
input, iif there is no precedent '/'.
(variable ixml_candidate_tag_to_push: string option)
The STRING state finalisation must take on account an extra state where
to return (INITIAL, XMLTAG, IXML_TAG).
-----
Grammar additions:
* terminals
| IXML_FOR | IXML_END_FOR
| IXML_IFTHEN | IXML_END_IFTHEN | IXML_ELSE | IXML_END_ELSE
* extra xml production rules:
(* $if $else rule:
*)
| IXML_IFTHEN LBRACE eexp RBRACE xml IXML_END_IFTHEN
IXML_ELSE xmlOpt IXML_END_ELSE
(let
val loc = s (IXML_IFTHENleft, IXML_END_ELSEright)
in
(ECase (eexp, [((PCon (["Basis"], "True", NONE), loc), xml),
((PCon (["Basis"], "False", NONE), loc),
xmlOpt)]), loc)
end)
(* $for rule:
List.foldr join <xml/> (List.mp (fn item_patt => xml) items_expr)
*)
| IXML_FOR LBRACE eargs RBRACE LARROW LBRACE eexp RBRACE xml
IXML_END_FOR
(let
val loc = s (IXML_FORleft, IXML_END_FORright)
val fn_item_pattern_to_xml = #1 (eargs (xml, (CWild (KType,
loc), loc)))
val list_map = (EVar (["List"], "mp", Infer), loc)
val list_foldr = (EVar (["List"], "foldr", Infer), loc)
val basis_join = (EVar (["Basis"], "join", Infer), loc)
val xmlEmpty = (EApp ((EVar (["Basis"], "cdata", Infer), loc),
(EPrim (Prim.String (Prim.Html, "")), loc))
, loc)
val e = (EApp (list_map, fn_item_pattern_to_xml), loc)
val e1 = (EApp (e, eexp), loc)
val e = (EApp (list_foldr, basis_join), loc)
val e = (EApp (e, xmlEmpty), loc)
in
(EApp (e, e1), loc)
end
)
More information about the Ur
mailing list