Jacob_DiDiodato icon

Easy As Py Compiler

Jacob_DiDiodato | PRO | 02/24/17 01:03:03 AM UTC | 0 ⭐ | 315 👁️ | Never ⏰ | []
Python |

9.61 KB

|

None

|

0 👍

/

0 👎

#! 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

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎