1
package parser
2

3
import (
4
	"fmt"
5

6
	log "github.com/sirupsen/logrus"
7

8
	"github.com/pkg/errors"
9

10
	"github.com/noirbizarre/gonja/nodes"
11
	"github.com/noirbizarre/gonja/tokens"
12
)
13

14
type StatementParser func(parser *Parser, args *Parser) (nodes.Statement, error)
15

16
// Tag = "{%" IDENT ARGS "%}"
17 0
func (p *Parser) ParseStatement() (nodes.Statement, error) {
18 0
	log.WithFields(log.Fields{
19 0
		"current": p.Current(),
20 0
	}).Trace("ParseStatement")
21 0

22 0
	if p.Match(tokens.BlockBegin) == nil {
23 0
		return nil, p.Error("'{%' expected here", p.Current())
24 0
	}
25

26 0
	name := p.Match(tokens.Name)
27 0
	if name == nil {
28 0
		return nil, p.Error("Expected a statement name here", p.Current())
29 0
	}
30

31
	// Check for the existing statement
32 0
	stmtParser, exists := p.Statements[name.Val]
33 0
	if !exists {
34 0
		// Does not exists
35 0
		return nil, p.Error(fmt.Sprintf("Statement '%s' not found (or beginning not provided)", name.Val), name)
36 0
	}
37

38
	// Check sandbox tag restriction
39
	// if _, isBanned := p.bannedStmts[tokenName.Val]; isBanned {
40
	// 	return nil, p.Error(fmt.Sprintf("Usage of statement '%s' is not allowed (sandbox restriction active).", tokenName.Val), tokenName)
41
	// }
42

43 0
	var args []*tokens.Token
44 0
	for p.Peek(tokens.BlockEnd) == nil && !p.Stream.End() {
45 0
		// Add token to args
46 0
		args = append(args, p.Next())
47 0
		// p.Consume() // next token
48 0
	}
49

50
	// EOF?
51
	// if p.Remaining() == 0 {
52
	// 	return nil, p.Error("Unexpectedly reached EOF, no statement end found.", p.lastToken)
53
	// }
54

55 0
	if p.Match(tokens.BlockEnd) == nil {
56 0
		return nil, p.Error(fmt.Sprintf(`Expected end of block "%s"`, p.Config.BlockEndString), p.Current())
57 0
	}
58

59 0
	argParser := NewParser("statement", p.Config, tokens.NewStream(args))
60 0
	// argParser := newParser(p.name, argsToken, p.template)
61 0
	// if len(argsToken) == 0 {
62 0
	// 	// This is done to have nice EOF error messages
63 0
	// 	argParser.lastToken = tokenName
64 0
	// }
65 0

66 0
	p.Level++
67 0
	defer func() { p.Level-- }()
68 0
	return stmtParser(p, argParser)
69
}
70

71
// type StatementParser func(parser *Parser, args *Parser) (nodes.Stmt, error)
72

73 4
func (p *Parser) ParseStatementBlock() (*nodes.StatementBlock, error) {
74 4
	log.WithFields(log.Fields{
75 4
		"current": p.Current(),
76 4
	}).Trace("ParseStatementBlock")
77 1

78 4
	begin := p.Match(tokens.BlockBegin)
79 4
	if begin == nil {
80 0
		return nil, errors.Errorf(`Expected "%s" got "%s"`, p.Config.BlockStartString, p.Current())
81 0
	}
82

83 4
	name := p.Match(tokens.Name)
84 4
	if name == nil {
85 0
		return nil, p.Error("Expected a statement name here", p.Current())
86 0
	}
87

88
	// Check for the existing statement
89 4
	stmtParser, exists := p.Statements[name.Val]
90 4
	if !exists {
91 0
		// Does not exists
92 0
		return nil, p.Error(fmt.Sprintf("Statement '%s' not found (or beginning not provided)", name.Val), name)
93 0
	}
94

95
	// Check sandbox tag restriction
96
	// if _, isBanned := p.bannedStmts[tokenName.Val]; isBanned {
97
	// 	return nil, p.Error(fmt.Sprintf("Usage of statement '%s' is not allowed (sandbox restriction active).", tokenName.Val), tokenName)
98
	// }
99

100 4
	log.Trace("args")
101 4
	var args []*tokens.Token
102 4
	for p.Peek(tokens.BlockEnd) == nil && !p.Stream.End() {
103 4
		log.Trace("for args")
104 1
		// Add token to args
105 4
		args = append(args, p.Next())
106 1
		// p.Consume() // next token
107 1
	}
108 4
	log.Trace("loop ended")
109 1

110 1
	// EOF?
111 1
	// if p.Remaining() == 0 {
112 1
	// 	return nil, p.Error("Unexpectedly reached EOF, no statement end found.", p.lastToken)
113 1
	// }
114 1

115 4
	end := p.Match(tokens.BlockEnd)
116 4
	if end == nil {
117 0
		return nil, p.Error(fmt.Sprintf(`Expected end of block "%s"`, p.Config.BlockEndString), p.Current())
118 0
	}
119 4
	log.WithFields(log.Fields{
120 4
		"args": args,
121 4
	}).Trace("Matched end block")
122 1

123 4
	stream := tokens.NewStream(args)
124 4
	log.WithFields(log.Fields{
125 4
		"stream": stream,
126 4
	}).Trace("Got stream")
127 4
	argParser := NewParser(fmt.Sprintf("%s:args", name.Val), p.Config, stream)
128 4
	log.Trace("argparser")
129 1
	// argParser := newParser(p.name, argsToken, p.template)
130 1
	// if len(argsToken) == 0 {
131 1
	// 	// This is done to have nice EOF error messages
132 1
	// 	argParser.lastToken = tokenName
133 1
	// }
134 1

135 1
	// p.template.level++
136 1
	// defer func() { p.template.level-- }()
137 4
	stmt, err := stmtParser(p, argParser)
138 4
	if err != nil {
139 0
		return nil, errors.Wrapf(err, `Unable to parse statement "%s"`, name.Val)
140 0
	}
141 4
	log.Trace("got stmt and return")
142 4
	return &nodes.StatementBlock{
143 4
		Location: begin,
144 4
		Name:     name.Val,
145 4
		Stmt:     stmt,
146 4
		LStrip:   begin.Val[len(begin.Val)-1] == '+',
147 4
		Trim: &nodes.Trim{
148 4
			Left:  begin.Val[len(begin.Val)-1] == '-',
149 4
			Right: end.Val[0] == '-',
150 4
		},
151 4
	}, nil
152
}

Read our documentation on viewing source code .

Loading