languages_and_translators/final_lang/fort.py

999 lines
24 KiB
Python
Raw Normal View History

2019-03-21 14:52:07 -06:00
import ply.lex as lex
2019-03-21 18:38:52 -06:00
import ply.yacc as yacc
import sys
2019-04-22 14:47:49 -05:00
# Ignore unresolved import error if present.
from typeValidation import resultingType
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# --------------------------------Globals-------------------------------------
# ----------------------------------------------------------------------------
2019-04-12 05:55:09 +00:00
2019-04-22 14:47:49 -05:00
kEqualityOperators = ['>', '<', '>=', '<=', '==', '/=', ]
resultQuadruplets = []
# The first quadruplet will be line 1, that way it will match the lines in
# the editor and will be easier to analyze.
quadrupletIndex = 1
# Auxiliary stacks.
operandsStack = []
operatorsStack = []
2019-04-11 23:46:23 +00:00
typesStack = []
jumpsStack = []
2019-04-11 23:46:23 +00:00
exitsStack = []
avail = []
for i in range(200):
avail.append('$' + str(i))
2019-03-21 18:38:52 -06:00
2019-04-04 23:05:36 +00:00
# Operations related to the table of symbols
symbols = {}
# Our variables start at direction 50, the temps take the first 49 directions.
currentIndex = 200
2019-04-04 23:05:36 +00:00
# Multi dimensional variables dimensions just for declaration.
globalDimension1 = 0
globalDimension2 = 0
globalDimensionalSize = 1
# Multi dimensional variables dimensions just for accessing.
globalIndex1 = 0
globalIndex2 = 0
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# ------------------------------Util methods----------------------------------
# ----------------------------------------------------------------------------
2019-04-12 05:55:09 +00:00
# Adds a symbol to the symbols table.
2019-04-22 14:47:49 -05:00
def addSymbol(name, symbolType, value=0):
global currentIndex
symbols[name] = {
2019-04-11 23:46:23 +00:00
'type': symbolType,
2019-04-30 09:54:10 -05:00
'value': value,
'direction': currentIndex,
'dimension1': globalDimension1,
'dimension2': globalDimension2,
}
currentIndex += globalDimensionalSize
# Returns the last item of a list without deleting it.
2019-04-22 14:47:49 -05:00
def peek(list):
if (len(list) == 0):
return None
return list[len(list) - 1]
2019-04-04 23:05:36 +00:00
# Checks whether or not a an operand is a temp variable.
2019-04-22 14:47:49 -05:00
def isTemp(operand):
if type(operand) is not str:
return False
operand = int(operand[1:])
if (operand < 50):
return True
return False
2019-04-22 14:47:49 -05:00
def isDirection(operand):
if type(operand) is not str:
return False
if "$" in operand or "*" in operand:
return True
return False
2019-04-12 05:55:09 +00:00
def fillGoto(position, fillValue):
global resultQuadruplets
# Using position - 1 because the quadruplets start at 1 and not 0.
2019-04-22 14:47:49 -05:00
resultQuadruplets[position-1] = resultQuadruplets[position -
1].replace('_', str(fillValue))
2019-04-12 05:55:09 +00:00
return
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# ---------------------------------LEXER--------------------------------------
# ----------------------------------------------------------------------------
2019-04-12 05:55:09 +00:00
2019-03-21 18:38:52 -06:00
tokens = [
'doubleColon',
'coma',
'openBra',
'closedBra',
'int',
'rea',
'parens',
'openParen',
'closedParen',
'string',
'plus',
'minus',
'mul',
'div',
'or',
'and',
'not',
'equals',
'doubleEquals',
'notEquals',
'less',
'more',
'lessEquals',
'moreEquals',
2019-03-21 21:09:36 -06:00
'id',
2019-03-21 21:39:07 -06:00
'program',
2019-04-29 17:56:14 -05:00
'endline',
2019-03-21 21:39:07 -06:00
'end',
'read',
'print',
'if',
'then',
'else',
'elif',
'do',
'swap',
'exit',
'integer',
'real',
'subroutine',
2019-03-21 20:20:55 -06:00
]
2019-03-21 21:39:07 -06:00
reserved = {
2019-04-22 14:47:49 -05:00
'program': 'program',
2019-04-29 17:56:14 -05:00
'endline': 'endline',
2019-04-22 14:47:49 -05:00
'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',
2019-03-21 21:39:07 -06:00
}
2019-03-21 20:20:55 -06:00
2019-03-21 21:09:36 -06:00
t_doubleColon = r'::'
t_coma = r','
t_openBra = r'\['
t_closedBra = r'\]'
t_parens = r'\(\)'
t_openParen = r'\('
t_closedParen = r'\)'
2019-03-21 20:20:55 -06:00
t_plus = r'\+'
t_minus = r'-'
t_mul = r'\*'
2019-04-29 17:56:14 -05:00
t_string = r'\'[a-zA-Z0-9 \?\:\t\r\n\f()\[\]\&\!\@\#\$\%\^\-\=\+\/\,]*\''
2019-03-21 21:39:07 -06:00
t_or = r'\.or\.'
t_and = r'\.and\.'
t_not = r'\.not\.'
t_doubleEquals = r'\=\='
t_equals = r'\='
t_notEquals = r'\/\='
t_div = r'\/'
t_lessEquals = r'\<\='
t_less = r'\<'
t_moreEquals = r'\>\='
t_more = r'\>'
t_ignore = ' \t\r\n\f\v'
2019-03-21 20:20:55 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def t_rea(t):
r'\d+\.\d+'
t.value = float(t.value)
return t
2019-04-22 14:47:49 -05:00
def t_int(t):
r'\d+'
t.value = int(t.value)
return t
2019-03-21 20:20:55 -06:00
def t_id(t):
2019-03-21 21:09:36 -06:00
r'[a-zA-Z_][a-zA-Z_0-9]*'
2019-03-21 21:39:07 -06:00
if t.value in reserved:
2019-04-22 14:47:49 -05:00
t.type = reserved[t.value]
else:
2019-03-21 21:39:07 -06:00
t.type = 'id'
2019-03-21 20:20:55 -06:00
return t
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def t_error(t):
print("Illegal character!")
2019-03-21 22:59:22 -06:00
print(t)
2019-03-21 20:20:55 -06:00
t.lexer.skip(1)
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
lexer = lex.lex()
2019-04-12 05:55:09 +00:00
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# ---------------------------------PARSER-------------------------------------
# ----------------------------------------------------------------------------
2019-04-12 05:55:09 +00:00
2019-03-21 20:20:55 -06:00
def p_programa(p):
'''
2019-04-30 09:54:10 -05:00
programa : program action_37 id V F action_38 B end program
2019-04-22 14:47:49 -05:00
'''
print('+++ Valid program')
2019-03-21 20:20:55 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_V(p):
'''
V : V Tipo Dim doubleColon Rid action_addSymbols action_32
2019-03-21 20:20:55 -06:00
|
'''
2019-04-04 23:05:36 +00:00
2019-03-21 20:20:55 -06:00
def p_Rid(p):
'''
Rid : id
| Rid coma id
'''
2019-04-04 23:05:36 +00:00
# p[0] will contain an list with all the variable
# names for this production in string format.
if (len(p) == 2):
p[0] = [p[1]]
else:
p[0] = p[1] + [p[3]]
2019-03-21 20:20:55 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_Tipo(p):
'''
Tipo : integer
| real
'''
2019-04-04 23:05:36 +00:00
# p[0] will contain the type in string format
p[0] = p[1]
2019-03-21 20:20:55 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_Dim(p):
'''
Dim : openBra int action_30 closedBra
| openBra int action_30 closedBra openBra int action_31 closedBra
2019-03-21 20:20:55 -06:00
|
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_F(p):
'''
2019-04-30 09:54:10 -05:00
F : F subroutine id action_39 B end subroutine action_40
2019-03-21 20:20:55 -06:00
|
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_B(p):
'''
B : B S
|
'''
2019-04-29 17:56:14 -05:00
2019-03-21 20:20:55 -06:00
def p_S(p):
'''
2019-04-30 09:54:10 -05:00
S : Dimensional equals EA action_8
| id parens action_41
2019-03-21 20:20:55 -06:00
| read RDimensional
2019-04-29 17:56:14 -05:00
| print RDimOrString
| if action_16 Relif ElseOrEmpty end if action_20
| do id action_24 equals EA action_25 coma EA action_26 IntOrEmpty then B action_29 end do
| do then action_21 B action_22 end do
2019-03-21 20:20:55 -06:00
| swap Dimensional coma Dimensional
| exit action_23
2019-03-21 20:20:55 -06:00
'''
# Adjust the action to support matrices
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_Dimensional(p):
'''
2019-04-30 09:54:10 -05:00
Dimensional : id DimensionsOrEmpty action_1
2019-03-21 20:20:55 -06:00
'''
p[0] = p[1]
2019-03-21 20:20:55 -06:00
def p_DimensionsOrEmpty(p):
'''
DimensionsOrEmpty : openParen EA action_setDim1 ComaEAOrEmpty closedParen
2019-03-21 20:20:55 -06:00
|
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_ComaEAOrEmpty(p):
'''
ComaEAOrEmpty : coma EA action_setDim2
2019-03-21 20:20:55 -06:00
|
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_RDimensional(p):
'''
2019-04-30 09:54:10 -05:00
RDimensional : Dimensional action_36
| RDimensional coma Dimensional action_36
2019-03-21 20:20:55 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_RDimOrString(p):
'''
RDimOrString : DimOrString
| RDimOrString coma DimOrString
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_DimOrString(p):
'''
2019-04-30 09:54:10 -05:00
DimOrString : Dimensional action_33
| string action_34
2019-04-29 17:56:14 -05:00
| endline action_34
2019-03-21 20:20:55 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_Relif(p):
'''
Relif : openParen EL closedParen action_17 then B
| Relif elif action_18 openParen EL closedParen action_17 then B
2019-03-21 20:20:55 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_ElseOrEmpty(p):
'''
ElseOrEmpty : else action_19 B
2019-03-21 20:20:55 -06:00
|
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_IntOrEmpty(p):
'''
IntOrEmpty : coma int action_28
| action_27
2019-03-21 20:20:55 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 20:20:55 -06:00
def p_EA(p):
'''
EA : MultDiv
| EA SumOrSub action_3 MultDiv action_4
2019-03-21 20:20:55 -06:00
'''
2019-03-21 20:20:55 -06:00
def p_SumOrSub(p):
'''
SumOrSub : plus
| minus
'''
p[0] = p[1]
2019-03-21 21:09:36 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_MultDiv(p):
'''
MultDiv : EAParens
| MultDiv MDSymbols action_5 EAParens action_6
2019-03-21 21:09:36 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_MDSymbols(p):
'''
MDSymbols : mul
| div
'''
p[0] = p[1]
2019-03-21 21:09:36 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_EAParens(p):
'''
EAParens : EItem
| openParen EA closedParen
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_EL(p):
'''
EL : AND
| EL or action_10 AND action_9
2019-03-21 21:09:36 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_AND(p):
'''
AND : Equality
| AND and action_12 Equality action_11
2019-03-21 21:09:36 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_Equality(p):
'''
Equality : EItem EQSymbols action_13 EItem action_14
2019-03-21 21:09:36 -06:00
| openParen EL closedParen
| not EL action_15
2019-03-21 21:09:36 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_EItem(p):
'''
2019-04-30 09:54:10 -05:00
EItem : Dimensional
| int action_2
| rea action_2_rea
2019-03-21 21:09:36 -06:00
'''
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
def p_EQSymbols(p):
'''
EQSymbols : less
| more
| doubleEquals
| notEquals
| lessEquals
| moreEquals
'''
p[0] = p[1]
2019-03-21 21:09:36 -06:00
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# -----------------------------PARSER ACTIONS---------------------------------
# ----------------------------------------------------------------------------
2019-04-29 17:56:14 -05:00
def p_action_addSymbols(p):
"action_addSymbols :"
for name in p[-1]:
addSymbol(name, p[-4])
def p_action_1(p):
"action_1 :"
global globalIndex1
global globalIndex2
global quadrupletIndex
global resultQuadruplets
global avail
2019-04-30 09:54:10 -05:00
if p[-2] not in symbols:
raise Exception(f'The variable {p[-2]} was not declared')
direction = symbols[p[-2]]['direction']
dimension1 = symbols[p[-2]]['dimension1']
dimension2 = symbols[p[-2]]['dimension2']
if dimension2 is not 0:
indirectPointer = avail.pop(0)
if isDirection(globalIndex1) or isDirection(globalIndex2):
2019-04-29 17:56:14 -05:00
resultQuadruplets.append(
f'* {globalIndex1} {dimension1} {indirectPointer}\n')
quadrupletIndex += 1
2019-04-29 17:56:14 -05:00
resultQuadruplets.append(
f'+ {globalIndex2} {indirectPointer} {indirectPointer}\n')
quadrupletIndex += 1
2019-04-29 17:56:14 -05:00
resultQuadruplets.append(
f'+ {direction} {indirectPointer} {indirectPointer}\n')
quadrupletIndex += 1
operandsStack.append(indirectPointer.replace('$', '*'))
else:
direction += globalIndex2 + (globalIndex1 * dimension1)
operandsStack.append(f'${direction}')
2019-04-30 09:54:10 -05:00
globalIndex1 = 0
globalIndex2 = 0
elif dimension1 is not 0:
indirectPointer = avail.pop(0)
if isDirection(globalIndex1):
2019-04-29 17:56:14 -05:00
resultQuadruplets.append(
f'+ {direction} {globalIndex1} {indirectPointer}\n')
quadrupletIndex += 1
operandsStack.append(indirectPointer.replace('$', '*'))
else:
direction += globalIndex1
operandsStack.append(f'${direction}')
2019-04-30 09:54:10 -05:00
globalIndex1 = 0
else:
operandsStack.append(f'${direction}')
2019-04-30 09:54:10 -05:00
sType = symbols[p[-2]]['type']
2019-04-29 17:56:14 -05:00
# operandsStack.append(f'${direction}')
typesStack.append(sType)
def p_action_2(p):
"action_2 :"
operandsStack.append(p[-1])
typesStack.append('integer')
2019-04-22 14:47:49 -05:00
def p_action_2_rea(p):
"action_2_rea :"
operandsStack.append(p[-1])
typesStack.append('real')
2019-04-22 14:47:49 -05:00
def p_action_3(p):
"action_3 :"
operatorsStack.append(p[-1])
2019-04-22 14:47:49 -05:00
def p_action_4(p):
"action_4 :"
if (peek(operatorsStack) == '+' or peek(operatorsStack) == '-'):
global quadrupletIndex
global avail
operator = operatorsStack.pop()
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
resultType = resultingType(operator, type1, type2)
temp = avail.pop(0)
operandsStack.append(temp)
typesStack.append(resultType)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append(str(
operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_5(p):
"action_5 :"
operatorsStack.append(p[-1])
def p_action_6(p):
"action_6 :"
if (peek(operatorsStack) == '*' or peek(operatorsStack) == '/'):
global quadrupletIndex
global avail
operator = operatorsStack.pop()
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
resultType = resultingType(operator, type1, type2)
temp = avail.pop(0)
operandsStack.append(temp)
typesStack.append(resultType)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append(str(
operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_8(p):
"action_8 :"
global quadrupletIndex
global avail
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
# Result type only gets called to make sure the types are compatible.
resultingType('=', type1, type2)
2019-04-22 14:47:49 -05:00
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.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
2019-04-22 14:47:49 -05:00
def p_action_9(p):
"action_9 :"
if (peek(operatorsStack) == '.or.'):
global quadrupletIndex
global avail
operator = operatorsStack.pop()
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
resultType = resultingType(operator, type1, type2)
temp = avail.pop(0)
operandsStack.append(temp)
typesStack.append(resultType)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append(str(
operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_10(p):
"action_10 :"
operatorsStack.append(p[-1])
def p_action_11(p):
"action_11 :"
if (peek(operatorsStack) == '.and.'):
global quadrupletIndex
global avail
operator = operatorsStack.pop()
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
resultType = resultingType(operator, type1, type2)
temp = avail.pop(0)
operandsStack.append(temp)
typesStack.append(resultType)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append(str(
operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_12(p):
"action_12 :"
operatorsStack.append(p[-1])
def p_action_13(p):
"action_13 :"
operatorsStack.append(p[-1])
def p_action_14(p):
"action_14 :"
if (peek(operatorsStack) in kEqualityOperators):
global quadrupletIndex
global avail
operator = operatorsStack.pop()
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
resultType = resultingType(operator, type1, type2)
temp = avail.pop(0)
operandsStack.append(temp)
typesStack.append(resultType)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append(str(
operator) + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_15(p):
"action_15 :"
if (peek(typesStack) is not 'bool'):
raise Exception("Cannot use .not. with non boolean")
global quadrupletIndex
# It is not necessary to pop the types stack since the result will also
# be bool.
operand1 = operandsStack.pop()
temp = avail.pop(0)
operandsStack.append(temp)
2019-04-22 14:47:49 -05:00
resultQuadruplets.append('.not. ' + str(operand1) +
' ' + str(temp) + '\n')
quadrupletIndex += 1
def p_action_16(p):
"action_16 :"
jumpsStack.append('$')
2019-04-22 14:47:49 -05:00
def p_action_17(p):
"action_17 :"
global quadrupletIndex
global avail
operand1 = operandsStack.pop()
type1 = typesStack.pop()
if (type1 is not 'bool'):
2019-04-22 14:47:49 -05:00
raise Exception(
'Can\'t use non logical expression as conditional for if')
jumpsStack.append(quadrupletIndex)
resultQuadruplets.append('gotoF ' + str(operand1) + ' _\n')
quadrupletIndex += 1
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_18(p):
"action_18 :"
global quadrupletIndex
resultQuadruplets.append('goto _\n')
quadrupletIndex += 1
Dir = jumpsStack.pop()
fillGoto(Dir, quadrupletIndex)
jumpsStack.append(quadrupletIndex - 1)
def p_action_19(p):
"action_19 :"
global quadrupletIndex
resultQuadruplets.append('goto _\n')
quadrupletIndex += 1
Dir = jumpsStack.pop()
fillGoto(Dir, quadrupletIndex)
jumpsStack.append(quadrupletIndex - 1)
def p_action_20(p):
"action_20 :"
while(peek(jumpsStack) is not '$'):
Dir = jumpsStack.pop()
fillGoto(Dir, quadrupletIndex)
jumpsStack.pop()
def p_action_21(p):
"action_21 :"
jumpsStack.append(quadrupletIndex)
exitsStack.append('$')
def p_action_22(p):
"action_22 :"
global resultQuadruplets
global quadrupletIndex
Dir = jumpsStack.pop()
resultQuadruplets.append(f'goto {Dir}\n')
quadrupletIndex += 1
while(peek(exitsStack) != '$'):
Dir = exitsStack.pop()
fillGoto(Dir, quadrupletIndex)
exitsStack.pop()
def p_action_23(p):
"action_23 :"
global quadrupletIndex
global quadrupletIndex
exitsStack.append(quadrupletIndex)
resultQuadruplets.append('goto _\n')
quadrupletIndex += 1
def p_action_24(p):
"action_24 :"
if p[-1] not in symbols:
raise Exception(f'The variable {p[-1]} was not declared')
direction = symbols[p[-1]]['direction']
sType = symbols[p[-1]]['type']
operandsStack.append(f'${direction}')
operandsStack.append(f'${direction}')
operandsStack.append(f'${direction}')
typesStack.append(sType)
typesStack.append(sType)
typesStack.append(sType)
def p_action_25(p):
"action_25 :"
global quadrupletIndex
global avail
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
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')
quadrupletIndex += 1
# Return the operand to the availbale if it is a temporal.
if (isTemp(operand2)):
avail = [operand2.replace('*', '$')] + avail
def p_action_26(p):
"action_26 :"
global quadrupletIndex
global avail
operand2 = operandsStack.pop()
operand1 = operandsStack.pop()
type2 = typesStack.pop()
type1 = typesStack.pop()
# call function just to make sure types are compatible
resultingType('<=', type1, type2)
temp = avail.pop(0)
# push to the jumps stack so the program can return to this quadruplet after each cycle.
jumpsStack.append(quadrupletIndex)
resultQuadruplets.append(
'<=' + ' ' + str(operand1) + ' ' + str(operand2) + ' ' + str(temp) + '\n')
quadrupletIndex += 1
# push to the jumps stack so this gotoF can be filled later.
jumpsStack.append(quadrupletIndex)
resultQuadruplets.append(f'gotoF {str(temp)} _\n')
quadrupletIndex += 1
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_27(p):
"action_27 :"
operandsStack.append("1")
typesStack.append("integer")
def p_action_28(p):
"action_28 :"
operandsStack.append(p[-1])
typesStack.append("integer")
def p_action_29(p):
"action_29 :"
global quadrupletIndex
global avail
incrementOperand = operandsStack.pop()
counterOperand = operandsStack.pop()
incrementType = typesStack.pop()
counterType = typesStack.pop()
temp = avail.pop(0)
# function call just to make sure that the types are compatible
resultingType('+', counterType, incrementType)
resultQuadruplets.append(f'+ {counterOperand} {incrementOperand} {temp}\n')
quadrupletIndex += 1
resultQuadruplets.append(f'= {temp} {counterOperand}\n')
quadrupletIndex += 1
# return the temp used to the avail vector
avail = [temp] + avail
gotoFPosition = jumpsStack.pop()
conditionPosition = jumpsStack.pop()
resultQuadruplets.append(f'goto {conditionPosition}\n')
quadrupletIndex += 1
fillGoto(gotoFPosition, quadrupletIndex)
2019-04-29 17:56:14 -05:00
def p_action_30(p):
"action_30 :"
global globalDimension1
global globalDimensionalSize
globalDimension1 = p[-1]
globalDimensionalSize *= p[-1]
def p_action_31(p):
"action_31 :"
global globalDimension2
global globalDimensionalSize
globalDimension2 = p[-1]
globalDimensionalSize *= p[-1]
2019-04-29 17:56:14 -05:00
def p_action_32(p):
"action_32 :"
global globalDimension1
global globalDimension2
global globalDimensionalSize
globalDimension1 = 0
globalDimension2 = 0
globalDimensionalSize = 1
2019-04-29 17:56:14 -05:00
def p_action_33(p):
"action_33 :"
global quadrupletIndex
global avail
operand1 = operandsStack.pop()
typesStack.pop()
resultQuadruplets.append(f'print {operand1}\n')
quadrupletIndex += 1
if (isTemp(operand1)):
avail = [operand1.replace('*', '$')] + avail
def p_action_34(p):
"action_34 :"
global quadrupletIndex
resultQuadruplets.append(f'print {p[-1]}\n')
quadrupletIndex += 1
2019-04-29 17:56:14 -05:00
def p_action_36(p):
"action_36 :"
global quadrupletIndex
2019-04-29 17:56:14 -05:00
operand1 = operandsStack.pop()
2019-04-30 09:54:10 -05:00
typesStack.pop()
2019-04-29 17:56:14 -05:00
resultQuadruplets.append(f'read {operand1}\n')
quadrupletIndex += 1
2019-04-30 09:54:10 -05:00
def p_action_37(p):
"action_37 :"
global quadrupletIndex
resultQuadruplets.append('goto _\n')
quadrupletIndex += 1
def p_action_38(p):
"action_38 :"
global quadrupletIndex
fillGoto(1, quadrupletIndex)
def p_action_39(p):
"action_39 :"
global quadrupletIndex
subroutineId = p[-1]
addSymbol(subroutineId, 'method', quadrupletIndex)
def p_action_40(p):
"action_40 :"
global quadrupletIndex
resultQuadruplets.append('goback\n')
quadrupletIndex += 1
def p_action_41(p):
"action_41 :"
global quadrupletIndex
if p[-2] not in symbols:
raise Exception(f'The variable {p[-2]} was not declared')
if symbols[p[-2]]['type'] is not 'method':
raise Exception(f'{p[-2]} is not a function')
value = symbols[p[-2]]['value']
resultQuadruplets.append(f'call {value}\n')
quadrupletIndex += 1
def p_action_setDim1(p):
"action_setDim1 :"
global globalIndex1
operand1 = operandsStack.pop()
type1 = typesStack.pop()
if (type1 == 'integer'):
globalIndex1 = operand1
else:
raise Exception("Cannot use floating point number as index")
def p_action_setDim2(p):
"action_setDim2 :"
global globalIndex2
operand1 = operandsStack.pop()
type1 = typesStack.pop()
if (type1 == 'integer'):
globalIndex2 = operand1
else:
raise Exception("Cannot use floating point number as index")
2019-03-21 21:09:36 -06:00
def p_error(p):
print('XXX Invalid program')
2019-03-21 22:59:22 -06:00
print(p)
2019-03-21 21:09:36 -06:00
2019-04-22 14:47:49 -05:00
2019-03-21 21:09:36 -06:00
parser = yacc.yacc()
2019-04-12 05:55:09 +00:00
2019-04-22 14:47:49 -05:00
# ----------------------------------------------------------------------------
# --------------------INTERMEDIATE CODE FILE GENERATION-----------------------
# ----------------------------------------------------------------------------
2019-04-12 05:55:09 +00:00
if (len(sys.argv) > 1):
programName = sys.argv[1]
programFile = open(programName, "r")
resultFile = open(programName + '.out', "w+")
# This is neccessary because the read method parses literal ends
2019-04-04 23:05:36 +00:00
# of lines as \\n instead of \n.
program = programFile.read().replace('\\n', '\n')
parser.parse(program)
resultFile.writelines(resultQuadruplets)
# Close the files.
programFile.close()
resultFile.close()
else:
raise Exception('''
No file name was provided.
Please add the file name as a command line argument
Example: fort.py test.fort
''')