...

Source file src/github.com/noirbizarre/gonja/parser/statement.go

Documentation: github.com/noirbizarre/gonja/parser

     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  func (p *Parser) ParseStatement() (nodes.Statement, error) {
    18  	log.WithFields(log.Fields{
    19  		"current": p.Current(),
    20  	}).Trace("ParseStatement")
    21  
    22  	if p.Match(tokens.BlockBegin) == nil {
    23  		return nil, p.Error("'{%' expected here", p.Current())
    24  	}
    25  
    26  	name := p.Match(tokens.Name)
    27  	if name == nil {
    28  		return nil, p.Error("Expected a statement name here", p.Current())
    29  	}
    30  
    31  	// Check for the existing statement
    32  	stmtParser, exists := p.Statements[name.Val]
    33  	if !exists {
    34  		// Does not exists
    35  		return nil, p.Error(fmt.Sprintf("Statement '%s' not found (or beginning not provided)", name.Val), name)
    36  	}
    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  	var args []*tokens.Token
    44  	for p.Peek(tokens.BlockEnd) == nil && !p.Stream.End() {
    45  		// Add token to args
    46  		args = append(args, p.Next())
    47  		// p.Consume() // next token
    48  	}
    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  	if p.Match(tokens.BlockEnd) == nil {
    56  		return nil, p.Error(fmt.Sprintf(`Expected end of block "%s"`, p.Config.BlockEndString), p.Current())
    57  	}
    58  
    59  	argParser := NewParser("statement", p.Config, tokens.NewStream(args))
    60  	// argParser := newParser(p.name, argsToken, p.template)
    61  	// if len(argsToken) == 0 {
    62  	// 	// This is done to have nice EOF error messages
    63  	// 	argParser.lastToken = tokenName
    64  	// }
    65  
    66  	p.Level++
    67  	defer func() { p.Level-- }()
    68  	return stmtParser(p, argParser)
    69  }
    70  
    71  // type StatementParser func(parser *Parser, args *Parser) (nodes.Stmt, error)
    72  
    73  func (p *Parser) ParseStatementBlock() (*nodes.StatementBlock, error) {
    74  	log.WithFields(log.Fields{
    75  		"current": p.Current(),
    76  	}).Trace("ParseStatementBlock")
    77  
    78  	begin := p.Match(tokens.BlockBegin)
    79  	if begin == nil {
    80  		return nil, errors.Errorf(`Expected "%s" got "%s"`, p.Config.BlockStartString, p.Current())
    81  	}
    82  
    83  	name := p.Match(tokens.Name)
    84  	if name == nil {
    85  		return nil, p.Error("Expected a statement name here", p.Current())
    86  	}
    87  
    88  	// Check for the existing statement
    89  	stmtParser, exists := p.Statements[name.Val]
    90  	if !exists {
    91  		// Does not exists
    92  		return nil, p.Error(fmt.Sprintf("Statement '%s' not found (or beginning not provided)", name.Val), name)
    93  	}
    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  	log.Trace("args")
   101  	var args []*tokens.Token
   102  	for p.Peek(tokens.BlockEnd) == nil && !p.Stream.End() {
   103  		log.Trace("for args")
   104  		// Add token to args
   105  		args = append(args, p.Next())
   106  		// p.Consume() // next token
   107  	}
   108  	log.Trace("loop ended")
   109  
   110  	// EOF?
   111  	// if p.Remaining() == 0 {
   112  	// 	return nil, p.Error("Unexpectedly reached EOF, no statement end found.", p.lastToken)
   113  	// }
   114  
   115  	end := p.Match(tokens.BlockEnd)
   116  	if end == nil {
   117  		return nil, p.Error(fmt.Sprintf(`Expected end of block "%s"`, p.Config.BlockEndString), p.Current())
   118  	}
   119  	log.WithFields(log.Fields{
   120  		"args": args,
   121  	}).Trace("Matched end block")
   122  
   123  	stream := tokens.NewStream(args)
   124  	log.WithFields(log.Fields{
   125  		"stream": stream,
   126  	}).Trace("Got stream")
   127  	argParser := NewParser(fmt.Sprintf("%s:args", name.Val), p.Config, stream)
   128  	log.Trace("argparser")
   129  	// argParser := newParser(p.name, argsToken, p.template)
   130  	// if len(argsToken) == 0 {
   131  	// 	// This is done to have nice EOF error messages
   132  	// 	argParser.lastToken = tokenName
   133  	// }
   134  
   135  	// p.template.level++
   136  	// defer func() { p.template.level-- }()
   137  	stmt, err := stmtParser(p, argParser)
   138  	if err != nil {
   139  		return nil, errors.Wrapf(err, `Unable to parse statement "%s"`, name.Val)
   140  	}
   141  	log.Trace("got stmt and return")
   142  	return &nodes.StatementBlock{
   143  		Location: begin,
   144  		Name:     name.Val,
   145  		Stmt:     stmt,
   146  		LStrip:   begin.Val[len(begin.Val)-1] == '+',
   147  		Trim: &nodes.Trim{
   148  			Left:  begin.Val[len(begin.Val)-1] == '-',
   149  			Right: end.Val[0] == '-',
   150  		},
   151  	}, nil
   152  }
   153  

View as plain text