5
\$\begingroup\$

I decided to write my own programming language, of sorts. Essentially, you write code into a text file and the program will run the code inside the text file. The file is provided through a script argument.

# Basic programming language
from operator import eq, ne, lt, gt, le, ge
from random import random
from sys import exit, argv


# Specify file to be run
code = argv([1])


"""
>> - Specify to the user that something will be outputted.
<< - Specify to the user that something will be inputted.
"""


# Dict storing operators
OPERATORS = {
    "==": eq,
    "!=": ne,
    "<=": le,
    ">=": ge,
    "<": lt,
    ">": gt
}


# Dict storing program data
data = {
    "vars": [0] * 100000,
    "rand": random()
}


# Interpret the code
def interpreter(separator):
    for line in open(code, "r").readlines():

        # Split each line
        s_command = line.split(separator)

        # Basic input and output
        if s_command[0] == "$out" and s_command[1] == ">>":
            if s_command[2] in data:
                print data[s_command[2]]
            if s_command[2] not in data:
                print s_command[2]
        if s_command[0] == "$inp" and s_command[1] == "<<":
            inp = raw_input(s_command[2])

        # Assign integer variables
        if s_command[0] == "$assignint" and s_command[1] == "<<":
            data["vars"][int(s_command[2])] = int(s_command[3])

        # Assign string variables
        if s_command[0] == "$assignstr" and s_command[1] == "<<":
            data["vars"][int(s_command[2])] = s_command[3]

        # Return variable values
        if s_command[0] == "$return" and s_command[1] == ">>":
            print data["vars"][int(s_command[2])]

        # Test integer values
        if s_command[0] == "$testint" and s_command[1] == ">>":
            if s_command[3] in OPERATORS:
                print OPERATORS[s_command[3]](
                    int(s_command[2]),
                    int(s_command[4]))

        # Test string values
        if s_command[0] == "$teststr" and s_command[1] == ">>":
            if s_command[3] in OPERATORS:
                print OPERATORS[s_command[3]](
                    s_command[2],
                    s_command[4])

        # Test variable values
        if s_command[0] == "$testvar" and s_command[1] == ">>":
            if s_command[3] in OPERATORS:
                print OPERATORS[s_command[3]](
                    data["vars"][int(s_command[2])],
                    data["vars"][int(s_command[4])])

        # Terminate the program
        if s_command[0] == "$exit" and s_command[1] == ">>":
            exit(int(s_command[2]))


# Run the interpreter
if __name__ == "__main__":
    while True:
        interpreter(":")

Here's an example of a code file:

$out:>>:Hello world.
$inp:<<:[input]>

$assignint:<<:0:10
$assignint:<<:1:11

$return:>>:0
$return:>>:1

$testvar:>>:0:==:1
$testvar:>>:0:!=:1

$exit:>>:0

All I'm really looking for is a way to turn that ugly if/else chain into something prettier without changing the original syntax.

\$\endgroup\$

1 Answer 1

8
\$\begingroup\$

It looks like all your tests follow the pattern

if s_command[0] == "$xxxxx" and s_command[1] == "yyyyy":

So what you can do is create a tuple of the first two elements of s_command:

instr = tuple(s_command[:2])

Then, you can do

if instr == ("$xxxxx", "yyyyy"):

Next, you can use a dictionary to collect all your instructions in one place:

Instructions = {
    ("$out", ">>"): do_out,
    ("$inp", "<<"): do_inp,
    ("$assignint", "<<"): do_assignint,
    ...
}

Then you would define a number of functions, one for each instruction, such as

def do_inp(s_command):
    inp = raw_input(s_command[2])

and call your methods with

Instructions[instr](s_command)
\$\endgroup\$
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.