Beispiel #1
0
func (s *State) formatTreeErr(name string, tr *parse.Tree, node parse.Node, err error) error {
	loc, _ := tr.ErrorContext(node)
	if loc != "" {
		// Might to adjust the column due to the prepend varNop nodes
		file, line, col, ok := splitErrorContext(loc)
		if ok {
			col -= s.p.tmpl.offsets[tr][line]
			loc = fmt.Sprintf("%s:%d:%d", file, line, col)
		}
		err = fmt.Errorf("%s: %s", loc, err.Error())
	}
	return err
}
Beispiel #2
0
// removeVarNopNodes removes any nodes of the form
// {{ $Something := _gondola_nop }}
// They are used to fool the parser and letting us parse
// variable nodes which haven't been previously defined
// in the same template.
func (t *Template) removeVarNopNodes(tr *parse.Tree, nodes []parse.Node) []parse.Node {
	var newNodes []parse.Node
	for _, v := range nodes {
		if an, ok := v.(*parse.ActionNode); ok {
			if len(an.Pipe.Cmds) == 1 && len(an.Pipe.Cmds[0].Args) == 1 {
				if id, ok := an.Pipe.Cmds[0].Args[0].(*parse.IdentifierNode); ok && id.Ident == varNop {
					// Store offset for errors
					loc, _ := tr.ErrorContext(v)
					if _, line, _, ok := splitErrorContext(loc); ok {
						if t.offsets[tr] == nil {
							t.offsets[tr] = make(map[int]int)
						}
						varName := an.Pipe.Decl[0].Ident[0]
						// delim (2) + space (1) + len(varname) + space(1) + := (2) + space(1) + len(varNop) + space (1) + delim (2)
						t.offsets[tr][line] += 2 + 1 + len(varName) + 1 + 2 + 1 + len(varNop) + 1 + 2
					}
					continue
				}
			}
		}
		newNodes = append(newNodes, v)
	}
	return newNodes
}
Beispiel #3
0
// ReplaceTranslatableBlocks replaces begintrans/endtrans blocks
// with an equivalent action using the translation function named
// by fn.
func ReplaceTranslatableBlocks(tr *parse.Tree, fn string) error {
	var err error
	WalkTree(tr, func(n, p parse.Node) {
		if err != nil {
			return
		}
		if IsPseudoFunction(n, BeginTranslatableBlock) {
			list, ok := p.(*parse.ListNode)
			if !ok {
				loc, ctx := tr.ErrorContext(n)
				err = fmt.Errorf("%s:%s:%s not in ListNode (%T)", loc, ctx, BeginTranslatableBlock, p)
				return
			}
			cmd := &parse.CommandNode{
				NodeType: parse.NodeCommand,
				Pos:      n.Position(),
			}
			pipe := &parse.PipeNode{
				NodeType: parse.NodePipe,
				Pos:      n.Position(),
				Cmds:     []*parse.CommandNode{cmd},
			}
			repl := &parse.ActionNode{
				NodeType: parse.NodeAction,
				Pos:      n.Position(),
				Pipe:     pipe,
			}
			if repl != nil {
			}
			pos := -1
			for ii, v := range list.Nodes {
				if v == n {
					pos = ii
					break
				}
			}
			var pipes []parse.Node
			var buf bytes.Buffer
			endPos := -1
		Nodes:
			for ii, v := range list.Nodes[pos+1:] {
				switch x := v.(type) {
				case *parse.TextNode:
					buf.Write(x.Text)
				case *parse.ActionNode:
					if IsPseudoFunction(x, EndTranslatableBlock) {
						endPos = ii
						break Nodes
					}
					if len(x.Pipe.Decl) > 0 {
						loc, ctx := tr.ErrorContext(n)
						err = fmt.Errorf("%s:%s:%s translatable block can't contain a pipe with declaractions", loc, ctx, v)
					}
					buf.WriteString("%v")
					pipes = append(pipes, x.Pipe)
				default:
					loc, ctx := tr.ErrorContext(n)
					err = fmt.Errorf("%s translatable block can't contain %T %s", loc, v, ctx)
					return
				}
			}
			if buf.Len() > 0 {
				text := buf.String()
				quoted := strconv.Quote(text)
				innerPipe := &parse.PipeNode{
					NodeType: parse.NodePipe,
					Pos:      n.Position(),
					Cmds: []*parse.CommandNode{
						&parse.CommandNode{
							NodeType: parse.NodeCommand,
							Pos:      n.Position(),
							Args: []parse.Node{parse.NewIdentifier(fn), &parse.StringNode{
								NodeType: parse.NodeString,
								Pos:      n.Position(),
								Quoted:   quoted,
								Text:     text,
							}},
						},
					},
				}
				cmd.Args = append(cmd.Args, parse.NewIdentifier("printf"), innerPipe)
				cmd.Args = append(cmd.Args, pipes...)
			}
			nodes := list.Nodes[:pos]
			nodes = append(nodes, repl)
			nodes = append(nodes, list.Nodes[endPos+pos+1:]...)
			list.Nodes = nodes
		}
	})
	return err
}