mirror of
https://github.com/gohugoio/hugo.git
synced 2024-05-11 05:54:58 +00:00
88 lines
2.3 KiB
Go
88 lines
2.3 KiB
Go
// Copyright 2018 The Hugo Authors. All rights reserved.
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
// Package pageparser provides a parser for Hugo content files (Markdown, HTML etc.) in Hugo.
|
|
// This implementation is highly inspired by the great talk given by Rob Pike called "Lexical Scanning in Go"
|
|
// It's on YouTube, Google it!.
|
|
// See slides here: http://cuddle.googlecode.com/hg/talk/lex.html
|
|
package pageparser
|
|
|
|
// The lexical scanning below
|
|
|
|
type Tokens struct {
|
|
lexer *pageLexer
|
|
token [3]Item // 3-item look-ahead is what we currently need
|
|
peekCount int
|
|
}
|
|
|
|
func (t *Tokens) Next() Item {
|
|
if t.peekCount > 0 {
|
|
t.peekCount--
|
|
} else {
|
|
t.token[0] = t.lexer.nextItem()
|
|
}
|
|
return t.token[t.peekCount]
|
|
}
|
|
|
|
// backs up one token.
|
|
func (t *Tokens) Backup() {
|
|
t.peekCount++
|
|
}
|
|
|
|
// backs up two tokens.
|
|
func (t *Tokens) Backup2(t1 Item) {
|
|
t.token[1] = t1
|
|
t.peekCount = 2
|
|
}
|
|
|
|
// backs up three tokens.
|
|
func (t *Tokens) Backup3(t2, t1 Item) {
|
|
t.token[1] = t1
|
|
t.token[2] = t2
|
|
t.peekCount = 3
|
|
}
|
|
|
|
// check for non-error and non-EOF types coming next
|
|
func (t *Tokens) IsValueNext() bool {
|
|
i := t.Peek()
|
|
return i.typ != tError && i.typ != tEOF
|
|
}
|
|
|
|
// look at, but do not consume, the next item
|
|
// repeated, sequential calls will return the same item
|
|
func (t *Tokens) Peek() Item {
|
|
if t.peekCount > 0 {
|
|
return t.token[t.peekCount-1]
|
|
}
|
|
t.peekCount = 1
|
|
t.token[0] = t.lexer.nextItem()
|
|
return t.token[0]
|
|
}
|
|
|
|
// Consume is a convencience method to consume the next n tokens,
|
|
// but back off Errors and EOF.
|
|
func (t *Tokens) Consume(cnt int) {
|
|
for i := 0; i < cnt; i++ {
|
|
token := t.Next()
|
|
if token.typ == tError || token.typ == tEOF {
|
|
t.Backup()
|
|
break
|
|
}
|
|
}
|
|
}
|
|
|
|
// LineNumber returns the current line number. Used for logging.
|
|
func (t *Tokens) LineNumber() int {
|
|
return t.lexer.lineNum()
|
|
}
|