You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
202 lines
3.5 KiB
202 lines
3.5 KiB
3 years ago
|
package scanner
|
||
|
|
||
|
import (
|
||
|
"sync"
|
||
|
|
||
|
"github.com/goccy/go-yaml/token"
|
||
|
)
|
||
|
|
||
|
// Context context at scanning
|
||
|
type Context struct {
|
||
|
idx int
|
||
|
size int
|
||
|
notSpaceCharPos int
|
||
|
notSpaceOrgCharPos int
|
||
|
src []rune
|
||
|
buf []rune
|
||
|
obuf []rune
|
||
|
tokens token.Tokens
|
||
|
isRawFolded bool
|
||
|
isLiteral bool
|
||
|
isFolded bool
|
||
|
isSingleLine bool
|
||
|
literalOpt string
|
||
|
}
|
||
|
|
||
|
var (
|
||
|
ctxPool = sync.Pool{
|
||
|
New: func() interface{} {
|
||
|
return createContext()
|
||
|
},
|
||
|
}
|
||
|
)
|
||
|
|
||
|
func createContext() *Context {
|
||
|
return &Context{
|
||
|
idx: 0,
|
||
|
tokens: token.Tokens{},
|
||
|
isSingleLine: true,
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func newContext(src []rune) *Context {
|
||
|
ctx := ctxPool.Get().(*Context)
|
||
|
ctx.reset(src)
|
||
|
return ctx
|
||
|
}
|
||
|
|
||
|
func (c *Context) release() {
|
||
|
ctxPool.Put(c)
|
||
|
}
|
||
|
|
||
|
func (c *Context) reset(src []rune) {
|
||
|
c.idx = 0
|
||
|
c.size = len(src)
|
||
|
c.src = src
|
||
|
c.tokens = c.tokens[:0]
|
||
|
c.resetBuffer()
|
||
|
c.isSingleLine = true
|
||
|
}
|
||
|
|
||
|
func (c *Context) resetBuffer() {
|
||
|
c.buf = c.buf[:0]
|
||
|
c.obuf = c.obuf[:0]
|
||
|
c.notSpaceCharPos = 0
|
||
|
c.notSpaceOrgCharPos = 0
|
||
|
}
|
||
|
|
||
|
func (c *Context) isSaveIndentMode() bool {
|
||
|
return c.isLiteral || c.isFolded || c.isRawFolded
|
||
|
}
|
||
|
|
||
|
func (c *Context) breakLiteral() {
|
||
|
c.isLiteral = false
|
||
|
c.isRawFolded = false
|
||
|
c.isFolded = false
|
||
|
c.literalOpt = ""
|
||
|
}
|
||
|
|
||
|
func (c *Context) addToken(tk *token.Token) {
|
||
|
if tk == nil {
|
||
|
return
|
||
|
}
|
||
|
c.tokens = append(c.tokens, tk)
|
||
|
}
|
||
|
|
||
|
func (c *Context) addBuf(r rune) {
|
||
|
if len(c.buf) == 0 && r == ' ' {
|
||
|
return
|
||
|
}
|
||
|
c.buf = append(c.buf, r)
|
||
|
if r != ' ' && r != '\t' {
|
||
|
c.notSpaceCharPos = len(c.buf)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *Context) addOriginBuf(r rune) {
|
||
|
c.obuf = append(c.obuf, r)
|
||
|
if r != ' ' && r != '\t' {
|
||
|
c.notSpaceOrgCharPos = len(c.obuf)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
func (c *Context) removeRightSpaceFromBuf() int {
|
||
|
trimmedBuf := c.obuf[:c.notSpaceOrgCharPos]
|
||
|
buflen := len(trimmedBuf)
|
||
|
diff := len(c.obuf) - buflen
|
||
|
if diff > 0 {
|
||
|
c.obuf = c.obuf[:buflen]
|
||
|
c.buf = c.bufferedSrc()
|
||
|
}
|
||
|
return diff
|
||
|
}
|
||
|
|
||
|
func (c *Context) isDocument() bool {
|
||
|
return c.isLiteral || c.isFolded || c.isRawFolded
|
||
|
}
|
||
|
|
||
|
func (c *Context) isEOS() bool {
|
||
|
return len(c.src)-1 <= c.idx
|
||
|
}
|
||
|
|
||
|
func (c *Context) isNextEOS() bool {
|
||
|
return len(c.src)-1 <= c.idx+1
|
||
|
}
|
||
|
|
||
|
func (c *Context) next() bool {
|
||
|
return c.idx < c.size
|
||
|
}
|
||
|
|
||
|
func (c *Context) source(s, e int) string {
|
||
|
return string(c.src[s:e])
|
||
|
}
|
||
|
|
||
|
func (c *Context) previousChar() rune {
|
||
|
if c.idx > 0 {
|
||
|
return c.src[c.idx-1]
|
||
|
}
|
||
|
return rune(0)
|
||
|
}
|
||
|
|
||
|
func (c *Context) currentChar() rune {
|
||
|
return c.src[c.idx]
|
||
|
}
|
||
|
|
||
|
func (c *Context) nextChar() rune {
|
||
|
if c.size > c.idx+1 {
|
||
|
return c.src[c.idx+1]
|
||
|
}
|
||
|
return rune(0)
|
||
|
}
|
||
|
|
||
|
func (c *Context) repeatNum(r rune) int {
|
||
|
cnt := 0
|
||
|
for i := c.idx; i < c.size; i++ {
|
||
|
if c.src[i] == r {
|
||
|
cnt++
|
||
|
} else {
|
||
|
break
|
||
|
}
|
||
|
}
|
||
|
return cnt
|
||
|
}
|
||
|
|
||
|
func (c *Context) progress(num int) {
|
||
|
c.idx += num
|
||
|
}
|
||
|
|
||
|
func (c *Context) nextPos() int {
|
||
|
return c.idx + 1
|
||
|
}
|
||
|
|
||
|
func (c *Context) existsBuffer() bool {
|
||
|
return len(c.bufferedSrc()) != 0
|
||
|
}
|
||
|
|
||
|
func (c *Context) bufferedSrc() []rune {
|
||
|
src := c.buf[:c.notSpaceCharPos]
|
||
|
if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" {
|
||
|
// remove end '\n' character
|
||
|
src = src[:len(src)-1]
|
||
|
}
|
||
|
return src
|
||
|
}
|
||
|
|
||
|
func (c *Context) bufferedToken(pos *token.Position) *token.Token {
|
||
|
if c.idx == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
source := c.bufferedSrc()
|
||
|
if len(source) == 0 {
|
||
|
return nil
|
||
|
}
|
||
|
var tk *token.Token
|
||
|
if c.isDocument() {
|
||
|
tk = token.String(string(source), string(c.obuf), pos)
|
||
|
} else {
|
||
|
tk = token.New(string(source), string(c.obuf), pos)
|
||
|
}
|
||
|
c.resetBuffer()
|
||
|
return tk
|
||
|
}
|