123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146 |
- // Copyright 2011 The Go Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE file.
- package jade
- import (
- "fmt"
- "runtime"
- )
- // Tree is the representation of a single parsed template.
- type Tree struct {
- Name string // name of the template represented by the tree.
- Root *ListNode // top-level root of the tree.
- text string // text parsed to create the template (or its parent)
- // Parsing only; cleared after parse.
- lex *lexer
- token [3]item // three-token lookahead for parser.
- peekCount int
- tab int // depth of focus
- mixin map[string]*MixinNode
- block map[string]*ListNode
- }
- // Copy returns a copy of the Tree. Any parsing state is discarded.
- func (t *Tree) Copy() *Tree {
- if t == nil {
- return nil
- }
- return &Tree{
- Name: t.Name,
- Root: t.Root.CopyList(),
- text: t.text,
- }
- }
- // next returns the next token.
- func (t *Tree) next() item {
- if t.peekCount > 0 {
- t.peekCount--
- } else {
- t.token[0] = t.lex.nextItem()
- }
- return t.token[t.peekCount]
- }
- // backup backs the input stream up one token.
- func (t *Tree) backup() {
- t.peekCount++
- }
- // backup2 backs the input stream up two tokens.
- // The zeroth token is already there.
- func (t *Tree) backup2(t1 item) {
- t.token[1] = t1
- t.peekCount = 2
- }
- // backup3 backs the input stream up three tokens
- // The zeroth token is already there.
- func (t *Tree) backup3(t2, t1 item) { // Reverse order: we're pushing back.
- t.token[1] = t1
- t.token[2] = t2
- t.peekCount = 3
- }
- // peek returns but does not consume the next token.
- func (t *Tree) peek() item {
- if t.peekCount > 0 {
- return t.token[t.peekCount-1]
- }
- t.peekCount = 1
- t.token[0] = t.lex.nextItem()
- return t.token[0]
- }
- // nextNonSpace returns the next non-space token.
- func (t *Tree) nextNonSpace() (token item) {
- for {
- token = t.next()
- if token.typ != itemIdent && token.typ != itemEndL && token.typ != itemEmptyLine {
- break
- }
- }
- // fmt.Println("\t\tnextNonSpace", token.val)
- return token
- }
- // peekNonSpace returns but does not consume the next non-space token.
- func (t *Tree) peekNonSpace() (token item) {
- for {
- token = t.next()
- if token.typ != itemIdent && token.typ != itemEndL && token.typ != itemEmptyLine {
- break
- }
- }
- t.backup()
- return token
- }
- // errorf formats the error and terminates processing.
- func (t *Tree) errorf(format string, args ...interface{}) {
- t.Root = nil
- format = fmt.Sprintf("template:%d: %s", t.token[0].line, format)
- panic(fmt.Errorf(format, args...))
- }
- //
- //
- //
- // recover is the handler that turns panics into returns from the top level of Parse.
- func (t *Tree) recover(errp *error) {
- e := recover()
- if e != nil {
- if _, ok := e.(runtime.Error); ok {
- panic(e)
- }
- if t != nil {
- t.lex.drain()
- t.lex = nil
- }
- *errp = e.(error)
- }
- }
- func (t *Tree) Parse(text string) (tree *Tree, err error) {
- defer t.recover(&err)
- t.lex = lex(t.Name, text)
- t.text = text
- t.topParse()
- t.lex = nil
- return t, nil
- }
- // New allocates a new parse tree with the given name.
- func New(name string) *Tree {
- return &Tree{
- Name: name,
- mixin: map[string]*MixinNode{},
- block: map[string]*ListNode{},
- }
- }
|