(p *peeker)
| 102 | } |
| 103 | |
| 104 | func parseObject(p *peeker) (node, hcl.Diagnostics) { |
| 105 | var diags hcl.Diagnostics |
| 106 | |
| 107 | open := p.Read() |
| 108 | attrs := []*objectAttr{} |
| 109 | |
| 110 | // recover is used to shift the peeker to what seems to be the end of |
| 111 | // our object, so that when we encounter an error we leave the peeker |
| 112 | // at a reasonable point in the token stream to continue parsing. |
| 113 | recover := func(tok token) { |
| 114 | open := 1 |
| 115 | for { |
| 116 | switch tok.Type { |
| 117 | case tokenBraceO: |
| 118 | open++ |
| 119 | case tokenBraceC: |
| 120 | open-- |
| 121 | if open <= 1 { |
| 122 | return |
| 123 | } |
| 124 | case tokenEOF: |
| 125 | // Ran out of source before we were able to recover, |
| 126 | // so we'll bail here and let the caller deal with it. |
| 127 | return |
| 128 | } |
| 129 | tok = p.Read() |
| 130 | } |
| 131 | } |
| 132 | |
| 133 | Token: |
| 134 | for { |
| 135 | if p.Peek().Type == tokenBraceC { |
| 136 | break Token |
| 137 | } |
| 138 | |
| 139 | keyNode, keyDiags := parseValue(p) |
| 140 | diags = diags.Extend(keyDiags) |
| 141 | if keyNode == nil { |
| 142 | return nil, diags |
| 143 | } |
| 144 | |
| 145 | keyStrNode, ok := keyNode.(*stringVal) |
| 146 | if !ok { |
| 147 | return nil, diags.Append(&hcl.Diagnostic{ |
| 148 | Severity: hcl.DiagError, |
| 149 | Summary: "Invalid object property name", |
| 150 | Detail: "A JSON object property name must be a string", |
| 151 | Subject: keyNode.StartRange().Ptr(), |
| 152 | }) |
| 153 | } |
| 154 | |
| 155 | key := keyStrNode.Value |
| 156 | |
| 157 | colon := p.Read() |
| 158 | if colon.Type != tokenColon { |
| 159 | recover(colon) |
| 160 | |
| 161 | if colon.Type == tokenBraceC || colon.Type == tokenComma { |
no test coverage detected