diff options
Diffstat (limited to 'parser/pageparser/pageparser.go')
-rw-r--r-- | parser/pageparser/pageparser.go | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/parser/pageparser/pageparser.go b/parser/pageparser/pageparser.go new file mode 100644 index 000000000..5534ee64b --- /dev/null +++ b/parser/pageparser/pageparser.go @@ -0,0 +1,87 @@ +// 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() +} |