├── Graphical.py ├── If.py ├── For.py ├── While.py ├── README.md └── Keg.py /Graphical.py: -------------------------------------------------------------------------------- 1 | import Keg, tkinter 2 | 3 | class Textbox(): 4 | def __init__(self, root, width, height, args): 5 | self.frame = tkinter.Frame(root, width=width, height=height) 6 | self.width, self.height = width, height 7 | 8 | self.widget = tkinter.Text(self.frame, args) 9 | self.widget.pack(expand=tkinter.YES, fill=tkinter.BOTH) 10 | 11 | def place(self, *args, **kwargs): 12 | self.frame.place(*args, **kwargs) 13 | self.frame.place_configure(width=self.width, height=self.height) 14 | self.frame.config(bd=1, relief="solid", highlightbackground="#ffffff") 15 | 16 | def grun(): 17 | Keg.stack = [] 18 | Keg.register = None 19 | Keg.comment = False 20 | Keg.escape = False 21 | Keg.printed = False 22 | Keg.grun(codebox.widget.get("1.0", tkinter.END), prepop.get()) 23 | 24 | root = tkinter.Tk() 25 | root.geometry('800x600') 26 | 27 | codebox = Textbox(root, 800, 300, {'height': '300', 'width': '800'}) 28 | codebox.place(x=0, y=0) 29 | 30 | submit = tkinter.Button(root, text="Run Program", command=grun) 31 | submit.place(x=0, y=301) 32 | 33 | tkinter.Label(root, text="Values to prepopulate stack").place(x=0, y=330) 34 | prepop = tkinter.Entry(root, width=50) 35 | prepop.place(x=0, y=350) 36 | -------------------------------------------------------------------------------- /If.py: -------------------------------------------------------------------------------- 1 | #If [...|...] Extractor 2 | 3 | def extract(string): 4 | result = {1: "", 0: ""} 5 | mode = 1 6 | escape = False 7 | opened = 0 8 | loops = {"for" : 0, "while" : 0} 9 | 10 | for char in string: 11 | if escape: 12 | result[mode] += char 13 | escape = False 14 | continue 15 | 16 | if char == "\\": 17 | escape = True 18 | result[mode] += char 19 | continue 20 | 21 | elif char == "(": 22 | loops["for"] += 1 23 | result[mode] += char 24 | 25 | elif char == ")": 26 | loops["for"] -= 1 27 | result[mode] += char 28 | 29 | elif char == "{": 30 | loops["while"] += 1 31 | result[mode] += char 32 | 33 | elif char == "}": 34 | loops["while"] -= 1 35 | result[mode] += char 36 | 37 | elif char == "[": 38 | if opened > 0: 39 | result[mode] += char 40 | opened += 1 41 | 42 | elif char == "|": 43 | if opened > 1: 44 | result[mode] += char 45 | elif max(list(loops.values())) != 0: 46 | result[mode] += char 47 | else: 48 | mode = 0 49 | 50 | elif char == "]": 51 | if opened > 1: 52 | result[mode] += char 53 | opened -= 1 54 | else: 55 | break 56 | 57 | else: 58 | if opened == 0: 59 | continue 60 | result[mode] += char 61 | 62 | return result 63 | 64 | 65 | -------------------------------------------------------------------------------- /For.py: -------------------------------------------------------------------------------- 1 | #For (...|...) Extractor 2 | 3 | def extract(string): 4 | result = {"count": "", "body": ""} 5 | mode = "count" 6 | escape = False 7 | opened = 0 8 | loops = {"if" : 0, "while" : 0} 9 | 10 | for char in string: 11 | if escape: 12 | result[mode] += char 13 | escape = False 14 | continue 15 | 16 | if char == "\\": 17 | escape = True 18 | result[mode] += char 19 | continue 20 | 21 | elif char == "[": 22 | loops["if"] += 1 23 | result[mode] += char 24 | 25 | elif char == "]": 26 | loops["if"] -= 1 27 | result[mode] += char 28 | 29 | elif char == "{": 30 | loops["while"] += 1 31 | result[mode] += char 32 | 33 | elif char == "}": 34 | loops["while"] -= 1 35 | result[mode] += char 36 | 37 | elif char == "(": 38 | if opened > 0: 39 | result[mode] += char 40 | opened += 1 41 | 42 | elif char == "|": 43 | if opened > 1: 44 | result[mode] += char 45 | elif max(list(loops.values())) != 0: 46 | result[mode] += char 47 | else: 48 | mode = "body" 49 | 50 | elif char == ")": 51 | if opened > 1: 52 | result[mode] += char 53 | opened -= 1 54 | else: 55 | break 56 | 57 | else: 58 | if opened == 0: 59 | continue 60 | result[mode] += char 61 | 62 | if result["body"] == "": 63 | result["body"] = result["count"] 64 | result["count"] = "!" 65 | return result 66 | -------------------------------------------------------------------------------- /While.py: -------------------------------------------------------------------------------- 1 | #While {...|...} Extractor 2 | 3 | def extract(string): 4 | result = {"condition": "", "body": ""} 5 | mode = "condition" 6 | escape = False 7 | opened = 0 8 | loops = {"if" : 0, "for" : 0} 9 | 10 | for char in string: 11 | if escape: 12 | result[mode] += char 13 | escape = False 14 | continue 15 | 16 | if char == "\\": 17 | escape = True 18 | result[mode] += char 19 | continue 20 | 21 | elif char == "[": 22 | loops["if"] += 1 23 | result[mode] += char 24 | 25 | elif char == "]": 26 | loops["if"] -= 1 27 | result[mode] += char 28 | 29 | elif char == "(": 30 | loops["for"] += 1 31 | result[mode] += char 32 | 33 | elif char == ")": 34 | loops["for"] -= 1 35 | result[mode] += char 36 | 37 | elif char == "{": 38 | if opened > 0: 39 | result[mode] += char 40 | opened += 1 41 | 42 | elif char == "|": 43 | if opened > 1: 44 | result[mode] += char 45 | elif max(list(loops.values())) != 0: 46 | result[mode] += char 47 | else: 48 | mode = "body" 49 | 50 | elif char == "}": 51 | if opened > 1: 52 | result[mode] += char 53 | opened -= 1 54 | else: 55 | break 56 | 57 | else: 58 | if opened == 0: 59 | continue 60 | result[mode] += char 61 | if result["body"] == "": 62 | result["body"] = result["condition"] 63 | result["condition"] = "1" 64 | return result 65 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Keg -- (Ke)yboard (G)olfed 2 | _Keg_ is a stack-based esolang with condensability as well as simplicity and readability in mind. It's main purpose is to be used for golfing, although it can be potentially used for other purposes. What makes this esolang different from others is that: 3 | 4 | * Alphanumerical characters are automatically pushed (no need to wrap them in quotation marks) 5 | * There are readable and intuitive `if` statements, `for` and `while` loops 6 | * The number of functions to remember is small 7 | * And much more 8 | 9 | ## A Few Conventions of This Document 10 | * `∆ ... ∆` in a code snippet means that the code in the `...` is optional 11 | * `>` in a code snippet means an input prompt 12 | * `>>>` in a code snippet means a command prompt 13 | 14 | ## Design Principles 15 | The main inspiration for _Keg_ comes from a want of an esolang where only symbols count as commands and everything else is pushed onto the stack as a literal. This is why there are only 12 functions, 7 'keywords' and 8 operators. As such, this system allows for shorter programs where strings are involved (_uncompressed_ strings in Keg are usually 1-2 bytes shorter than their counterparts in other languages). 16 | 17 | Another design feature of _Keg_ is the look of `if` statements, `for` loops and `while` loops. These **structures** take on the form of: 18 | 19 | B...B 20 | 21 | Where `B` is any of the three brackets (`(/)`, `[/]` or `{/}`) and `...` is any body of code 22 | 23 | ## The Basics 24 | Most tutorials show how to print the string `Hello, World!` , so that's what this tutorial will do as well. Here is a simple 21 byte program to achieve the goal. 25 | 26 | Hello\, World\!^(!|,) 27 | 28 | ### Explanation 29 | 30 | Hello #Push the characters "H", "e", "l", "l" and "o" to the stack 31 | \, #Escape the "," and push it to the stack 32 | World #Push the characters "W", "o", "r", "l" and "d" to the stack 33 | \! #Escape the "!" and push it to the stack 34 | ^ #Reverse the stack 35 | (!| #Start a for loop and set the count to the length of the stack 36 | , #Print the last item on the stack as a character 37 | ) 38 | 39 | In the above example, 6 new functions and keywords are introduced: 40 | 41 | `\` : Escapes the next command, and instead pushes it as a string (pushes its ascii value) 42 | `,` : Prints the last item on the stack as a character 43 | `!` : Pushes the length of the stack onto the stack 44 | `^` : Reverses the stack 45 | `(...)` : The for loop structure 46 | `|` : Used in structures to switch from one branch to the other. 47 | 48 | ### The Stack 49 | One of the most important parts of _Keg_ is the stack, which is where all operations are performed. A stack is a type of container (or list) where the last item in the container is the first item to be operated on (LIFO -- Last In First Out). In the following examples, the stack will be investigated. 50 | 51 | 3# [3] 52 | 4# [3, 4] 53 | +# [7] 54 | 55 | In the above example, the numbers `3` and `4` are pushed onto the stack, and are then added using the `+` operator. The way it works is that the `+` pops what will be called `x` and `y` off the stack (the first and second last item) and pushes `y` + `x` back onto the stack. Note that the order of `x` and `y` are important when using the `-` and `\` operators, as `x` - `y` doesn't equal `y` - `x` most of the time (as is the same with `x` / `y` and `y` / `x`). This can be seen in the following example: 56 | 57 | 34-.#Outputs -1 58 | 43-.#Outputs 1 59 | 34/.#Outputs 0.75 60 | 43/.#Outputs 1.333333333333 61 | 62 | _Note that the `.` function prints the last item on the stack as an integer._ 63 | 64 | ### Input and Output 65 | _Keg_ has two output functions and one input function. When taking input from the user, the next line from the Standard Input and push the ascii value of each character onto the stack. It will then push -1 onto the stack to sigify the end of input (input as integers will be coming in a later version of _Keg_). Input is taken using the `?` command, as shown in the example program: 66 | 67 | ?(!|,) 68 | 69 | # > Example text 70 | # Example text 71 | 72 | The two output functions (`.` -- Print as integer and `,` -- Print as string) have already been detailed in other sections 73 | 74 | ## Program Flow 75 | ### `If` Statements 76 | As mentioned in the introduction, _Keg_ has a readable and intuative way of expressing `if` statements, `for` and `while` loops. The form of an `if` statement is: 77 | 78 | [...1 ∆| ...2∆] 79 | 80 | When an `if` statement is run, the last item on the stack is popped, and if it is non-zero, `...1` is executed. If there is a `|...2`, it is executed if the popped value is 0. 81 | 82 | ### `For` Loops 83 | The form of a `for` loop is: 84 | 85 | (∆...1|∆ ...2) 86 | 87 | When a `for` loop is run, if `...1` is present, it will be evaluated as used as the number of times the loop will be run (if it isn't given, the length of the stack will be used). `...2` is the body of the `for` loop, which will be executed. 88 | 89 | ### `While` Loops 90 | The form of a `while` loop is: 91 | 92 | { ∆...1|∆ ...2} 93 | 94 | When a `while` loop is run, `...1` (if given) will be the condition of the loop (if it isn't present, `1` will be used as the condition of the loop) and `...2` will be executed until the given condition is false. 95 | 96 | ## User Defined Functions 97 | One of the special features of _Keg_ is user-defined functions, which are defined using the following form: 98 | 99 | @name ∆n∆ | ...@ 100 | 101 | Where: 102 | `name` = the name of the function (note that it needs to be one full word, and that it can't contain any `@`'s) 103 | `n` = the number of items popped from the stack 104 | `...` = the body of the function 105 | 106 | If `n` isn't present, no items will be popped from the stack, and all code in the function will be applied to the main stack 107 | 108 | ## Special Bits 109 | 110 | * If nothing is printed during the run of the program, the whole stack will be joined together (stringified, with values less than 10 or greater than 256 being treated as integers) and printed 111 | 112 | * Closing brackets can be left out of programs, and will be auto-completed in a LIFO matter 113 | 114 | ## Example Programs 115 | 116 | ### Hello World, Further Golfed 117 | 118 | Hello\, World\! 119 | 120 | ### Cat Program 121 | 122 | ?^_ 123 | 124 | ### Fizzbuzz Program 125 | 126 | 0(d|1+:35*%0=[ zzubzziF(9|,)|:5%0=[ zzuB(5|,)|:3%0=[ zziF(5|,)|:. ,]]]) 127 | 128 | ### 99 Bottles of Beer Program 129 | 130 | c&(c|&:.& bottles of beer on the wall\, ^(!|,)&:.& bottles of beer\.91+^(!|,)Take one down\, pass it around\, ^(!|,)&1-&&:.& bottles of beer on the wall\.91+^(!|,)) 131 | 132 | ### Quine 133 | 134 | Q 135 | 136 | _This can be any series of alphabetical letters_ 137 | 138 | ## Command Glossary 139 | |Command|Description|Usage|Notes| 140 | |------------|-------------|-------|-------| 141 | | `!` | Pushes the length of the stack onto the stack | `!` | | 142 | | `:` | Duplicates the last item on the stack | `:` | | 143 | | `_` | Removes the last item on the stack | `_` | | 144 | | `,` | Prints the last item on the stack as a character | `,` | | 145 | | `.` | Prints the last item on the stack as an integer | `.` | | 146 | | `?` | Gets input from the user | `?` | Pushes -1 after the last character of input to signify EOI | 147 | | `'` | Left shifts the stack | `'` | | 148 | | `"` | Right shifts the stack | `"` | | 149 | | `~` | Pushes a random number onto the stack | `~` | The number will be between 0 and 32767 | 150 | | `^` | Reverses the stack | `^` | | 151 | | `$` | Swaps the top two items on the stack | `$` | | 152 | | `#` | Starts a comment | `#` | | 153 | | `|` | Branches to the next section of a structure | `B...\|...B`| `B` is any one bracket type | 154 | | `\` | Escapes the next command, and pushes it as a string | `\` | | 155 | | `&` | Gets/sets the register value | `&` | | 156 | | `@` | Define/call a function | `@ name ∆n∆ \| ...@` | | 157 | | `+` | Pops `x` and `y` and pushes `y` + `x` | `+` | | 158 | | `-` | Pops `x` and `y` and pushes `y` - `x` | `-` | | 159 | | `*` | Pops `x` and `y` and pushes `y` * `x` | `*` | | 160 | | `/` | Pops `x` and `y` and pushes `y` / `x` | `/` | Divison by zero gives an error | 161 | | `%` | Pops `x` and `y` and pushes `y` % `x` | `%` | Divison by zero gives an error | 162 | | `<` | Pops `x` and `y` and pushes `y` < `x` | `<` | | 163 | | `>` | Pops `x` and `y` and pushes `y` > `x` | `>` | | 164 | | `=` | Pops `x` and `y` and pushes `y` == `x` | `=` | | 165 | | `0-9` | Pushes the given integer onto the stack | `` | | 166 | | `a-z, A-Z` | Pushes the ascii value of the given character onto the stack | `` | | 167 | 168 | -------------------------------------------------------------------------------- /Keg.py: -------------------------------------------------------------------------------- 1 | import For, If, While, random 2 | 3 | #Functions 4 | 5 | LENGTH = "!" #Pushes the length of the stack onto the stack 6 | DUPLICATE = ":" #Duplicates the last item on the stack 7 | POP = "_" #Pops the last item from the stack 8 | PRINT_CHR = "," #Prints the last item on the stack as a string (ord(char)) 9 | PRINT_INT = "." #Prints the last item on the stack as an integer 10 | INPUT = "?" #Gets input from the user, pushing -1 as EOI 11 | L_SHIFT = "'" #Left shift stack 12 | R_SHIFT = '"' #Right shift stack 13 | RANDOM = "~" #Pushes a random number between -infinity and infinity 14 | REVERSE = "^" #Reverses the stack 15 | SWAP = "$" #Swap the last two items on the stack 16 | 17 | #Keywords 18 | 19 | COMMENT = "#" #Creates a comment, which ignores all code thereafter 20 | BRANCH = "|" #Switches to the other part of a structure 21 | ESCAPE = "\\" #Pushes the next command as a string (ord(char)) 22 | C_STRING = "`" #Toggles string compression mode 23 | REGISTER = "&" #Gets/sets the register 24 | FUNCTION = "@" #Starts/ends a function definiton OR calls a function 25 | 26 | #Operators 27 | 28 | MATHS = "+-*/%" 29 | CONDITIONAL = "<>=" 30 | NUMBERS = "0123456789" 31 | 32 | #Whitespace 33 | 34 | TAB = "\t" 35 | ALT_TAB = " " 36 | NEWLINE = "\n" 37 | 38 | #Structures 39 | 40 | START = "start" 41 | END = "end" 42 | BODY = "body" 43 | 44 | FOR_LOOP = {START : "(", END : ")"} 45 | IF_STMT = {START : "[", END : "]"} 46 | WHILE_LOOP = {START : "{", END : "}"} 47 | 48 | stack = [] 49 | register = None 50 | comment = False 51 | escape = False 52 | printed = False 53 | 54 | def _eval(expression): 55 | #Evaulate the given expression as Keg code 56 | temp = [] 57 | for char in expression: 58 | if char in NUMBERS: 59 | temp.append(int(char)) 60 | 61 | elif char in MATHS: 62 | x, y = temp.pop(), temp.pop() 63 | temp.append(eval("y{0}x".format(char))) 64 | 65 | elif char in CONDITIONAL: 66 | lhs, rhs = temp.pop(), temp.pop() 67 | 68 | if char == "=": 69 | char = "==" 70 | 71 | result = eval("lhs{0}rhs".format(char)) 72 | 73 | if result: 74 | temp.append(1) 75 | else: 76 | temp.append(0) 77 | 78 | elif char == LENGTH: 79 | temp.append(len(stack)) 80 | 81 | elif char == DUPLICATE: 82 | temp.append(stack[-1]) 83 | 84 | elif char == RANDOM: 85 | temp.append(random.randint(0, 32767)) 86 | 87 | elif char == POP: 88 | temp.append(stack.pop()) 89 | 90 | elif char == NEWLINE or char == TAB: 91 | continue 92 | 93 | elif char in "#|`@": 94 | raise SyntaxError("Invalid symbol in expression: " + expression) 95 | 96 | else: 97 | temp.append(ord(char)) 98 | 99 | return temp[0] 100 | 101 | def split(source): 102 | source = list(source.replace(TAB, "")) 103 | structures = {"If" : 0, "While" : 0, "For" : 0} 104 | indexes = [] 105 | index = {START : 0, END : 0, BODY : None} 106 | structure = None 107 | 108 | for i in range(len(source)): 109 | char = source[i] 110 | 111 | if char in FOR_LOOP.values(): 112 | if char == FOR_LOOP[START]: 113 | if max(structures.values()) == 0: 114 | structure = "For" 115 | index[START] = i 116 | 117 | structures["For"] += 1 118 | 119 | else: 120 | if list(structures.values()).count(0) == 2: 121 | if structures["For"] == 1 and structure == "For": 122 | index[END] = i 123 | index[BODY] = For.extract( 124 | "".join(source[index[START] : index[END] + 1])) 125 | indexes.append(index) 126 | index = {START : 0, END : 0, BODY : None} 127 | structure = None 128 | 129 | 130 | structures["For"] -= 1 131 | 132 | elif char in WHILE_LOOP.values(): 133 | if char == WHILE_LOOP[START]: 134 | if max(structures.values()) == 0: 135 | structure = "While" 136 | index[START] = i 137 | 138 | structures["While"] += 1 139 | 140 | else: 141 | if list(structures.values()).count(0) == 2: 142 | if structures["While"] == 1 and structure == "While": 143 | index[END] = i 144 | index[BODY] = While.extract( 145 | "".join(source[index[START] : index[END] + 1])) 146 | indexes.append(index) 147 | index = {START : 0, END : 0, BODY : None} 148 | structure = None 149 | 150 | structures["While"] -= 1 151 | 152 | elif char in IF_STMT.values(): 153 | if char == IF_STMT[START]: 154 | if max(structures.values()) == 0: 155 | structure = "If" 156 | index[START] = i 157 | 158 | structures["If"] += 1 159 | 160 | else: 161 | if list(structures.values()).count(0) == 2: 162 | if structures["If"] == 1 and structure == "If": 163 | index[END] = i 164 | index[BODY] = If.extract( 165 | "".join(source[index[START] : index[END] + 1])) 166 | indexes.append(index) 167 | index = {START : 0, END : 0, BODY : None} 168 | structure = None 169 | 170 | structures["If"] -= 1 171 | 172 | else: 173 | if structure is None: 174 | index[START] = i 175 | index[END] = i 176 | index[BODY] = source[i] 177 | indexes.append(index) 178 | index = {START : 0, END : 0, BODY : None} 179 | 180 | new = [] 181 | 182 | for index in indexes: 183 | new.append(index[BODY]) 184 | 185 | return new 186 | 187 | 188 | def run(source): 189 | global stack, register, comment, escape, printed 190 | 191 | if type(source) == str: 192 | #print(source) 193 | code = split(source) 194 | 195 | elif type(source) != list: 196 | raise TypeError("The given code is not of a supported type") 197 | 198 | else: 199 | code = source 200 | 201 | for cmd in code: 202 | 203 | #Handle any effects from keywords first 204 | 205 | if comment: 206 | if cmd == NEWLINE: 207 | comment = False 208 | 209 | continue 210 | 211 | if escape: 212 | escape = False 213 | stack.append(ord(cmd)) 214 | continue 215 | 216 | #Functions first 217 | if cmd == LENGTH: 218 | stack.append(len(stack)) 219 | 220 | elif cmd == DUPLICATE: 221 | stack.append(stack[-1]) 222 | 223 | elif cmd == POP: 224 | stack.pop() 225 | 226 | elif cmd == PRINT_CHR: 227 | print(chr(stack.pop()), end="") 228 | printed = True 229 | 230 | elif cmd == PRINT_INT: 231 | print(stack.pop(), end="") 232 | printed = True 233 | 234 | elif cmd == L_SHIFT: 235 | stack.append(stack[0]) 236 | del stack[0] 237 | 238 | elif cmd == R_SHIFT: 239 | stack.insert(0, stack.pop()) 240 | 241 | elif cmd == RANDOM: 242 | stack.append(random.randint(0, 32767)) 243 | 244 | elif cmd == REVERSE: 245 | stack.reverse() 246 | 247 | elif cmd == SWAP: 248 | stack[-1], stack[-2] = stack[-2], stack[-1] #only in python you see 249 | #this 250 | elif cmd == INPUT: 251 | x = input() 252 | stack.append(-1) 253 | for char in reversed(x): 254 | stack.append(ord(char)) 255 | 256 | 257 | #Now keywords 258 | 259 | elif cmd == COMMENT: 260 | comment = True 261 | 262 | elif cmd == BRANCH: 263 | #Just continue on this one, because hypothetically, all |'s 264 | #should be dealt with earlier 265 | continue 266 | 267 | elif cmd == ESCAPE: 268 | escape = True 269 | 270 | #elif cmd == C_STRING: 271 | #Code to handle string compression 272 | 273 | elif cmd == REGISTER: 274 | if register is None: 275 | register = stack.pop() 276 | 277 | else: 278 | stack.append(register) 279 | register = None 280 | 281 | #elif cmd == FUNCTION: 282 | #Code to handle functions here 283 | 284 | #Now, structures 285 | elif type(cmd) == dict: 286 | if 1 in cmd: 287 | #Must be an if 288 | test = stack.pop() 289 | 290 | if test: 291 | run(cmd[1]) 292 | 293 | else: 294 | run(cmd[0]) 295 | 296 | elif 'count' in cmd: 297 | #Must be a for loop 298 | n = _eval(cmd["count"]) 299 | 300 | for q in range(n): 301 | run(cmd["body"]) 302 | 303 | elif 'condition' in cmd: 304 | #Must be a while loop 305 | condition = cmd["condition"] 306 | #print(condition, _eval(condition), stack) 307 | 308 | while _eval(condition): 309 | run(cmd["body"]) 310 | 311 | else: 312 | raise Exception("Oh, uh, could you get me the milk!") 313 | 314 | #Now, operators 315 | elif cmd in MATHS: 316 | x, y = stack.pop(), stack.pop() 317 | stack.append(eval("y{0}x".format(cmd))) 318 | 319 | elif cmd in CONDITIONAL: 320 | lhs, rhs = stack.pop(), stack.pop() 321 | 322 | if cmd == "=": 323 | cmd = "==" 324 | 325 | result = eval("rhs{0}lhs".format(cmd)) 326 | 327 | if result: 328 | stack.append(1) 329 | else: 330 | stack.append(0) 331 | 332 | elif cmd in NUMBERS: 333 | stack.append(int(cmd)) 334 | 335 | #Deal with whitespace 336 | elif cmd == TAB: 337 | continue 338 | 339 | elif cmd == ALT_TAB: 340 | continue 341 | 342 | elif cmd == NEWLINE: 343 | continue 344 | 345 | #Don't do anything with normal spaces, as they are pushed 346 | 347 | else: 348 | stack.append(ord(cmd)) 349 | 350 | #print(cmd, stack) 351 | 352 | def grun(code, prepop): 353 | for item in prepop.split(): 354 | stack.append(int(item)) 355 | 356 | run(code) 357 | 358 | if not printed: 359 | printing = "" 360 | for item in stack: 361 | if item < 10 or item > 256: 362 | printing += str(item) + " " 363 | 364 | else: 365 | printing += chr(item) 366 | 367 | print(printing) 368 | 369 | 370 | 371 | if __name__ == "__main__": 372 | file_location = input("Enter the file location of the Keg program: ") 373 | prepop = input("Enter values to prepopulate the stack: ") 374 | 375 | for item in prepop.split(): 376 | stack.append(int(item)) 377 | 378 | code = open(file_location, encoding="utf-8").read().strip("\n") 379 | run(code) 380 | 381 | if not printed: 382 | printing = "" 383 | for item in stack: 384 | if item < 10 or item > 256: 385 | printing += str(item) + " " 386 | 387 | else: 388 | printing += chr(item) 389 | 390 | print(printing) 391 | --------------------------------------------------------------------------------