summaryrefslogtreecommitdiff
path: root/libgo/go/text/template
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/text/template')
-rw-r--r--libgo/go/text/template/doc.go2
-rw-r--r--libgo/go/text/template/exec.go1
-rw-r--r--libgo/go/text/template/exec_test.go4
-rw-r--r--libgo/go/text/template/multi_test.go2
-rw-r--r--libgo/go/text/template/parse/lex.go25
-rw-r--r--libgo/go/text/template/parse/parse.go2
-rw-r--r--libgo/go/text/template/parse/parse_test.go15
7 files changed, 48 insertions, 3 deletions
diff --git a/libgo/go/text/template/doc.go b/libgo/go/text/template/doc.go
index 10e0f7fc373..aa50ab97f6f 100644
--- a/libgo/go/text/template/doc.go
+++ b/libgo/go/text/template/doc.go
@@ -244,7 +244,7 @@ Functions
During execution functions are found in two function maps: first in the
template, then in the global function map. By default, no functions are defined
-in the template but the Funcs methods can be used to add them.
+in the template but the Funcs method can be used to add them.
Predefined global functions are named as follows.
diff --git a/libgo/go/text/template/exec.go b/libgo/go/text/template/exec.go
index ad0118e4e68..9a720cf43e3 100644
--- a/libgo/go/text/template/exec.go
+++ b/libgo/go/text/template/exec.go
@@ -369,6 +369,7 @@ func (s *state) evalVariableNode(dot reflect.Value, v *parse.VariableNode, args
// $x.Field has $x as the first ident, Field as the second. Eval the var, then the fields.
value := s.varValue(v.Ident[0])
if len(v.Ident) == 1 {
+ s.notAFunction(args, final)
return value
}
return s.evalFieldChain(dot, value, v.Ident[1:], args, final)
diff --git a/libgo/go/text/template/exec_test.go b/libgo/go/text/template/exec_test.go
index 70ab39cad20..5446027ff7a 100644
--- a/libgo/go/text/template/exec_test.go
+++ b/libgo/go/text/template/exec_test.go
@@ -466,6 +466,10 @@ var execTests = []execTest{
{"bug6b", "{{vfunc .V0 .V0}}", "vfunc", tVal, true},
{"bug6c", "{{vfunc .V1 .V0}}", "vfunc", tVal, true},
{"bug6d", "{{vfunc .V1 .V1}}", "vfunc", tVal, true},
+ // Legal parse but illegal execution: non-function should have no arguments.
+ {"bug7a", "{{3 2}}", "", tVal, false},
+ {"bug7b", "{{$x := 1}}{{$x 2}}", "", tVal, false},
+ {"bug7c", "{{$x := 1}}{{3 | $x}}", "", tVal, false},
}
func zeroArgs() string {
diff --git a/libgo/go/text/template/multi_test.go b/libgo/go/text/template/multi_test.go
index 22dedc4f839..bd98bd047ec 100644
--- a/libgo/go/text/template/multi_test.go
+++ b/libgo/go/text/template/multi_test.go
@@ -93,7 +93,7 @@ var multiExecTests = []execTest{
{"invoke dot []int", `{{template "dot" .SI}}`, "[3 4 5]", tVal, true},
{"invoke dotV", `{{template "dotV" .U}}`, "v", tVal, true},
{"invoke nested int", `{{template "nested" .I}}`, "17", tVal, true},
- {"variable declared by template", `{{template "nested" $x=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
+ {"variable declared by template", `{{template "nested" $x:=.SI}},{{index $x 1}}`, "[3 4 5],4", tVal, true},
// User-defined function: test argument evaluator.
{"testFunc literal", `{{oneArg "joe"}}`, "oneArg=joe", tVal, true},
diff --git a/libgo/go/text/template/parse/lex.go b/libgo/go/text/template/parse/lex.go
index 54e75ee0ca2..7705c0b88ff 100644
--- a/libgo/go/text/template/parse/lex.go
+++ b/libgo/go/text/template/parse/lex.go
@@ -347,6 +347,9 @@ Loop:
default:
l.backup()
word := l.input[l.start:l.pos]
+ if !l.atTerminator() {
+ return l.errorf("unexpected character %+U", r)
+ }
switch {
case key[word] > itemKeyword:
l.emit(key[word])
@@ -365,6 +368,28 @@ Loop:
return lexInsideAction
}
+// atTerminator reports whether the input is at valid termination character to
+// appear after an identifier. Mostly to catch cases like "$x+2" not being
+// acceptable without a space, in case we decide one day to implement
+// arithmetic.
+func (l *lexer) atTerminator() bool {
+ r := l.peek()
+ if isSpace(r) {
+ return true
+ }
+ switch r {
+ case eof, ',', '|', ':':
+ return true
+ }
+ // Does r start the delimiter? This can be ambiguous (with delim=="//", $x/2 will
+ // succeed but should fail) but only in extremely rare cases caused by willfully
+ // bad choice of delimiter.
+ if rd, _ := utf8.DecodeRuneInString(l.rightDelim); rd == r {
+ return true
+ }
+ return false
+}
+
// lexChar scans a character constant. The initial quote is already
// scanned. Syntax checking is done by the parse.
func lexChar(l *lexer) stateFn {
diff --git a/libgo/go/text/template/parse/parse.go b/libgo/go/text/template/parse/parse.go
index d67b3888085..c0087b2785b 100644
--- a/libgo/go/text/template/parse/parse.go
+++ b/libgo/go/text/template/parse/parse.go
@@ -326,7 +326,7 @@ func (t *Tree) pipeline(context string) (pipe *PipeNode) {
for {
if v := t.peek(); v.typ == itemVariable {
t.next()
- if next := t.peek(); next.typ == itemColonEquals || next.typ == itemChar {
+ if next := t.peek(); next.typ == itemColonEquals || (next.typ == itemChar && next.val == ",") {
t.next()
variable := newVariable(v.val)
if len(variable.Ident) != 1 {
diff --git a/libgo/go/text/template/parse/parse_test.go b/libgo/go/text/template/parse/parse_test.go
index 18c0a8b835e..b2e788238d3 100644
--- a/libgo/go/text/template/parse/parse_test.go
+++ b/libgo/go/text/template/parse/parse_test.go
@@ -201,6 +201,10 @@ var parseTests = []parseTest{
`{{range .X | .M}}"true"{{else}}"false"{{end}}`},
{"range []int", "{{range .SI}}{{.}}{{end}}", noError,
`{{range .SI}}{{.}}{{end}}`},
+ {"range 1 var", "{{range $x := .SI}}{{.}}{{end}}", noError,
+ `{{range $x := .SI}}{{.}}{{end}}`},
+ {"range 2 vars", "{{range $x, $y := .SI}}{{.}}{{end}}", noError,
+ `{{range $x, $y := .SI}}{{.}}{{end}}`},
{"constants", "{{range .SI 1 -3.2i true false 'a'}}{{end}}", noError,
`{{range .SI 1 -3.2i true false 'a'}}{{end}}`},
{"template", "{{template `x`}}", noError,
@@ -226,6 +230,17 @@ var parseTests = []parseTest{
{"invalid punctuation", "{{printf 3, 4}}", hasError, ""},
{"multidecl outside range", "{{with $v, $u := 3}}{{end}}", hasError, ""},
{"too many decls in range", "{{range $u, $v, $w := 3}}{{end}}", hasError, ""},
+ // Equals (and other chars) do not assignments make (yet).
+ {"bug0a", "{{$x := 0}}{{$x}}", noError, "{{$x := 0}}{{$x}}"},
+ {"bug0b", "{{$x = 1}}{{$x}}", hasError, ""},
+ {"bug0c", "{{$x ! 2}}{{$x}}", hasError, ""},
+ {"bug0d", "{{$x % 3}}{{$x}}", hasError, ""},
+ // Check the parse fails for := rather than comma.
+ {"bug0e", "{{range $x := $y := 3}}{{end}}", hasError, ""},
+ // Another bug: variable read must ignore following punctuation.
+ {"bug1a", "{{$x:=.}}{{$x!2}}", hasError, ""}, // ! is just illegal here.
+ {"bug1b", "{{$x:=.}}{{$x+2}}", hasError, ""}, // $x+2 should not parse as ($x) (+2).
+ {"bug1c", "{{$x:=.}}{{$x +2}}", noError, "{{$x := .}}{{$x +2}}"}, // It's OK with a space.
}
var builtins = map[string]interface{}{