Skip to content

Commit

Permalink
Finished
Browse files Browse the repository at this point in the history
Implemented turing complete programming language
  • Loading branch information
deflucaseng committed Dec 26, 2024
1 parent 3337287 commit a4a674f
Show file tree
Hide file tree
Showing 17 changed files with 451 additions and 0 deletions.
3 changes: 3 additions & 0 deletions notes.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Aatish said I missed some teammate evaluations for non-subteam members in the assignments. And with personal updates
that I missed the first few but after I talked to him earlier in the semester about it the submissions have been solid.
Because of that he recommended I ask you given that I am 2 points from an A in the class.
6 changes: 6 additions & 0 deletions readme.MD
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
lexer will convert into tokens

I will use the symboltable, but fortunately with python I can be more "liberal" with the way I interact with types

evaluator will be used for actually running the code.

Binary file added src/__pycache__/engevaluator.cpython-39.pyc
Binary file not shown.
Binary file added src/__pycache__/englexer.cpython-39.pyc
Binary file not shown.
Binary file added src/__pycache__/engnode.cpython-39.pyc
Binary file not shown.
Binary file added src/__pycache__/engparser.cpython-39.pyc
Binary file not shown.
Binary file added src/__pycache__/engtoken.cpython-39.pyc
Binary file not shown.
Binary file added src/__pycache__/symboltable.cpython-39.pyc
Binary file not shown.
73 changes: 73 additions & 0 deletions src/engevaluator.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
from engnode import *
from symboltable import SymbolTable


class EngEvaluator:
def __init__(self, nodes):
self.nodes = nodes
self.end = False
self.counter = 0
self.st = SymbolTable()

while(not self.end):
self.runcycle()


def runcycle(self):
currenttype = type(self.nodes[self.counter])
if(currenttype == DisplayNode):
print(self.gettrueval(self.nodes[self.counter].displayval))
elif(currenttype == SimpleAssignNode):
self.st.updateval(self.nodes[self.counter].var, self.gettrueval(self.nodes[self.counter].value))

elif(currenttype == EvaluatedAssignNode):
var, lhs, op, rhs = self.nodes[self.counter].var, self.nodes[self.counter].lhs, self.nodes[self.counter].op, self.nodes[self.counter].rhs
lhs, rhs, = self.gettrueval(lhs), self.gettrueval(rhs)

if(op == "equals"):
self.st.updateval(var, lhs == rhs)
elif(op == "!equals"):
self.st.updateval(var, lhs != rhs)
elif(op == "or"):
self.st.updateval(var, lhs or rhs)
elif(op == "and"):
self.st.updateval(var, lhs and rhs)
elif(op == "xnor"):
self.st.updateval(var, (not lhs and not rhs) or (lhs and rhs))
elif(op == "nor"):
self.st.updateval(var, (not lhs and not rhs))
elif(op == "xor"):
self.st.updateval(var, not ((not lhs and not rhs) or (lhs and rhs)))
elif(op == "nand"):
self.st.updateval(var, not(lhs and rhs))
elif(op == "plus"):
self.st.updateval(var, lhs + rhs)
elif(op == "minus"):
self.st.updateval(var, lhs - rhs)
elif(op == "times"):
self.st.updateval(var, lhs * rhs)
elif(op == "divided"):
self.st.updateval(var, lhs / rhs)
else:
raise ValueError

elif(currenttype == JumpNode):
if(self.gettrueval(self.nodes[self.counter].condition)):
self.counter = self.nodes[self.counter].jumpto - 2

elif(currenttype == EndNode):
self.end = True
else:
raise ValueError

self.counter += 1



def gettrueval(self, var):
if(var in self.st):
return self.st.getval(var)
elif(var.isalpha()):
return bool(var)
else:
return int(var)
11 changes: 11 additions & 0 deletions src/englexer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
from engtoken import EngToken


class EngLexer:
def __init__(self, path):
self.path = path

def lex(self):
with open(self.path, 'r') as file:
content = [line.strip() for line in file.readlines() if line != '\n']
return [EngToken(line) for line in content]
41 changes: 41 additions & 0 deletions src/engnode.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
class DisplayNode:
def __init__(self, displayval):
self.displayval = displayval

def __repr__(self):
return f'printing: {self.displayval}'


class SimpleAssignNode:
def __init__(self, var, value):
self.var = var
self.value = value

def __repr__(self):
return f'assigning {self.value} to {self.var}'

class EvaluatedAssignNode:
def __init__(self, var, lhs, op, rhs):
self.var = var
self.lhs = lhs
self.op = op
self.rhs = rhs

def __repr__(self):
return f'{self.lhs} {self.op} {self.rhs} are now assigned to {self.var}'

class JumpNode:
def __init__(self, jumpto, condition):
self.jumpto = int(jumpto)
self.condition = condition

def __repr__(self):
return f'jumping to line {self.jumpto} if {self.condition}'

class EndNode:
def __init__(self):
pass

def __repr__(self):
return "ending program"

48 changes: 48 additions & 0 deletions src/engparser.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
from engnode import *




class EngParser:

def parsetokens(self, tokens):
nodelst = []


for token in tokens:
if(token.type == "display"):
nodelst.append(self.parseDisplay(token.val[0]))
elif(token.type == "simpleassign"):
nodelst.append(self.parseSimpleAssign(token.var, token.val[0]))
elif(token.type == "numericcomparativeassign"):
nodelst.append(self.parseNumericComparativeAssign(token.var, token.val))
elif(token.type == "evaluatedassign"):
nodelst.append(self.parseEvaluatedAssign(token.var, token.val))
elif(token.type == "jump"):
nodelst.append(self.parseJump(token.val))
elif(token.type == "end"):
nodelst.append(EndNode())
else:
print("Error unknown Type Parser")
raise ValueError
return nodelst

def parseDisplay(self, displayval):
return DisplayNode(displayval)

def parseSimpleAssign(self, var, value):
return SimpleAssignNode(var, value)

def parseNumericComparativeAssign(self, var, value):
if(len(value) == 5): #Is equal to
return EvaluatedAssignNode(var, value[0], "equals", value[-1])

else: #is not equal to
return EvaluatedAssignNode(var, value[0], "!equals", value[-1])

def parseEvaluatedAssign(self, var, value):
return EvaluatedAssignNode(var, value[0], value[1], value[2])

def parseJump(self, value):
return JumpNode(value[0], value[-1])

34 changes: 34 additions & 0 deletions src/engtoken.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
class EngToken:
def __init__(self, line):
self.linelst = line.split()
if(self.linelst[0] == "end"):
self.type = "end"
self.var = None
self.val = []
elif(self.linelst[0] == "jump"):
self.type = "jump"
self.var = None
self.val = [val for val in self.linelst[2:]]

elif(self.linelst[0] == "display"):
self.type = "display"
self.var = None
self.val = [self.linelst[1]]
elif(self.linelst[1] == "isnow" and len(self.linelst) == 3):
self.type = "simpleassign"
self.var = self.linelst[0]
self.val = [self.linelst[2]]
elif(len(self.linelst) > 6):
self.type = "numericcomparativeassign"
self.var = self.linelst[0]
self.val = [val for val in self.linelst[2:]]
else:
self.type = "evaluatedassign"
self.var = self.linelst[0]
self.val = [val for val in self.linelst[2:]]

def __repr__(self):
return " ".join(self.linelst)



39 changes: 39 additions & 0 deletions src/main.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import sys
import os
from englexer import EngLexer
from engparser import EngParser
from engevaluator import EngEvaluator

def main():
# Check if a file path was provided as an argument
if len(sys.argv) < 2:
print("Error: Please provide a file path")
sys.exit(1)

# Get the file path from command line arguments
file_path = sys.argv[1]
if file_path[-4:] != ".eng":
print("Wrong file format")
sys.exit(1)
filename = file_path.split(".")[0]


# Check if the file exists
if not os.path.exists(file_path):
print(f"Error: File '{file_path}' does not exist")
sys.exit(1)

try:
# Open and read the file
tokens = EngLexer(file_path).lex()
parsednodes = EngParser().parsetokens(tokens)
EngEvaluator(parsednodes)



except Exception as e:
print(f"Error reading file: {e}")
sys.exit(1)

if __name__ == "__main__":
main()
13 changes: 13 additions & 0 deletions src/symboltable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class SymbolTable:
def __init__(self):
self.table = {}

def __contains__(self, value):
return value in self.table

def updateval(self, var, value):
self.table[var] = value

def getval(self, var):
return self.table[var]

16 changes: 16 additions & 0 deletions src/test.eng
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
ind1 isnow 2














end
Loading

0 comments on commit a4a674f

Please sign in to comment.