This page is part of the web mail archives of SRFI 109 from before July 7th, 2015. The new archives for SRFI 109 contain all messages, not just those from before July 7th, 2015.
This is a proposed syntax for optional user-specified
end tokens for both SRFI-108 and SRFI-109.
First the proposal, then a discussion comparing alternatives.
PROPOSAL
A string quasi-literal may have an optional end-label,
specified by a '!' followed by an label. For example:
&!END{
&|line1
&|line2
}!END
Syntax:
label ::= tagname-subsequent+
It seems reasonable to allow an integer label, so we allow
starting with a digit. Thus for simplicity we also allow
hyphen, underscore, or period.
(In an unrelated change, I think tagname-subsequent should
allow periods. XML compatibility is one reason.)
extended-string-literal ::= "&" string-starttag?
"{" initial-ignored? string-literal-part* "}!" string-endtag?
string-starttag ::= "!" label
string-endtag ::= "!" label
The string-endtag is required if the string-starttag is specified,
and of course the labels must much.
Note this chance means that an extended-string-literal must be
followed by a delimiter or end of input.
For a named quasi-literal, we can use the constructor-name as an end-tag:
&example{
&|line1
&|line2
}example
DISCUSSION: Should we require a final "!" if there is no
explicit label? Make it optional? I.e.:
}example!
You can add an explicit label:
&example!23{
&|line1
&|line2
}example!23
or:
&example!23{
&|line1
&|line2
}!23
(It's not clear all these options are all that useful.)
extended-datum-body ::=
"&" cname datum-start-label? "{" initial-ignored?
named-literal-part* "}" datum-end-label?
| "&" cname datum-start-label? "[" expression* "]{" initial-ignored?
named-literal-part* "}" datum-end-label?
datum-start-label ::= "!" label
datum-end-label :=
cname "!"?
| cname? "!" label
If may occasionally be useful to make labels available for
semantic information. One example is as implicit "id" attributes.
To do that we modify the translation:
&cname!label[init-args...]{content}cname!label ==>
($construct$:cname init-args... $>>$ "content" ($construct-label$
"label"))
I.e. we add ($construct-label$ "label") as the final operand
of the $construct$:foo. We also add a standard definition:
(define ($construct-label$ label) "")
This way the $construct-label$ by default becomes a no-op,
including when using define-simple-constructor.
ALTERNATIVES
There are some plausible alternatives. For example we can put the
end-tag just before the right brace.
For named constructors we could use:
&cname{
line1
line2
&cname}
This works and parses unambiguously. However, it's difficult
to come up with a "compatible" syntax for strings,
as discussed below. Also, the start-of-literal and the
end-of-literal both start with the same prefix "&cname", which
makes visual scanning slower.
We could add the "!" as also used for strings:
&!cname}
or:
&cname!}
The former appears incompatible with optional explicit
labels (i.e. "cname!tag"), while the latter doesn't
help much with the visual scanning problem.
For strings we don't need the "&" since the end-delimiter
is required if specified:
&!END{
&|line1
&|line2
!END}
This is a little tricky to parse, since you don't know that !END if
an end-tag until you see the right-brace. (For the same reason
it's not very human-readable.) However, it doesn't feel very
consistent with the named-constructor case.
We could avoid this by requiring a '&' before the end-tag, either:
&END}
or:
&!END}
The former feels inconsistent with named constructors (it seems
to preclude explicit labels); the latter seems excessive.
--
--Per Bothner
per@xxxxxxxxxxx http://per.bothner.com/