import re
from Variable import Variable
from collections import deque
vars = []
class SyntaxAnalyzer:
def program(self, tokens, lexeme, row):
i = 0
while tokens[i] == "COMMENT":
i += 1
if tokens[i] == "START": # encountered start of program
print("==== PROGRAM START! === \n")
i += 1
while tokens[i] != "END" and i < len(tokens):
if tokens[i] == "COMMENT":
i += 1
continue
if tokens[i] == "WAZZUP":
i += 1
i = isVarDec(tokens, lexeme, row, i)
i = statement(tokens, lexeme, row, i)
if i >= len(tokens):
break
if i == len(tokens):
raise RuntimeError("End of program not found")
# printVariables()
else:
raise RuntimeError("Start of program not found")
def isVarDec(tokens, lexeme, row, i):
maxlen = len(tokens)
while tokens[i] != "BUHBYE":
if tokens[i] == "COMMENT": # aka BTW (single line comment)
# comments are stored all in one, if it's a multiline is when we iterate thru so this is fine
i += 1
continue
elif tokens[i] == "VAR_DEC":
# build line
rowNum = row[i]
line = []
tline = []
while rowNum == row[i]:
line.append(lexeme[i])
tline.append(tokens[i])
i += 1
storeVariable(tline, line, rowNum)
else:
raise RuntimeError(
"Unexpected %r on line %d, Only variable declarations are allowed in this section"
% (lexeme[i], row[i])
)
if i >= maxlen:
raise RuntimeError("Encountered end of file")
return i
def storeVariable(tline, line, rowNum):
global vars
i = 1
maxlength = len(tline)
if tline[i] == "VARIABLE":
varName = line[i][:-1]
i += 1
else:
raise RuntimeError("Expected VARIABLE NAME on line %d" % (rowNum))
if i >= maxlength:
vars.append(Variable(varName, "NOOB", None))
return
if tline[i] == "ITZ":
i += 1
else:
raise RuntimeError("Expected 'ITZ' on line %d" % (rowNum))
if i >= maxlength:
raise RuntimeError("Encountered end of file!")
if (
tline[i] == "NOOB"
or tline[i] == "YARN"
or tline[i] == "TROOF"
or tline[i] == "NUMBAR"
or tline[i] == "NUMBR"
or tline[i] == "VARIABLE"
):
type = tline[i]
value = line[i]
vars.append(Variable(varName, type, value))
return
else:
raise RuntimeError(
"Variable declaration can only be to a YARN, TROOF, NOOB etch"
)
vars.append(Variable("IT", "NOOB", ""))
def statement(tokens, lexeme, row, i):
tline = []
line = []
rowNum = row[i]
# print(rowNum)
while rowNum == row[i]:
tline.append(tokens[i])
line.append(lexeme[i])
i += 1
if tline[0] == "PRINT":
printLine(line, tline)
elif tline[0] == "VAR_DEC":
raise RuntimeError("Unexpected variable declaration at line %d" % (rowNum))
elif tline[0] == "BOOL_OPER":
print(boolOpRegion(line, tline, 0, rowNum))
elif tline[0] == "COMPARISON":
print(comparison(line, tline, 0, rowNum))
elif tline[0] == "MATH":
print(mathOp(line, tline, 0, rowNum))
return i
def comparison(line, tline, i, rowNum):
compQ = []
# print(line)
if line[i] == "BOTH SAEM":
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
if tline[i] != "AN":
raise RuntimeError("Expected AN at line %d" % (rowNum))
i += 1
if line[i] == "BIGGR OF" or line[i] == "SMALLR OF":
compQ.append(line[i])
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
if compQ[0][1] != compQ[2][1]:
raise RuntimeError(
"Value mismatch - operand 1 and 2 (%r and %r) must be same"
% (compQ[0][1], compQ[2][1])
)
if tline[i] != "AN":
raise RuntimeError("Expected AN at line %d" % (rowNum))
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
elif tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, VARIABLE, BIGGR OF, or SMALLR OF at line %d"
% (rowNum)
)
# print(compQ)
if compQ[1] == "BIGGR OF":
if compQ[2][0] != compQ[3][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[2][0] == "NUMBR":
if int(compQ[2][1]) >= int(compQ[3][1]):
return "WIN"
else:
return "FAIL"
elif compQ[2][0] == "NUMBAR":
if float(compQ[2][1]) >= float(compQ[3][1]):
return "WIN"
else:
return "FAIL"
else:
raise RuntimeError("Unexpected type %r" % (compQ[2][0]))
elif compQ[1] == "SMALLR OF":
if compQ[2][0] != compQ[3][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[2][0] == "NUMBR":
if int(compQ[2][1]) <= int(compQ[3][1]):
return "WIN"
else:
return "FAIL"
elif compQ[2][0] == "NUMBAR":
if float(compQ[2][1]) <= float(compQ[3][1]):
return "WIN"
else:
return "FAIL"
else:
raise RuntimeError("Unexpected type %r" % (compQ[2][0]))
else:
if compQ[0][0] != compQ[1][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[0][1] == compQ[1][1]:
return "WIN"
else:
return "FAIL"
elif line[i] == "DIFFRINT":
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
if tline[i] != "AN":
raise RuntimeError("Expected AN at line %d" % (rowNum))
i += 1
if line[i] == "BIGGR OF" or line[i] == "SMALLR OF":
compQ.append(line[i])
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
if compQ[0][1] != compQ[2][1]:
raise RuntimeError(
"Value mismatch on line %d (%r and %r) must be same"
% (rowNum, compQ[0][1], compQ[2][1])
)
if tline[i] != "AN":
raise RuntimeError("Expected AN at line %d" % (rowNum))
i += 1
if tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, or VARIABLE at line %d" % (rowNum)
)
elif tline[i] == "NUMBR" or tline[i] == "NUMBAR":
compQ.append([tline[i], line[i]])
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
compQ.append([type, value])
i += 1
else:
raise RuntimeError(
"Expected NUMBR, NUMBAR, VARIABLE, BIGGR OF, or SMALLR OF at line %d"
% (rowNum)
)
# print(compQ)
if compQ[1] == "BIGGR OF":
if compQ[2][0] != compQ[3][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[2][0] == "NUMBR":
if int(compQ[3][1]) >= int(compQ[2][1]):
return "WIN"
else:
return "FAIL"
elif compQ[2][0] == "NUMBAR":
if float(compQ[3][1]) >= float(compQ[2][1]):
return "WIN"
else:
return "FAIL"
else:
raise RuntimeError("Unexpected type %r" % (compQ[2][0]))
elif compQ[1] == "SMALLR OF":
if compQ[2][0] != compQ[3][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[2][0] == "NUMBR":
if int(compQ[3][1]) <= int(compQ[2][1]):
return "WIN"
else:
return "FAIL"
elif compQ[2][0] == "NUMBAR":
if float(compQ[3][1]) <= float(compQ[2][1]):
return "WIN"
else:
return "FAIL"
else:
raise RuntimeError("Unexpected type %r" % (compQ[2][0]))
else:
if compQ[0][0] != compQ[1][0]:
raise RuntimeError(
"Type mismatch - cannot compare %r and %r"
% (compQ[0][0], compQ[1][0])
)
if compQ[0][1] != compQ[1][1]:
return "WIN"
else:
return "FAIL"
# function for parsing prefix notation math operations
def parse(tokens):
if not tokens:
raise RuntimeError("Unexpected end of statement.")
else:
token = tokens.popleft()
if token == "+":
return parse(tokens) + parse(tokens)
elif token == "-":
return parse(tokens) - parse(tokens)
elif token == "/":
return parse(tokens) / parse(tokens)
elif token == "*":
return parse(tokens) * parse(tokens)
elif token == "%":
return parse(tokens) % parse(tokens)
elif token == "max":
return max(parse(tokens), parse(tokens))
elif token == "min":
return min(parse(tokens), parse(tokens))
else:
return token
def mathOp(line, tline, i, rowNum):
op = []
while i < len(line):
if line[i] == "SUM OF":
op.append("+")
i += 1
elif line[i] == "DIFF OF":
op.append("-")
i += 1
elif line[i] == "PRODUKT OF":
op.append("*")
i += 1
elif line[i] == "QUOSHUNT OF":
op.append("/")
i += 1
elif line[i] == "MOD OF":
op.append("%")
i += 1
elif line[i] == "BIGGR OF":
op.append("max")
i += 1
elif line[i] == "SMALLR OF":
op.append("min")
i += 1
else:
if tline[i] == "NUMBR":
op.append(int(line[i]))
i += 1
elif tline[i] == "NUMBAR":
op.append(float(line[i]))
i += 1
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
op.append([type, value])
i += 1
elif tline[i] == "YARN":
value = typeCasting(line[i], tline[i], "NUMBAR", rowNum)
op.append(value)
i += 1
elif tline[i] == "AN":
i += 1
else:
raise RuntimeError("Unexpected %r at line %d" % (line[i], rowNum))
i += 1
return parse(deque(op))
def boolOp(line, tline, i, rowNum):
if tline[i] == "BOOL_OPER":
opAddress = i
boolQ = []
i += 1
i, boolQ0 = boolOp(line, tline, i, rowNum)
boolQ.append(boolQ0)
if line[opAddress] == "NOT":
if boolQ[0] == "WIN":
return i, "FAIL"
else:
return i, "WIN"
i += 1
if tline[i] != "AN":
raise RuntimeError("Expected AN at line %d" % (rowNum))
i += 1
i, boolQ1 = boolOp(line, tline, i, rowNum)
boolQ.append(boolQ1)
# print(boolQ)
if line[opAddress] == "BOTH OF":
if boolQ[0] == "WIN" and boolQ[1] == "WIN":
return i, "WIN"
else:
return i, "FAIL"
elif line[opAddress] == "EITHER OF":
if boolQ[0] == "WIN" or boolQ[1] == "WIN":
return i, "WIN"
else:
return i, "FAIL"
elif line[opAddress] == "WON OF":
if boolQ[0] != boolQ[1] and (boolQ[0] == "WIN" or boolQ[1] == "WIN"):
return i, "WIN"
else:
return i, "FAIL"
elif tline[i] == "VARIABLE":
if i < len(line) - 1:
line[i] = line[i][:-1]
value, type = searchVarValue(line[i])
if type != "TROOF":
value = typeCasting(value, type, "TROOF", rowNum)
return i, value
elif tline[i] == "TROOF":
return i, line[i]
else:
raise RuntimeError("Unexpected %r at line %d" % (line[i], rowNum))
def boolOpRegion(line, tline, i, rowNum):
# print(line)
if line[i] == "ALL OF" or line[i] == "ANY OF":
if line[i] == "ALL OF":
initCond = "WIN"
terminateCond = "WIN"
elif line[i] == "ANY OF":
terminateCond = "FAIL"
initCond = "FAIL"
i += 1
while i < len(line) and initCond == terminateCond:
initCond = boolOp(line, tline, i, rowNum)[1]
# print(initCond, terminateCond)
i += 1
if line[i] == "AN":
i += 1
else:
raise RuntimeError("Expected AN at line %d" % (rowNum))
if line[i] == "MKAY":
break
return initCond
else:
return boolOp(line, tline, i, rowNum)[1]
def printLine(line, tline):
# assume muna na YARN lang ung priniprint
string = ""
for i in range(0, len(line)):
if tline[i] != "PRINT" and tline[i] != "COMMENT":
if tline[i] == "YARN":
string = string + line[i][1:-1]
elif tline[i] == "VARIABLE":
value, type = searchVarValue(line[i])
if type != "YARN":
value = typeCasting(value, type, "YARN", i)
else:
value = value[1:-1]
string = string + value
elif tline[i] == "NUMBR" or tline[i] == "NUMBAR":
value = typeCasting(line[i], tline[i], "YARN", i)
string = string + value
elif tline[i] == "TROOF":
value = line[i]
string = string + value
else:
raise RuntimeError("Type %r cannot be printed" % (tline[i]))
print(string)
def searchVarValue(name):
global vars
for variable in vars:
if variable.name == name:
return variable.value, variable.dataType
raise RuntimeError("Variable %r does not exist" % (name))
def typeCasting(value, type1, type2, rowNum):
if type1 == "NOOB":
if type2 == "TROOF":
return False
else:
raise RuntimeError(
"Encountered error in line %d, cannot typecast NOOB to %r"
% (rowNum, type2)
)
elif type1 == "NUMBR" or type1 == "NUMBAR":
match type2:
case "NUMBAR":
return float(value)
case "NUMBR":
return int(value)
case "YARN":
return str(value)
case "TROOF":
if value == 0:
return "FAIL"
else:
return "WIN"
case _:
raise RuntimeError(
"Encountered error in line %d, cannot typecast NUMBR to %r"
% (rowNum, type2)
)
elif type1 == "TROOF":
match type2:
case "NUMBAR":
if value == "WIN":
return 1.0
else:
return 0
case "NUMBR":
if value == "WIN":
return 1
else:
return 0
case "YARN":
return value
case _:
raise RuntimeError(
"Encoutnered error in line %d, cannot typecast TROOF to %r"
% (rowNum, type2)
)
elif type1 == "YARN":
value = value[1:-1]
match type2:
case "NUMBR":
if bool(re.search(r"-?\d(\d)*", value)):
return int(value)
else:
raise RuntimeError(
"Encountered error in line %d, cannot typecast YARN to %r"
% (rowNum, type2)
)
case "NUMBAR":
if bool(re.search(r"-?\d(\d)*\.\d(\d)*", value)):
return float(value)
else:
raise RuntimeError(
"Encountered error in line %d, cannot typecast YARN to %r"
% (rowNum, type2)
)
case "TROOF":
if value == "":
return "FAIL"
else:
return "WIN"
case _:
raise RuntimeError(
"Encountered error in line %d, cannot typecast YARN to %r"
% (rowNum, type2)
)
def printVariables():
global vars
for variable in vars:
print(variable.name)
print(variable.dataType)
print(variable.value)
print("")