PyHP/pyhp.py

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)