Skip to content

Commit

Permalink
Refactor parser (#545)
Browse files Browse the repository at this point in the history
* refactor parser
  • Loading branch information
goccy authored Nov 26, 2024
1 parent ff5d41f commit deb129a
Show file tree
Hide file tree
Showing 10 changed files with 1,687 additions and 859 deletions.
8 changes: 8 additions & 0 deletions ast/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -1762,6 +1762,14 @@ type TagNode struct {
Value Node
}

func (n *TagNode) GetValue() any {
scalar, ok := n.Value.(ScalarNode)
if !ok {
return nil
}
return scalar.GetValue()
}

func (n *TagNode) stringWithoutComment() string {
return n.Value.String()
}
Expand Down
20 changes: 17 additions & 3 deletions decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,14 @@ func (d *Decoder) addHeadOrLineCommentToMap(node ast.Node) {
}
commentPath := node.GetPath()
if minCommentLine < targetLine {
switch n := node.(type) {
case *ast.MappingNode:
if len(n.Values) != 0 {
commentPath = n.Values[0].Key.GetPath()
}
case *ast.MappingValueNode:
commentPath = n.Key.GetPath()
}
d.addCommentToMap(commentPath, HeadComment(texts...))
} else {
d.addCommentToMap(commentPath, LineComment(texts[0]))
Expand Down Expand Up @@ -255,14 +263,20 @@ func (d *Decoder) addFootCommentToMap(node ast.Node) {
)
switch n := node.(type) {
case *ast.SequenceNode:
if len(n.Values) != 0 {
footCommentPath = n.Values[len(n.Values)-1].GetPath()
}
footComment = n.FootComment
if n.FootComment != nil {
footCommentPath = n.FootComment.GetPath()
}
case *ast.MappingNode:
footComment = n.FootComment
if n.FootComment != nil {
footCommentPath = n.FootComment.GetPath()
}
case *ast.MappingValueNode:
footComment = n.FootComment
if n.FootComment != nil {
footCommentPath = n.FootComment.GetPath()
}
}
if footComment == nil {
return
Expand Down
28 changes: 28 additions & 0 deletions parser/color.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package parser

import "fmt"

const (
colorFgHiBlack int = iota + 90
colorFgHiRed
colorFgHiGreen
colorFgHiYellow
colorFgHiBlue
colorFgHiMagenta
colorFgHiCyan
)

var colorTable = []int{
colorFgHiRed,
colorFgHiGreen,
colorFgHiYellow,
colorFgHiBlue,
colorFgHiMagenta,
colorFgHiCyan,
}

func colorize(idx int, content string) string {
colorIdx := idx % len(colorTable)
color := colorTable[colorIdx]
return fmt.Sprintf("\x1b[1;%dm", color) + content + "\x1b[22;0m"
}
106 changes: 99 additions & 7 deletions parser/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,21 @@ package parser
import (
"fmt"
"strings"

"github.com/goccy/go-yaml/token"
)

// context context at parsing
type context struct {
tokenRef *tokenRef
path string
isFlow bool
isMapKey bool
}

type tokenRef struct {
tokens []*Token
size int
idx int
}

var pathSpecialChars = []string{
Expand All @@ -32,6 +40,44 @@ func normalizePath(path string) string {
return path
}

func (c *context) currentToken() *Token {
if c.tokenRef.idx >= c.tokenRef.size {
return nil
}
return c.tokenRef.tokens[c.tokenRef.idx]
}

func (c *context) isComment() bool {
return c.currentToken().Type() == token.CommentType
}

func (c *context) nextToken() *Token {
if c.tokenRef.idx+1 >= c.tokenRef.size {
return nil
}
return c.tokenRef.tokens[c.tokenRef.idx+1]
}

func (c *context) nextNotCommentToken() *Token {
for i := c.tokenRef.idx + 1; i < c.tokenRef.size; i++ {
tk := c.tokenRef.tokens[i]
if tk.Type() == token.CommentType {
continue
}
return tk
}
return nil
}

func (c *context) withGroup(g *TokenGroup) *context {
ctx := *c
ctx.tokenRef = &tokenRef{
tokens: g.Tokens,
size: len(g.Tokens),
}
return &ctx
}

func (c *context) withChild(path string) *context {
ctx := *c
ctx.path = c.path + "." + normalizePath(path)
Expand All @@ -50,14 +96,60 @@ func (c *context) withFlow(isFlow bool) *context {
return &ctx
}

func (c *context) withMapKey() *context {
ctx := *c
ctx.isMapKey = true
return &ctx
}

func newContext() *context {
return &context{
path: "$",
}
}

func (c *context) goNext() {
ref := c.tokenRef
if ref.size <= ref.idx+1 {
ref.idx = ref.size
} else {
ref.idx++
}
}

func (c *context) next() bool {
return c.tokenRef.idx < c.tokenRef.size
}

func (c *context) insertNullToken(tk *Token) *Token {
nullToken := c.createNullToken(tk)
c.insertToken(nullToken)
c.goNext()

return nullToken
}

func (c *context) createNullToken(base *Token) *Token {
pos := *(base.RawToken().Position)
pos.Column++
return &Token{Token: token.New("null", "null", &pos)}
}

func (c *context) insertToken(tk *Token) {
ref := c.tokenRef
idx := ref.idx
if ref.size < idx {
return
}
if ref.size == idx {
curToken := ref.tokens[ref.size-1]
tk.RawToken().Next = curToken.RawToken()
curToken.RawToken().Prev = tk.RawToken()

ref.tokens = append(ref.tokens, tk)
ref.size = len(ref.tokens)
return
}

curToken := ref.tokens[idx]
tk.RawToken().Next = curToken.RawToken()
curToken.RawToken().Prev = tk.RawToken()

ref.tokens = append(ref.tokens[:idx+1], ref.tokens[idx:]...)
ref.tokens[idx] = tk
ref.size = len(ref.tokens)
}
Loading

0 comments on commit deb129a

Please sign in to comment.