#! python 2.7
"""
V: 0.0.1 Test Build
Easy As Py
easyPyCompiler.py
Last edit was: Sunday, December 11, 2016
Jacob DiDiodato
A python-based interpreter for very novice programmers
Probably pretty slow and error-prone
Should write to a temporary python file and run it with syntax error checking
A very space-minded language
My apologies about not much commenting. I think a lot of this is fairly self-explainatory. If people want it then I'll add it later
My attempt at writing a compiler without an AST (just text verification)
"""
#Includes pygame and random natively! Thats fun!
import pygame
from random import *
import os,sys
dQuote = '"'
sQuote = "'"
#Words and symbols you can't use in var names
keyWords = ["print", "set", "to", "random", "add", "False", "None", "True", "and", "as", "assert", "break", "class", "continue", "def", "del", "elif", "else", "except", "finally", "for", "from", "global", "if", "import", "in", "is", "lambda", "nonlocal", "not", "or", "pass", "raise", "return", "try", "while", "with", "yield"]
keyChars = ['~', '`', '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+', '=', '{', '[', '}', ']',
':', ';', dQuote, sQuote, '<', ',', '>', '.', '?', '/', '|', '\\']
def generateRandom(commands):
exclusive = False
try:
commands[3]
except IndexError:
exclusive = True
else:
if (commands[3] == "e"):
exclusive = True
return "randint(" + str(commands[0]) + ", " + str(commands[2]) + " - " + str(int(exclusive)) + ")"
def checkRandomNum(commands, lineNo, globalVars):
if (commands[1] == "to"):
if (globalVars.get(commands[0]) != None):
commands[0] = globalVars.get(commands[0])
if (globalVars.get(commands[2]) != None):
commands[2] = globalVars.get(commands[2])
try:
int(commands[0])
int(commands[2])
except ValueError:
print "Line " + str(lineNo + 1) + "\nValueError: [easyPyError #4] One of the numbers you have entered cannot be converted to an integer."
return -1
else:
if (int(commands[2]) < int(commands[0])):
print "Line " + str(lineNo + 1) + "\nRandomError: [easyPyError #5] Your second number in range is larger than your first number in range.\nConsider switching them."
return -1
else:
return generateRandom(commands)
else:
print "Line " + str(lineNo + 1) + "\nFormattingError: [easyPyError #3] Missing word 'to'.\nFormat random number like: 'random num1 to num2 (i/e)'."
return -1
def addition(commands):
return str(commands[0]) + "+" + str(commands[2])
def checkAddNum(commands, lineNo, globalVars):
if (commands[1] == "to"):
if (globalVars.get(commands[0]) != None):
commands[0] = globalVars.get(commands[0])
if (globalVars.get(commands[2]) != None):
commands[2] = globalVars.get(commands[2])
try:
int(commands[0])
int(commands[2])
except ValueError:
print "Line " + str(lineNo + 1) + "\nValueError: [easyPyError #4] One of the numbers you have entered cannot be converted to an integer."
return -1
else:
return addition(commands)
else:
print "Line " + str(lineNo + 1) + "\nFormattingError: [easyPyError #3] Missing word 'to'.\nFormat addition like: 'add num1 to num2'."
return -1
def subtract(commands):
return str(commands[0]) + "-" + str(commands[2])
def checkSubNum(commands, lineNo, globalVars):
if (commands[1] == "from"):
if (globalVars.get(commands[0]) != None):
commands[0] = globalVars.get(commands[0])
if (globalVars.get(commands[2]) != None):
commands[2] = globalVars.get(commands[2])
try:
int(commands[0])
int(commands[2])
except ValueError:
print "Line " + str(lineNo + 1) + "\nValueError: [easyPyError #4] One of the numbers you have entered cannot be converted to an integer."
return -1
else:
return subtract(commands)
else:
print "Line " + str(lineNo + 1) + "\nFormattingError: [easyPyError #3] Missing word 'from'.\nFormat subtraction like: 'subtract num1 from num2'."
return -1
def interpret(srcText):
#the container for all global variables in the code
globalVars = {}
runningTab = ""
open("pySource.py", "w").close()
pySource = open("pySource.py", "a")
pySource.write("#! python2.7\n#Compiled with the Easy As Py Compiler\n\nimport pygame\nfrom random import *\n\n")
line = len(srcText)
for i in range(line):
commands = srcText[i].split(" ")
#To print a string/variable
if (commands[0] == "print"):
pySource.write("print ")
#If i am printing a variable check if that variable exists
#If it does then i print it but if it doesnt then i just print the word instead
if (globalVars.get(commands[1]) != None):
pySource.write(runningTab + commands[1] + "\n")
elif (commands[1] == "random"):
if (checkRandomNum(commands[2:], i, globalVars) != -1):
pySource.write(runningTab + checkRandomNum(commands[2:], i, globalVars) + "\n")
else:
break
elif (commands[1] == "add"):
if (checkAddNum(commands[2:], i, globalVars) != -1):
pySource.write(runningTab + checkAddNum(commands[2:], i, globalVars) + "\n")
else:
break
elif (commands[1] == "subtract"):
if (checkSubNum(commands[2:], i, globalVars) != -1):
pySource.write(runningTab + checkSubNum(commands[2:], i, globalVars) + "\n")
else:
break
#If i am printing a string
else:
#Print the contents of the string
pySource.write(runningTab + dQuote + " ".join(commands[1:]) + dQuote + "\n")
#To set a variable
elif (commands[0] == "set"):
#Checking syntax
if (commands[2] == "to"):
badVar = False
for j in range(len(keyChars)):
for k in range(len(commands[1])):
if (commands[1][k] == keyChars[j]):
print(commands[1][k])
print "Line " + str(i + 1) + "\nVariableNameError: [easyPyError #6] Invalid variable name.\nThe character '" + keyChars[j] + "' can't be used in a variable name."
badVar = True
for j in range(len(keyWords)):
if (commands[1] == keyWords[j]):
print "Line " + str(i + 1) + "\nVariableNameError: [easyPyError #6] Invalid variable name.\nThe word '" + keyWords[j] + "' is special and can't be used in a variable name."
badVar = True
if (badVar == True):
break
#Set our variable internally in a sort of RAM
#I use a dictionary to specify an arbitrarily large amount of RAM
#Write it into python code
if (commands[3] == "random"):
if (checkRandomNum(commands[4:], i, globalVars) != -1):
exclusive = False
try:
commands[7]
except IndexError:
exclusive = True
else:
if (commands[7] == "e"):
exclusive = True
if (globalVars.get(commands[4]) != None):
commands[4] = globalVars.get(commands[4])
if (globalVars.get(commands[6]) != None):
commands[6] = globalVars.get(commands[6])
randVar = randint(int(commands[4]), int(commands[6]) - int(exclusive))
globalVars[commands[1]] = randVar
pySource.write(runningTab + commands[1] + "=" + str(globalVars[commands[1]]) + "\n")
else:
break
elif (commands[3] == "add"):
if (checkAddNum(commands[4:], i, globalVars) != -1):
globalVars[commands[1]] = int(commands[4]) + int(commands[6])
pySource.write(runningTab + commands[1] + "=" + str(checkAddNum(commands[4:], i, globalVars)) + "\n")
else:
break
elif (commands[3] == "subtract"):
if (checkSubNum(commands[4:], i, globalVars) != -1):
globalVars[commands[1]] = int(commands[4]) - int(commands[6])
pySource.write(runningTab + commands[1] + "=" + str(checkSubNum(commands[4:], i, globalVars)) + "\n")
else:
break
else:
try:
globalVars[commands[1]] = int(commands[3]);
pySource.write(runningTab + commands[1] + "=" + str(globalVars[commands[1]]) + "\n")
except ValueError:
globalVars[commands[1]] = commands[3];
pySource.write(runningTab + commands[1] + "=" + dQuote + globalVars[commands[1]] + dQuote + "\n")
else:
#If we are missing some syntax
print "Line " + str(i + 1) + "\nFormattingError: [easyPyError #3] Missing word 'to'.\nFormat varible setting like: 'set varName to value'."
break
elif (commands[0] == "random"):
pySource.write(runningTab + checkRandomNum(commands[1:], i, globalVars))
elif (commands[0] == "add"):
pySource.write(runningTab + checkAddNum(commands[1:], i, globalVars))
elif (commands[0] == "subtract"):
pySource.write(runningTab + checkSubNum(commands[1:], i, globalVars))
elif (commands[0] == "!"):
pySource.write("#" + " ".join(commands[1:]) + "\n")
elif (commands[0] == ""):
pass
#If the first token is not recognized by the compiler
else:
print "Line " + str(i + 1) + "\nSyntaxError: [easyPyError #2] Token or function '" + str(commands[0] + "' does not exist.\nTake a look at the first word of line " + str(i + 1) + " to see if thats what you meant to type.")
pySource.close()
os.remove("pySource.py")
return -1
pySource.close()
os.system("python pySource.py")
#Keep the following line in the release build
#os.remove("pySource.py")
return 0
def openFile():
#Get the filename from the command line arguments
filename = str(sys.argv[1])
#Check to see if the file exists
try:
#Open the file
src = open(filename, "r")
except IOError:
#Give a very English defintion of the error
print "Line 0\nFileNameError: [easyPyError #1] That file does not exist.\nTry naming the file something like: '" + str(sys.argv[1].split(".")[0]) + ".easyPy'"
else:
srcText = src.read().split("\n")
interpret(srcText)
def main():
openFile()
main()
Comments
0 B
|👍
/👎