| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | package scanner | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	"sync" | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/goccy/go-yaml/token" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-21 12:53:30 +09:00
										 |  |  | // Context context at scanning | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | type Context struct { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	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() | 
					
						
							|  |  |  | 		}, | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | ) | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | func createContext() *Context { | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	return &Context{ | 
					
						
							| 
									
										
										
										
											2019-12-04 23:58:06 +09:00
										 |  |  | 		idx:          0, | 
					
						
							|  |  |  | 		tokens:       token.Tokens{}, | 
					
						
							|  |  |  | 		isSingleLine: true, | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 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() | 
					
						
							| 
									
										
										
										
											2022-11-14 19:19:25 +09:00
										 |  |  | 	c.isRawFolded = false | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	c.isSingleLine = true | 
					
						
							| 
									
										
										
										
											2022-11-14 19:19:25 +09:00
										 |  |  | 	c.isLiteral = false | 
					
						
							|  |  |  | 	c.isFolded = false | 
					
						
							|  |  |  | 	c.literalOpt = "" | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | func (c *Context) resetBuffer() { | 
					
						
							|  |  |  | 	c.buf = c.buf[:0] | 
					
						
							|  |  |  | 	c.obuf = c.obuf[:0] | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	c.notSpaceCharPos = 0 | 
					
						
							|  |  |  | 	c.notSpaceOrgCharPos = 0 | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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) { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	if len(c.buf) == 0 && r == ' ' { | 
					
						
							|  |  |  | 		return | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	c.buf = append(c.buf, r) | 
					
						
							| 
									
										
										
										
											2020-06-17 11:38:36 +09:00
										 |  |  | 	if r != ' ' && r != '\t' { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 		c.notSpaceCharPos = len(c.buf) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) addOriginBuf(r rune) { | 
					
						
							|  |  |  | 	c.obuf = append(c.obuf, r) | 
					
						
							| 
									
										
										
										
											2020-06-17 11:38:36 +09:00
										 |  |  | 	if r != ' ' && r != '\t' { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 		c.notSpaceOrgCharPos = len(c.obuf) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-11 17:17:05 +09:00
										 |  |  | func (c *Context) removeRightSpaceFromBuf() int { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	trimmedBuf := c.obuf[:c.notSpaceOrgCharPos] | 
					
						
							|  |  |  | 	buflen := len(trimmedBuf) | 
					
						
							| 
									
										
										
										
											2019-12-11 17:17:05 +09:00
										 |  |  | 	diff := len(c.obuf) - buflen | 
					
						
							|  |  |  | 	if diff > 0 { | 
					
						
							|  |  |  | 		c.obuf = c.obuf[:buflen] | 
					
						
							| 
									
										
										
										
											2019-12-28 22:37:50 +09:00
										 |  |  | 		c.buf = c.bufferedSrc() | 
					
						
							| 
									
										
										
										
											2019-12-11 17:17:05 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return diff | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-11-07 23:45:39 +09:00
										 |  |  | func (c *Context) isDocument() bool { | 
					
						
							|  |  |  | 	return c.isLiteral || c.isFolded || c.isRawFolded | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | func (c *Context) isEOS() bool { | 
					
						
							|  |  |  | 	return len(c.src)-1 <= c.idx | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-30 16:57:59 +09:00
										 |  |  | func (c *Context) isNextEOS() bool { | 
					
						
							|  |  |  | 	return len(c.src)-1 <= c.idx+1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | func (c *Context) next() bool { | 
					
						
							|  |  |  | 	return c.idx < c.size | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) source(s, e int) string { | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 	return string(c.src[s:e]) | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) previousChar() rune { | 
					
						
							|  |  |  | 	if c.idx > 0 { | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 		return c.src[c.idx-1] | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return rune(0) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) currentChar() rune { | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 	return c.src[c.idx] | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-10-21 12:53:30 +09:00
										 |  |  | func (c *Context) nextChar() rune { | 
					
						
							|  |  |  | 	if c.size > c.idx+1 { | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 		return c.src[c.idx+1] | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return rune(0) | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) repeatNum(r rune) int { | 
					
						
							|  |  |  | 	cnt := 0 | 
					
						
							|  |  |  | 	for i := c.idx; i < c.size; i++ { | 
					
						
							| 
									
										
										
										
											2019-11-07 17:18:17 +09:00
										 |  |  | 		if c.src[i] == r { | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 			cnt++ | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			break | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return cnt | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) progress(num int) { | 
					
						
							|  |  |  | 	c.idx += num | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) nextPos() int { | 
					
						
							|  |  |  | 	return c.idx + 1 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2019-12-28 22:37:50 +09:00
										 |  |  | func (c *Context) existsBuffer() bool { | 
					
						
							|  |  |  | 	return len(c.bufferedSrc()) != 0 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) bufferedSrc() []rune { | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	src := c.buf[:c.notSpaceCharPos] | 
					
						
							| 
									
										
										
										
											2019-11-08 16:48:54 +09:00
										 |  |  | 	if len(src) > 0 && src[len(src)-1] == '\n' && c.isDocument() && c.literalOpt == "-" { | 
					
						
							|  |  |  | 		// remove end '\n' character | 
					
						
							|  |  |  | 		src = src[:len(src)-1] | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-28 22:37:50 +09:00
										 |  |  | 	return src | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (c *Context) bufferedToken(pos *token.Position) *token.Token { | 
					
						
							|  |  |  | 	if c.idx == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	source := c.bufferedSrc() | 
					
						
							|  |  |  | 	if len(source) == 0 { | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2020-06-01 12:54:23 +09:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2019-12-28 22:20:45 +09:00
										 |  |  | 	c.resetBuffer() | 
					
						
							| 
									
										
										
										
											2019-10-16 18:19:48 +09:00
										 |  |  | 	return tk | 
					
						
							|  |  |  | } |