Skip to content

Commit

Permalink
performance: store path in stack to avoid copying context
Browse files Browse the repository at this point in the history
  • Loading branch information
yoelsusanto committed Mar 24, 2024
1 parent 4653a1b commit 2018c1a
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 29 deletions.
54 changes: 31 additions & 23 deletions parser/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@ import (

// context context at parsing
type context struct {
parent *context
idx int
size int
tokens token.Tokens
path string
parent *context
idx int
size int
tokens token.Tokens
path string
pathStack []string
}

var pathSpecialChars = []string{
Expand All @@ -37,26 +38,32 @@ func normalizePath(path string) string {
}

func (c *context) withChild(path string) *context {
ctx := c.copy()
// store current path in the stack for later retrieval
c.pathStack = append(c.pathStack, c.path)
c.path = c.createPathForChild(path)
return c
}

func (c *context) createPathForChild(path string) string {
path = normalizePath(path)
ctx.path += fmt.Sprintf(".%s", path)
return ctx
return fmt.Sprintf("%s.%s", c.path, path)
}

func (c *context) withIndex(idx uint) *context {
ctx := c.copy()
ctx.path += fmt.Sprintf("[%d]", idx)
return ctx
// store current path in the stack for later retrieval
c.pathStack = append(c.pathStack, c.path)
c.path = c.createPathForIndex(idx)
return c
}

func (c *context) copy() *context {
return &context{
parent: c,
idx: c.idx,
size: c.size,
tokens: append(token.Tokens{}, c.tokens...),
path: c.path,
}
func (c *context) createPathForIndex(idx uint) string {
return fmt.Sprintf("%s[%d]", c.path, idx)
}

func (c *context) popPath() {
// restore previous path from top element in stack and remove it from stack
c.path = c.pathStack[len(c.pathStack)-1]
c.pathStack = c.pathStack[:len(c.pathStack)-1]
}

func (c *context) next() bool {
Expand Down Expand Up @@ -184,9 +191,10 @@ func newContext(tokens token.Tokens, mode Mode) *context {
}
}
return &context{
idx: 0,
size: len(filteredTokens),
tokens: token.Tokens(filteredTokens),
path: "$",
idx: 0,
size: len(filteredTokens),
tokens: token.Tokens(filteredTokens),
path: "$",
pathStack: []string{},
}
}
18 changes: 12 additions & 6 deletions parser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ func (p *parser) parseSequence(ctx *context) (*ast.SequenceNode, error) {
}

value, err := p.parseToken(ctx.withIndex(uint(len(node.Values))), tk)
ctx.popPath()
if err != nil {
return nil, errors.Wrapf(err, "failed to parse sequence value in flow sequence node")
}
Expand Down Expand Up @@ -160,7 +161,7 @@ func (p *parser) createMapValueNode(ctx *context, key ast.MapKeyNode, colonToken
if tk.Type == token.CommentType {
comment = p.parseCommentOnly(ctx)
if comment != nil {
comment.SetPath(ctx.withChild(key.GetToken().Value).path)
comment.SetPath(ctx.createPathForChild(key.GetToken().Value))
}
tk = ctx.currentToken()
}
Expand Down Expand Up @@ -236,7 +237,7 @@ func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) {
return nil, errors.Wrapf(err, "failed to parse map key")
}
keyText := key.GetToken().Value
key.SetPath(ctx.withChild(keyText).path)
key.SetPath(ctx.createPathForChild(keyText))
if err := p.validateMapKey(key.GetToken()); err != nil {
return nil, errors.Wrapf(err, "validate mapping key error")
}
Expand All @@ -246,7 +247,9 @@ func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) {
return nil, errors.ErrSyntax("unexpected map", key.GetToken())
}
ctx.progress(1) // progress to value token
if err := p.setSameLineCommentIfExists(ctx.withChild(keyText), key); err != nil {
err = p.setSameLineCommentIfExists(ctx.withChild(keyText), key)
ctx.popPath()
if err != nil {
return nil, errors.Wrapf(err, "failed to set same line comment to node")
}
if key.GetComment() != nil {
Expand All @@ -256,6 +259,7 @@ func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) {
}

value, err := p.parseMapValue(ctx.withChild(keyText), key, tk)
ctx.popPath()
if err != nil {
return nil, errors.Wrapf(err, "failed to parse map value")
}
Expand All @@ -264,9 +268,9 @@ func (p *parser) parseMappingValue(ctx *context) (ast.Node, error) {
}

mvnode := ast.MappingValue(tk, key, value)
mvnode.SetPath(ctx.withChild(keyText).path)
mvnode.SetPath(ctx.createPathForChild(keyText))
node := ast.Mapping(tk, false, mvnode)
node.SetPath(ctx.withChild(keyText).path)
node.SetPath(ctx.createPathForChild(keyText))

ntk := ctx.nextNotCommentToken()
antk := ctx.afterNextNotCommentToken()
Expand Down Expand Up @@ -339,11 +343,12 @@ func (p *parser) parseSequenceEntry(ctx *context) (*ast.SequenceNode, error) {
}
}
value, err := p.parseToken(ctx.withIndex(uint(len(sequenceNode.Values))), ctx.currentToken())
ctx.popPath()
if err != nil {
return nil, errors.Wrapf(err, "failed to parse sequence")
}
if comment != nil {
comment.SetPath(ctx.withIndex(uint(len(sequenceNode.Values))).path)
comment.SetPath(ctx.createPathForIndex(uint(len(sequenceNode.Values))))
sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, comment)
} else {
sequenceNode.ValueHeadComments = append(sequenceNode.ValueHeadComments, nil)
Expand Down Expand Up @@ -621,6 +626,7 @@ func (p *parser) parseMappingKey(ctx *context) (*ast.MappingKeyNode, error) {
node.SetPath(ctx.path)
ctx.progress(1) // skip mapping key token
value, err := p.parseToken(ctx.withChild(keyTk.Value), ctx.currentToken())
ctx.popPath()
if err != nil {
return nil, errors.Wrapf(err, "failed to parse map key")
}
Expand Down

0 comments on commit 2018c1a

Please sign in to comment.