()
| 1137 | } |
| 1138 | |
| 1139 | parseNode() { |
| 1140 | this.skipWhitespace(); |
| 1141 | |
| 1142 | let nodeName = ''; |
| 1143 | let nodeLabel = null; |
| 1144 | const labels = []; |
| 1145 | |
| 1146 | // Parse node identifier |
| 1147 | if (this.content.charCodeAt(this.pos) === SLASH) { |
| 1148 | nodeName = '/'; |
| 1149 | this.pos++; |
| 1150 | } else { |
| 1151 | const startPos = this.pos; |
| 1152 | while (this.pos < this.length && this.isIdentifierChar(this.content.charCodeAt(this.pos))) { |
| 1153 | this.pos++; |
| 1154 | } |
| 1155 | nodeName = this.content.slice(startPos, this.pos); |
| 1156 | } |
| 1157 | |
| 1158 | this.skipWhitespace(); |
| 1159 | |
| 1160 | // Handle multiple labels (e.g., label1: label2: nodename) |
| 1161 | while (this.pos < this.length && this.content.charCodeAt(this.pos) === COLON) { |
| 1162 | labels.push(nodeName); |
| 1163 | this.pos++; // consume ':' |
| 1164 | this.skipWhitespace(); |
| 1165 | |
| 1166 | const startPos = this.pos; |
| 1167 | while (this.pos < this.length && this.isIdentifierChar(this.content.charCodeAt(this.pos))) { |
| 1168 | this.pos++; |
| 1169 | } |
| 1170 | nodeName = this.content.slice(startPos, this.pos); |
| 1171 | this.skipWhitespace(); |
| 1172 | } |
| 1173 | |
| 1174 | // Set the primary label (first one if multiple) |
| 1175 | nodeLabel = labels.length > 0 ? labels[0] : null; |
| 1176 | |
| 1177 | if (this.content.charCodeAt(this.pos) !== LBRACE) { |
| 1178 | return null; |
| 1179 | } |
| 1180 | this.pos++; // consume '{' |
| 1181 | |
| 1182 | const node = { |
| 1183 | name: nodeName, |
| 1184 | label: nodeLabel, |
| 1185 | properties: {}, |
| 1186 | children: {} |
| 1187 | }; |
| 1188 | |
| 1189 | // Add all labels if multiple exist |
| 1190 | if (labels.length > 1) { |
| 1191 | node.labels = labels; |
| 1192 | } |
| 1193 | |
| 1194 | // Parse node contents |
| 1195 | while (this.pos < this.length) { |
| 1196 | this.skipWhitespace(); |
no test coverage detected