128 lines
5.1 KiB
Python
128 lines
5.1 KiB
Python
|
#!/usr/bin/env python3
|
||
|
|
||
|
# This is a naive implementation of the Python Hypertext preprocessor.
|
||
|
# For example, we just assume that we can hold the entire code in memory.
|
||
|
# Also, this is just the preprocessor, the resulting code will not be
|
||
|
# executed.
|
||
|
|
||
|
# Yes, the comments were here first and I wrote the code after writing them and then adjusted them to reality.
|
||
|
|
||
|
import sys
|
||
|
|
||
|
fd = open(sys.argv[1], "r")
|
||
|
lines = fd.read().split("\n")
|
||
|
fd.close()
|
||
|
|
||
|
# start text
|
||
|
output = "print(\"\"\""
|
||
|
# while not end of file
|
||
|
while len(lines)>0:
|
||
|
# grab a line to process
|
||
|
line = lines.pop(0)
|
||
|
# iterate over line
|
||
|
i=0
|
||
|
while i < len(line):
|
||
|
# attempt to grab the next few characters
|
||
|
try:
|
||
|
# variable(s) or code
|
||
|
if line[i:i+3] in ["<?p", "<?="]:
|
||
|
# end text
|
||
|
output = output + "\"\"\""
|
||
|
# variable(s)
|
||
|
if line[i:i+3] == "<?=":
|
||
|
output = output + " + str("
|
||
|
# store variable list
|
||
|
# (may span more than just one line)
|
||
|
variable_list = ""
|
||
|
i = i+3
|
||
|
# walk until we either encounter a ?> or a line break
|
||
|
while True:
|
||
|
# if line break, attempt to go to next line
|
||
|
if len(line[i:])<2:
|
||
|
variable_list = variable_list + line[i:]
|
||
|
i = -1
|
||
|
try:
|
||
|
line = lines.pop(0)
|
||
|
except IndexError:
|
||
|
print("Unexpected end of file: No closing ?> found.", file=sys.stderr)
|
||
|
sys.exit(1)
|
||
|
else:
|
||
|
if line[i:i+2]=="?>":
|
||
|
i = i+1
|
||
|
break
|
||
|
else:
|
||
|
# add to variable list
|
||
|
variable_list = variable_list + line[i]
|
||
|
i = i+1
|
||
|
# split at comma and add the variables
|
||
|
output = output + ") + str(".join(variable_list.split(",")) + ") + "
|
||
|
# code
|
||
|
elif line[i:i+4] == "<?py":
|
||
|
output = output + ", end=\"\")\n"
|
||
|
# determine indent
|
||
|
#default to 0
|
||
|
indent = 0
|
||
|
try:
|
||
|
# any non whitespace characters left on line?
|
||
|
if not line[i+4:].strip()=="":
|
||
|
# attempt to use that as indent value
|
||
|
indent = int(line[i+4:])
|
||
|
# determining indent failed
|
||
|
except ValueError:
|
||
|
print("Invalid indent: \""+line[i+4:]+"\"\n" + line, file=sys.stderr)
|
||
|
sys.exit(1)
|
||
|
# attempt to check for end of code
|
||
|
try:
|
||
|
# grab code line
|
||
|
line = lines.pop(0)
|
||
|
# determine appropriate unindent length to get
|
||
|
# "raw" code
|
||
|
unindent_length = len(line)-len(line.lstrip())
|
||
|
while not "?>" in line:
|
||
|
# fix indent
|
||
|
line = indent*" "+line[unindent_length:]
|
||
|
# add code line
|
||
|
output = output + line + "\n"
|
||
|
# grab next code line
|
||
|
line = lines.pop(0)
|
||
|
# checking for end of code failed
|
||
|
except IndexError:
|
||
|
print("Unexpected end of file: No closing ?> found.", file=sys.stderr)
|
||
|
sys.exit(1)
|
||
|
# attempt to determine indent after end of code
|
||
|
indent = 0
|
||
|
try:
|
||
|
if not line[:line.find("?>")].strip()=="":
|
||
|
indent = int(line[:line.find("?>")])
|
||
|
except ValueError:
|
||
|
print("Invalid indent: \""+line[:line.find("?>")]+"\"\n" + line, file=sys.stderr)
|
||
|
sys.exit(1)
|
||
|
# add indent after end of code
|
||
|
output = output + " "*indent + "print("
|
||
|
# set i accordingly to add rest of line after code
|
||
|
# block end
|
||
|
i = line.find("?>")+2
|
||
|
# assume accidental match
|
||
|
else:
|
||
|
# start text
|
||
|
output = output + " + \""
|
||
|
# add text
|
||
|
output = output + line[i]
|
||
|
# end text
|
||
|
output = output + "\" + "
|
||
|
# start text
|
||
|
output = output + "\"\"\""
|
||
|
else:
|
||
|
# add text
|
||
|
output = output + line[i]
|
||
|
# handle last characters of line
|
||
|
except IndexError:
|
||
|
# add text
|
||
|
output = output + line[i]
|
||
|
i = i+1
|
||
|
output = output + "\n"
|
||
|
# end text
|
||
|
output = output + "\"\"\", end=\"\")\n"
|
||
|
|
||
|
print(output)
|