(astr, env, level, line)
| 214 | |
| 215 | |
| 216 | def parse_string(astr, env, level, line): |
| 217 | lineno = f"#line {line}\n" |
| 218 | |
| 219 | # local function for string replacement, uses env |
| 220 | def replace(match): |
| 221 | name = match.group(1) |
| 222 | try: |
| 223 | val = env[name] |
| 224 | except KeyError: |
| 225 | msg = f'line {line}: no definition of key "{name}"' |
| 226 | raise ValueError(msg) from None |
| 227 | return val |
| 228 | |
| 229 | code = [lineno] |
| 230 | struct = parse_structure(astr, level) |
| 231 | if struct: |
| 232 | # recurse over inner loops |
| 233 | oldend = 0 |
| 234 | newlevel = level + 1 |
| 235 | for sub in struct: |
| 236 | pref = astr[oldend:sub[0]] |
| 237 | head = astr[sub[0]:sub[1]] |
| 238 | text = astr[sub[1]:sub[2]] |
| 239 | oldend = sub[3] |
| 240 | newline = line + sub[4] |
| 241 | code.append(replace_re.sub(replace, pref)) |
| 242 | try: |
| 243 | envlist = parse_loop_header(head) |
| 244 | except ValueError as e: |
| 245 | msg = f"line {newline}: {e}" |
| 246 | raise ValueError(msg) |
| 247 | for newenv in envlist: |
| 248 | newenv.update(env) |
| 249 | newcode = parse_string(text, newenv, newlevel, newline) |
| 250 | code.extend(newcode) |
| 251 | suff = astr[oldend:] |
| 252 | code.append(replace_re.sub(replace, suff)) |
| 253 | else: |
| 254 | # replace keys |
| 255 | code.append(replace_re.sub(replace, astr)) |
| 256 | code.append('\n') |
| 257 | return ''.join(code) |
| 258 | |
| 259 | def process_str(astr): |
| 260 | code = [header] |
no test coverage detected
searching dependent graphs…