I'm working on a script parser that expands embedded Python code into script code by extracting all Python code into a single file so that it can remember Python variables defined earlier in the script. In order to substitute the Python output in the appropriate places in the script, it therefore cares about both Python's output, and the line number that produced this output. So I would like to generate Python code like this:
sys.stdout = ... # Write function reads _lineNumber and includes it in the output
_lineNumber = 1 # this line automatically inserted
print("qwerty") # from line 1
_lineNumber = 2 # this line automatically inserted
def foobar(x):
print(x)
_lineNumber = 4
if True:
foobar("fdsa") # from line 4
_lineNumber = 6
foobar("asdf") # from line 6
Note however that I have to skip lines 3 and 5 because they are not at the top-level context--changing _lineNumber during the function call would be incorrect behavior, and changing _lineNumber during the if would require matching the indentation and is unnecessarily complicated when I can simply require that the user complete all code blocks such as functions and conditionals in the same block of script code. My problem is ensuring that it is always valid to perform the assignment to _lineNumber when I do--the lines between the assignments are arbitrary code. My question is, if the following line has no indentation, does that guarantee that it is syntactically valid to insert an assignment to _lineNumber on the previous line, or is there any other python grammar that would make the scheme of inserting an assignment before every unindented line be invalid?
No; while indentation at the start of the line can tell you the the depth of context of that statement, it is still possible for many things such as lists to cause one line to span multiple code lines, and other statements such as else
can be connected to earlier statements despite having no indentation. There's no simple way to do this; short of getting into the python parsing, you'd have to rely on the user to return to the top level context at well-defined points.