[Ur] Hamlet like XML, structured by indentation with tag autoclosing
Gabriel Riba
gabriel at xarxaire.com
Mon Jun 29 10:34:23 EDT 2015
El 26/06/15 a les 18:12, Adam Chlipala ha escrit:
> I appreciate your ongoing efforts to improve the usability of Ur/Web.
> Based on discussion here so far, I'm leaning towards not adopting your
> additional syntax extensions. Subjectively to me, they don't make the
> code more readable, while they do introduce more independent notations
> to be understood.
I bring here some documentation and a mercurial patch of the trial
worked, for the case anyone wanted to try it.
Summary Documentation of the Indented XML, with lines' first tag
autoclosing and logic
(* Example with $foldlmapx, $if/$elsif/$else alternatives *)
val testl : list int = 1 :: 2 :: 3 :: 4 :: []
fun main (): transaction page = return <ixml>
<body>
$foldlmapx {testl} <| {x}
$if {x = 1}
<p>1
$elsif {x = 2}
<p>2
$elsif {x = 3}
<p>3
$else
<p>other
</ixml>
(* Example with $foldlmapx, $case/$of alternatives *)
val testOpts : list (option int) = Some 3 :: None :: []
fun main (): transaction page = return <ixml>
<body>
$foldlmapx {testOpts} <| {x}
$case {x}
$of {Some v}
<p>Some {[v]}
$of {None}
<p>None
</ixml>
(* Example derived from the web demo "Sql" with $foldrmapx *)
table t : { A : int, B : float, C : string, D : bool }
PRIMARY KEY A
type t_qry_item = {T: { A : int, B : float, C : string, D : bool }}
fun main () =
rows <- queryL (SELECT * FROM t) ;
return <ixml>
<body>
<table>
<tr> <th>A</th> <th>B</th> <th>C</th> <th>D</th>
$foldrmapx {rows} <| {row : t_qry_item}
<tr>
<td>{[row.T.A]}
<td>{[row.T.B]}
<td>{[row.T.C]}
<td>{[row.T.D]}
</ixml>
(*
--------------------------------------------------------------------------------------
*)
Grammar productions added (BNF):
xmlOne: ...
| IXML_FOLDRMAP LBRACE eexp RBRACE FWDAPP LBRACE eargs RBRACE
xml IXML_END_FOLDRMAP
| IXML_FOLDLMAP LBRACE eexp RBRACE FWDAPP LBRACE eargs RBRACE
xml IXML_END_FOLDLMAP
| IXML_IFTHEN LBRACE eexp RBRACE xml IXML_END_IFTHEN ixml_elsifs
IXML_ELSE xmlOpt IXML_END_ELSE
| IXML_CASE_EXPR LBRACE eexp RBRACE IXML_END_CASE_EXPR ixml_caseOfs
(* --- *)
ixml_elsif : IXML_ELSIF LBRACE eexp RBRACE xml IXML_END_ELSIF
ixml_elsifs : (* empty *)
| ixml_elsifs ixml_elsif
ixml_caseOf : IXML_CASE_OF LBRACE pat RBRACE xml IXML_END_CASE_OF
ixml_caseOfs : ixml_caseOf
| ixml_caseOfs ixml_caseOf
(* --- terminals *)
%term
| IXML_FOLDRMAP | IXML_END_FOLDRMAP | IXML_FOLDLMAP | IXML_END_FOLDLMAP
| IXML_IFTHEN | IXML_END_IFTHEN | IXML_ELSE | IXML_END_ELSE |
IXML_ELSIF | IXML_END_ELSIF
| IXML_CASE_EXPR | IXML_END_CASE_EXPR | IXML_CASE_OF | IXML_END_CASE_OF
(* --- non-terminals *)
%nonterm
| ixml_elsif of (exp * exp)
| ixml_elsifs of (exp * exp) list
| ixml_caseOf of pat * exp
| ixml_caseOfs of (pat * exp) list
(* ----------------------------------------------------------------- *)
Lexer:
new lexer states: IXML IXMLTAG IXML_LOGIC
datatype xmlStringContext = SC_XMLTAG | SC_IXMLTAG
val xmlString = ref (NONE : xmlStringContext option)
val isIXML = ref false
val ixml_candidate_tag_to_push = ref (NONE: (int * string) option)
datatype ixml_logic = IXL_FoldrMap | IXL_FoldlMap
| IXL_IfThen | IXL_Else | IXL_Elsif
| IXL_CaseExpr | IXL_CaseOf
datatype ixml_item = IX_Tag of string | IX_Logic of ixml_logic
val ixml_indents = ref ([] : (int * ixml_item) list)
val ixml_pop_deeper_or_same_level_items: int -> ixml_item option = fn
indent =>
case !ixml_indents of
[] => NONE
| (lastIndent, item) :: _ => if lastIndent >= indent then
(ixml_indents := tl
(!ixml_indents) ; SOME item)
else NONE
val ixml_emit_item_closing_and_rewind: (ixml_item * int ref * string *
int) -> (svalue,pos) Tokens.token =
fn (item, yybufpos, yytext, yypos) =>
((* rewind yybufpos *) yybufpos := (!yybufpos) - size yytext ;
case item of
(IX_Tag tag_to_close) => Tokens.END_TAG (tag_to_close, yypos,
yypos + size yytext)
| (IX_Logic ixl) => (case ixl of
IXL_FoldrMap => Tokens.IXML_END_FOLDRMAP (yypos,
yypos + size yytext)
| IXL_FoldlMap => Tokens.IXML_END_FOLDLMAP (yypos,
yypos + size yytext)
| IXL_IfThen => Tokens.IXML_END_IFTHEN (yypos, yypos +
size yytext)
| IXL_Else => Tokens.IXML_END_ELSE (yypos, yypos + size
yytext)
| IXL_Elsif => Tokens.IXML_END_ELSIF (yypos, yypos +
size yytext)
| IXL_CaseExpr => Tokens.IXML_END_CASE_EXPR (yypos,
yypos + size yytext)
| IXL_CaseOf => Tokens.IXML_END_CASE_OF (yypos, yypos +
size yytext)
)
)
(* ---- definitions *)
%%
indent = \n(\ )*;
spcs = (\ )*;
...
More in the attached patch.
More information about the Ur
mailing list