summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRob Pike <r@golang.org>2009-04-27 21:04:46 -0700
committerRob Pike <r@golang.org>2009-04-27 21:04:46 -0700
commit4b69a278bf554e8bc1f49ccb47f789ad9f9dc084 (patch)
tree432c642c06d5c62d0397c43cac214978a32a937a
parent5ac70968962dc2240ff9f4f8dda4a68034137f4d (diff)
downloadgolang-4b69a278bf554e8bc1f49ccb47f789ad9f9dc084.tar.gz
implement .alternates
R=rsc OCL=27928 CL=27928
-rw-r--r--src/lib/template/template.go30
-rw-r--r--src/lib/template/template_test.go14
2 files changed, 40 insertions, 4 deletions
diff --git a/src/lib/template/template.go b/src/lib/template/template.go
index 1676a8fdd..c6957d4de 100644
--- a/src/lib/template/template.go
+++ b/src/lib/template/template.go
@@ -36,7 +36,6 @@
is executed for each element. If the array is nil or empty,
YYY is executed instead. If the {.alternates with} marker
is present, ZZZ is executed between iterations of XXX.
- (TODO(r): .alternates is not yet implemented)
{field}
{field|formatter}
@@ -132,9 +131,11 @@ type sectionElement struct {
end int; // one beyond last element
}
-// A .repeated block, possibly with a .or. TODO(r): .alternates
+// A .repeated block, possibly with a .or and a .alternates
type repeatedElement struct {
- sectionElement; // It has the same structure!
+ sectionElement; // It has the same structure...
+ altstart int; // ... except for alternates
+ altend int;
}
// Template is the type that represents a template definition.
@@ -438,6 +439,8 @@ func (t *Template) parseRepeated(words []string) *repeatedElement {
// Scan section, collecting true and false (.or) blocks.
r.start = t.elems.Len();
r.or = -1;
+ r.altstart = -1;
+ r.altend = -1;
Loop:
for {
item := t.nextItem();
@@ -455,17 +458,27 @@ Loop:
if r.or >= 0 {
t.parseError("extra .or in .repeated section");
}
+ r.altend = t.elems.Len();
r.or = t.elems.Len();
case tokSection:
t.parseSection(w);
case tokRepeated:
t.parseRepeated(w);
case tokAlternates:
- t.parseError("internal error: .alternates not implemented");
+ if r.altstart >= 0 {
+ t.parseError("extra .alternates in .repeated section");
+ }
+ if r.or >= 0 {
+ t.parseError(".alternates inside .or block in .repeated section");
+ }
+ r.altstart = t.elems.Len();
default:
t.parseError("internal error: unknown repeated section item: %s", item);
}
}
+ if r.altend < 0 {
+ r.altend = t.elems.Len()
+ }
r.end = t.elems.Len();
return r;
}
@@ -693,6 +706,9 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
if end < 0 {
end = r.end
}
+ if r.altstart >= 0 {
+ end = r.altstart
+ }
if field != nil {
array := field.(reflect.ArrayValue);
for j := 0; j < array.Len(); j++ {
@@ -700,6 +716,12 @@ func (t *Template) executeRepeated(r *repeatedElement, st *state) {
for i := start; i < end; {
i = t.executeElement(i, newst)
}
+ // If appropriate, do .alternates between elements
+ if j < array.Len() - 1 && r.altstart >= 0 {
+ for i := r.altstart; i < r.altend; i++ {
+ i = t.executeElement(i, newst)
+ }
+ }
}
}
}
diff --git a/src/lib/template/template_test.go b/src/lib/template/template_test.go
index cacc4404f..fb931615e 100644
--- a/src/lib/template/template_test.go
+++ b/src/lib/template/template_test.go
@@ -183,6 +183,20 @@ var tests = []*Test {
"this should appear: empty field\n"
},
+ &Test{
+ "{.section pdata }\n"
+ "{.repeated section @ }\n"
+ "{item}={value}\n"
+ "{.alternates with}DIVIDER\n"
+ "{.or}\n"
+ "this should not appear\n"
+ "{.end}\n"
+ "{.end}\n",
+
+ "ItemNumber1=ValueNumber1\n"
+ "DIVIDER\n"
+ "ItemNumber2=ValueNumber2\n"
+ },
// Formatters
&Test{