diff --git a/.gitignore b/.gitignore index 894a44c..19c2d3a 100644 --- a/.gitignore +++ b/.gitignore @@ -102,3 +102,11 @@ venv.bak/ # mypy .mypy_cache/ + +# zip files +*.zip + +# vscode configuration +.vscode/ + +*.DS_Store diff --git a/final_lang/fort.py b/final_lang/fort.py index cd186e4..92789ab 100644 --- a/final_lang/fort.py +++ b/final_lang/fort.py @@ -1,13 +1,14 @@ import ply.lex as lex import ply.yacc as yacc import sys +# Ignore unresolved import error if present. from typeValidation import resultingType -#---------------------------------------------------------------------------- -#--------------------------------Globals------------------------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# --------------------------------Globals------------------------------------- +# ---------------------------------------------------------------------------- -kEqualityOperators = ['>', '<', '>=', '<=', '==', '/=',] +kEqualityOperators = ['>', '<', '>=', '<=', '==', '/=', ] resultQuadruplets = [] # The first quadruplet will be line 1, that way it will match the lines in @@ -29,11 +30,13 @@ symbols = {} # Our variables start at direction 50, the temps take the first 50 directions. currentIndex = 50 -#---------------------------------------------------------------------------- -#------------------------------Util methods---------------------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# ------------------------------Util methods---------------------------------- +# ---------------------------------------------------------------------------- # Adds a symbol to the symbols table. + + def addSymbol(name, symbolType): global currentIndex initialValue = 0 if symbolType == 'integer' else 0.0 @@ -45,12 +48,16 @@ def addSymbol(name, symbolType): currentIndex += 1 # Returns the last item of a list without deleting it. + + def peek(list): if (len(list) == 0): return None return list[len(list) - 1] # Checks whether or not a an operand is a temp variable. + + def isTemp(operand): if type(operand) is not str: return False @@ -59,15 +66,17 @@ def isTemp(operand): return True return False + def fillGoto(position, fillValue): global resultQuadruplets # Using position - 1 because the quadruplets start at 1 and not 0. - resultQuadruplets[position-1] = resultQuadruplets[position-1].replace('_', str(fillValue)) + resultQuadruplets[position-1] = resultQuadruplets[position - + 1].replace('_', str(fillValue)) return -#---------------------------------------------------------------------------- -#---------------------------------LEXER-------------------------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# ---------------------------------LEXER-------------------------------------- +# ---------------------------------------------------------------------------- tokens = [ @@ -113,20 +122,20 @@ tokens = [ ] reserved = { - 'program' : 'program', - 'end' : 'end', - 'read' : 'read', - 'print' : 'print', - 'if' : 'if', - 'then' : 'then', - 'else' : 'else', - 'elif' : 'elif', - 'do' : 'do', - 'swap' : 'swap', - 'exit' : 'exit', - 'integer' : 'integer', - 'real' : 'real', - 'subroutine' : 'subroutine', + 'program': 'program', + 'end': 'end', + 'read': 'read', + 'print': 'print', + 'if': 'if', + 'then': 'then', + 'else': 'else', + 'elif': 'elif', + 'do': 'do', + 'swap': 'swap', + 'exit': 'exit', + 'integer': 'integer', + 'real': 'real', + 'subroutine': 'subroutine', } t_doubleColon = r'::' @@ -153,11 +162,13 @@ t_moreEquals = r'\>\=' t_more = r'\>' t_ignore = ' \t\r\n\f\v' + def t_rea(t): r'\d+\.\d+' t.value = float(t.value) return t + def t_int(t): r'\d+' t.value = int(t.value) @@ -167,30 +178,33 @@ def t_int(t): def t_id(t): r'[a-zA-Z_][a-zA-Z_0-9]*' if t.value in reserved: - t.type = reserved[ t.value ] - else: + t.type = reserved[t.value] + else: t.type = 'id' return t + def t_error(t): print("Illegal character!") print(t) t.lexer.skip(1) + lexer = lex.lex() -#---------------------------------------------------------------------------- -#---------------------------------PARSER------------------------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# ---------------------------------PARSER------------------------------------- +# ---------------------------------------------------------------------------- def p_programa(p): ''' programa : program id V F B end program - ''' + ''' print('+++ Valid program') + def p_V(p): ''' V : V Tipo Dim doubleColon Rid @@ -215,6 +229,7 @@ def p_Rid(p): else: p[0] = p[1] + [p[3]] + def p_Tipo(p): ''' Tipo : integer @@ -223,6 +238,7 @@ def p_Tipo(p): # p[0] will contain the type in string format p[0] = p[1] + def p_Dim(p): ''' Dim : openBra int closedBra @@ -230,18 +246,21 @@ def p_Dim(p): | ''' + def p_F(p): ''' F : F subroutine id B end subroutine | ''' + def p_B(p): ''' B : B S | ''' + def p_S(p): ''' S : Dimensional action_7 equals EA action_8 @@ -256,6 +275,8 @@ def p_S(p): ''' # Adjust the action to support matrices + + def p_Dimensional(p): ''' Dimensional : id DimensionsOrEmpty @@ -269,48 +290,56 @@ def p_DimensionsOrEmpty(p): | ''' + def p_ComaEAOrEmpty(p): ''' ComaEAOrEmpty : coma EA | ''' + def p_RDimensional(p): ''' RDimensional : Dimensional | RDimensional coma Dimensional ''' + def p_RDimOrString(p): ''' RDimOrString : DimOrString | RDimOrString coma DimOrString ''' + def p_DimOrString(p): ''' DimOrString : Dimensional | string ''' + def p_Relif(p): ''' Relif : openParen EL closedParen action_17 then B | Relif elif action_18 openParen EL closedParen action_17 then B ''' + def p_ElseOrEmpty(p): ''' ElseOrEmpty : else action_19 B | ''' + def p_IntOrEmpty(p): ''' IntOrEmpty : coma int | ''' + def p_EA(p): ''' EA : MultDiv @@ -325,12 +354,14 @@ def p_SumOrSub(p): ''' p[0] = p[1] + def p_MultDiv(p): ''' MultDiv : EAParens | MultDiv MDSymbols action_5 EAParens action_6 ''' + def p_MDSymbols(p): ''' MDSymbols : mul @@ -338,24 +369,28 @@ def p_MDSymbols(p): ''' p[0] = p[1] + def p_EAParens(p): ''' EAParens : EItem | openParen EA closedParen ''' + def p_EL(p): ''' EL : AND | EL or action_10 AND action_9 ''' + def p_AND(p): ''' AND : Equality | AND and action_12 Equality action_11 ''' + def p_Equality(p): ''' Equality : EItem EQSymbols action_13 EItem action_14 @@ -363,6 +398,7 @@ def p_Equality(p): | not EL action_15 ''' + def p_EItem(p): ''' EItem : Dimensional action_1 @@ -370,6 +406,7 @@ def p_EItem(p): | rea action_2_rea ''' + def p_EQSymbols(p): ''' EQSymbols : less @@ -381,9 +418,10 @@ def p_EQSymbols(p): ''' p[0] = p[1] -#---------------------------------------------------------------------------- -#-----------------------------PARSER ACTIONS--------------------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# -----------------------------PARSER ACTIONS--------------------------------- +# ---------------------------------------------------------------------------- + def p_action_1(p): "action_1 :" @@ -400,15 +438,18 @@ def p_action_2(p): operandsStack.append(p[-1]) typesStack.append('integer') + def p_action_2_rea(p): "action_2_rea :" operandsStack.append(p[-1]) typesStack.append('real') + def p_action_3(p): "action_3 :" operatorsStack.append(p[-1]) + def p_action_4(p): "action_4 :" if (peek(operatorsStack) == '+' or peek(operatorsStack) == '-'): @@ -423,7 +464,8 @@ def p_action_4(p): temp = avail.pop(0) operandsStack.append(temp) typesStack.append(resultType) - resultQuadruplets.append(str(operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') + resultQuadruplets.append(str( + operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') quadrupletIndex += 1 if (isTemp(operand2)): avail = [operand2] + avail @@ -450,7 +492,8 @@ def p_action_6(p): temp = avail.pop(0) operandsStack.append(temp) typesStack.append(resultType) - resultQuadruplets.append(str(operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') + resultQuadruplets.append(str( + operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') quadrupletIndex += 1 if (isTemp(operand2)): avail = [operand2] + avail @@ -458,7 +501,6 @@ def p_action_6(p): avail = [operand1] + avail - def p_action_7(p): "action_7 :" if p[-1] not in symbols: @@ -479,12 +521,14 @@ def p_action_8(p): type1 = typesStack.pop() # Result type only gets called to make sure the types are compatible. resultingType('=', type1, type2) - resultQuadruplets.append('= ' + str(operand2) + ' ' + str(operand1) + '\n') + resultQuadruplets.append('= ' + str(operand2) + + ' ' + str(operand1) + '\n') quadrupletIndex += 1 # Return the operand to the availbale if it is a temporal. if (isTemp(operand2)): avail = [operand2] + avail + def p_action_9(p): "action_9 :" if (peek(operatorsStack) == '.or.'): @@ -499,7 +543,8 @@ def p_action_9(p): temp = avail.pop(0) operandsStack.append(temp) typesStack.append(resultType) - resultQuadruplets.append(str(operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') + resultQuadruplets.append(str( + operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') quadrupletIndex += 1 if (isTemp(operand2)): avail = [operand2] + avail @@ -507,7 +552,6 @@ def p_action_9(p): avail = [operand1] + avail - def p_action_10(p): "action_10 :" operatorsStack.append(p[-1]) @@ -527,7 +571,8 @@ def p_action_11(p): temp = avail.pop(0) operandsStack.append(temp) typesStack.append(resultType) - resultQuadruplets.append(str(operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') + resultQuadruplets.append(str( + operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') quadrupletIndex += 1 if (isTemp(operand2)): avail = [operand2] + avail @@ -559,7 +604,8 @@ def p_action_14(p): temp = avail.pop(0) operandsStack.append(temp) typesStack.append(resultType) - resultQuadruplets.append(str(operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') + resultQuadruplets.append(str( + operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n') quadrupletIndex += 1 if (isTemp(operand2)): avail = [operand2] + avail @@ -573,13 +619,15 @@ def p_action_15(p): raise Exception("Cannot use .not. with non boolean") global quadrupletIndex operand1 = peek(operandsStack) - resultQuadruplets.append('.not. ' + str(operand1) + ' ' + str(operand1) + '\n') + resultQuadruplets.append('.not. ' + str(operand1) + + ' ' + str(operand1) + '\n') def p_action_16(p): "action_16 :" jumpsStack.append('$') + def p_action_17(p): "action_17 :" global quadrupletIndex @@ -587,7 +635,8 @@ def p_action_17(p): operand1 = operandsStack.pop() type1 = typesStack.pop() if (type1 is not 'bool'): - raise Exception('Can\'t use non logical expression as conditional for if') + raise Exception( + 'Can\'t use non logical expression as conditional for if') jumpsStack.append(quadrupletIndex) resultQuadruplets.append('gotoF ' + str(operand1) + ' _\n') quadrupletIndex += 1 @@ -651,17 +700,17 @@ def p_action_23(p): quadrupletIndex += 1 - def p_error(p): print('XXX Invalid program') print(p) + parser = yacc.yacc() -#---------------------------------------------------------------------------- -#--------------------INTERMEDIATE CODE FILE GENERATION----------------------- -#---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# --------------------INTERMEDIATE CODE FILE GENERATION----------------------- +# ---------------------------------------------------------------------------- if (len(sys.argv) > 1): programName = sys.argv[1] @@ -684,5 +733,3 @@ else: Example: fort.py test.fort ''') - -