github.com/khulnasoft-lab/defsec@v1.0.5-0.20230827010352-5e9f46893d95/pkg/scanners/azure/arm/parser/armjson/parse.go (about) 1 package armjson 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/khulnasoft-lab/defsec/pkg/types" 8 ) 9 10 type parser struct { 11 position Position 12 size int 13 peeker *PeekReader 14 } 15 16 func newParser(p *PeekReader, pos Position) *parser { 17 return &parser{ 18 position: pos, 19 peeker: p, 20 } 21 } 22 23 func (p *parser) parse(rootMetadata *types.Metadata) (Node, error) { 24 root, err := p.parseElement(rootMetadata) 25 if err != nil { 26 return nil, err 27 } 28 root.(*node).updateMetadata("") 29 return root, nil 30 } 31 32 func (p *parser) parseElement(parentMetadata *types.Metadata) (Node, error) { 33 if err := p.parseWhitespace(); err != nil { 34 return nil, err 35 } 36 n, err := p.parseValue(parentMetadata) 37 if err != nil { 38 return nil, err 39 } 40 if err := p.parseWhitespace(); err != nil { 41 return nil, err 42 } 43 return n, nil 44 } 45 46 func (p *parser) parseValue(parentMetadata *types.Metadata) (Node, error) { 47 c, err := p.peeker.Peek() 48 if err != nil { 49 return nil, err 50 } 51 52 switch c { 53 case '/': 54 return p.parseComment(parentMetadata) 55 case '"': 56 return p.parseString(parentMetadata) 57 case '{': 58 return p.parseObject(parentMetadata) 59 case '[': 60 return p.parseArray(parentMetadata) 61 case 'n': 62 return p.parseNull(parentMetadata) 63 case 't', 'f': 64 return p.parseBoolean(parentMetadata) 65 default: 66 if c == '-' || (c >= '0' && c <= '9') { 67 return p.parseNumber(parentMetadata) 68 } 69 return nil, fmt.Errorf("unexpected character '%c'", c) 70 } 71 } 72 73 func (p *parser) next() (rune, error) { 74 b, err := p.peeker.Next() 75 if err != nil { 76 return 0, err 77 } 78 p.position.Column++ 79 p.size++ 80 return b, nil 81 } 82 83 func (p *parser) undo() error { 84 if err := p.peeker.Undo(); err != nil { 85 return err 86 } 87 p.position.Column-- 88 p.size-- 89 return nil 90 } 91 92 func (p *parser) makeError(format string, args ...interface{}) error { 93 return fmt.Errorf( 94 "error at line %d, column %d: %s", 95 p.position.Line, 96 p.position.Column, 97 fmt.Sprintf(format, args...), 98 ) 99 } 100 101 func (p *parser) newNode(k Kind, parentMetadata *types.Metadata) (*node, *types.Metadata) { 102 n := &node{ 103 start: p.position, 104 kind: k, 105 } 106 metadata := types.NewMetadata( 107 types.NewRange(parentMetadata.Range().GetFilename(), n.start.Line, n.end.Line, "", parentMetadata.Range().GetFS()), 108 n.ref, 109 ) 110 metadata.SetParentPtr(parentMetadata) 111 n.metadata = &metadata 112 return n, n.metadata 113 } 114 115 func (n *node) updateMetadata(prefix string) { 116 117 var full string 118 // nolint:gocritic 119 if strings.HasPrefix(n.ref, "[") { 120 full = prefix + n.ref 121 } else if prefix != "" { 122 full = prefix + "." + n.ref 123 } else { 124 full = n.ref 125 } 126 127 n.metadata.SetRange(types.NewRange(n.metadata.Range().GetFilename(), 128 n.start.Line, 129 n.end.Line, 130 "", 131 n.metadata.Range().GetFS())) 132 133 n.metadata.SetReference(full) 134 135 for i := range n.content { 136 n.content[i].(*node).updateMetadata(full) 137 } 138 } 139 140 func (p *parser) swallowIfEqual(r rune) bool { 141 c, err := p.peeker.Peek() 142 if err != nil { 143 return false 144 } 145 if c != r { 146 return false 147 } 148 _, _ = p.next() 149 return true 150 }