(self, s, position, match, reentrances, fstruct)
| 2316 | raise ValueError("close bracket", position) |
| 2317 | |
| 2318 | def _read_partial_featdict(self, s, position, match, reentrances, fstruct): |
| 2319 | # If there was a prefix feature, record it. |
| 2320 | if match.group(2): |
| 2321 | if self._prefix_feature is None: |
| 2322 | raise ValueError("open bracket or identifier", match.start(2)) |
| 2323 | prefixval = match.group(2).strip() |
| 2324 | if prefixval.startswith("?"): |
| 2325 | prefixval = Variable(prefixval) |
| 2326 | fstruct[self._prefix_feature] = prefixval |
| 2327 | |
| 2328 | # If group 3 is empty, then we just have a bare prefix, so |
| 2329 | # we're done. |
| 2330 | if not match.group(3): |
| 2331 | return self._finalize(s, match.end(), reentrances, fstruct) |
| 2332 | |
| 2333 | # Build a list of the features defined by the structure. |
| 2334 | # Each feature has one of the three following forms: |
| 2335 | # name = value |
| 2336 | # name -> (target) |
| 2337 | # +name |
| 2338 | # -name |
| 2339 | while position < len(s): |
| 2340 | # Use these variables to hold info about each feature: |
| 2341 | name = value = None |
| 2342 | |
| 2343 | # Check for the close bracket. |
| 2344 | match = self._END_FSTRUCT_RE.match(s, position) |
| 2345 | if match is not None: |
| 2346 | return self._finalize(s, match.end(), reentrances, fstruct) |
| 2347 | |
| 2348 | # Get the feature name's name |
| 2349 | match = self._FEATURE_NAME_RE.match(s, position) |
| 2350 | if match is None: |
| 2351 | raise ValueError("feature name", position) |
| 2352 | name = match.group(2) |
| 2353 | position = match.end() |
| 2354 | |
| 2355 | # Check if it's a special feature. |
| 2356 | if name[0] == "*" and name[-1] == "*": |
| 2357 | name = self._features.get(name[1:-1]) |
| 2358 | if name is None: |
| 2359 | raise ValueError("known special feature", match.start(2)) |
| 2360 | |
| 2361 | # Check if this feature has a value already. |
| 2362 | if name in fstruct: |
| 2363 | raise ValueError("new name", match.start(2)) |
| 2364 | |
| 2365 | # Boolean value ("+name" or "-name") |
| 2366 | if match.group(1) == "+": |
| 2367 | value = True |
| 2368 | if match.group(1) == "-": |
| 2369 | value = False |
| 2370 | |
| 2371 | # Reentrance link ("-> (target)") |
| 2372 | if value is None: |
| 2373 | match = self._REENTRANCE_RE.match(s, position) |
| 2374 | if match is not None: |
| 2375 | position = match.end() |
no test coverage detected