]> Cypherpunks repositories - gostls13.git/commitdiff
implement .alternates
authorRob Pike <r@golang.org>
Tue, 28 Apr 2009 04:04:46 +0000 (21:04 -0700)
committerRob Pike <r@golang.org>
Tue, 28 Apr 2009 04:04:46 +0000 (21:04 -0700)
R=rsc
OCL=27928
CL=27928

src/lib/template/template.go
src/lib/template/template_test.go

index 1676a8fdde1a08c8cc2cbb67251f03167e05c228..c6957d4de555939fd78a390bc31bef5dd3abc736 100644 (file)
@@ -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)
+                               }
+                       }
                }
        }
 }
index cacc4404fad7c3e9bdde7c9c46599a90c540bfe4..fb931615ea6f5125d8066c9e7d65e4e93d60f6b9 100644 (file)
@@ -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{