Finish main task, start refactoring

This commit is contained in:
Jan-Niclas Loosen
2025-11-20 15:10:38 +01:00
parent 622ecef369
commit eb362896fd
8 changed files with 1415 additions and 208 deletions

View File

@@ -1,45 +1,140 @@
# ------------------------------------------------------------
# triplayacc.py
#
# Yacc grammar of the TRIPLA language
''' Here an initial grammar
E -> while E do { E }
| CONST
CONST: Positive, integer numbers = 0 | [1-9][0-9]*
'''
# Note: For LALR(1) left recursion is preferred
# Grammar of the TRIPLA language
# ------------------------------------------------------------
import ply.yacc as yacc
import syntax as ast
# Get the token map from the lexer. This is required.
from triplalex import tokens
# Operator precedence
precedence = (
('left', 'COMP'),
('left', 'EQOP'),
('left', 'AOP'),
)
def p_expression_const(p):
'expression : CONST'
start = 'E'
# ------------------------------------------------------------
# Rules for E
# ------------------------------------------------------------
def p_E_let(p):
'E : LET D IN E'
p[0] = ast.LET(p[2], p[4])
def p_E_id(p):
'E : ID'
p[0] = ast.ID(p[1])
def p_E_call(p):
'E : ID LPAREN A RPAREN'
# E : ID(A)
p[0] = ast.CALL(p[1], p[3])
def p_E_aop(p):
'E : E AOP E'
p[0] = ast.AOP(p[2], p[1], p[3])
def p_E_paren(p):
'E : LPAREN E RPAREN'
# E : (E)
p[0] = p[2]
def p_E_const(p):
'E : CONST'
p[0] = ast.CONST(p[1])
def p_E_assign(p):
'E : ID ASSIGN E'
p[0] = ast.ASSIGN(ast.ID(p[1]), p[3])
def p_expression_while(p):
'expression : WHILE expression DO LBRACE expression RBRACE'
p[0] = ast.WHILE(p[2],p[5])
def p_E_seq(p):
'E : E SEMICOLON E'
p[0] = ast.SEQ(p[1], p[3])
#def p_empty(p):
# 'empty :'
# pass
def p_E_if(p):
'E : IF LPAREN B RPAREN THEN E ELSE E'
p[0] = ast.IF(p[3], p[6], p[8])
# Error rule for syntax errors
def p_E_while(p):
'E : WHILE LPAREN B RPAREN DO LBRACE E RBRACE'
p[0] = ast.WHILE(p[3], p[7])
# ------------------------------------------------------------
# Rules for A
# ------------------------------------------------------------
def p_A_single(p):
'A : E'
p[0] = [p[1]]
def p_A_multiple(p):
'A : A COMMA E'
p[0] = p[1] + [p[3]]
# ------------------------------------------------------------
# Rules for D
# ------------------------------------------------------------
def p_D_single(p):
'D : ID LPAREN V RPAREN LBRACE E RBRACE'
p[0] = ast.DECL(p[1], p[3], p[6])
def p_D_concat(p):
'D : D D'
p[0] = p[1] + [p[2]] if isinstance(p[1], list) else [p[1], p[2]]
# ------------------------------------------------------------
# Rules for V
# ------------------------------------------------------------
def p_V_single(p):
'V : ID'
p[0] = [p[1]]
def p_V_multiple(p):
'V : V COMMA ID'
p[0] = p[1] + [p[3]]
# ------------------------------------------------------------
# Rules for B
# ------------------------------------------------------------
def p_B_eqop_E(p):
'B : E EQOP E'
p[0] = ast.EQOP(p[2], p[1], p[3])
def p_B_comp(p):
'B : E COMP E'
p[0] = ast.COMP(p[2], p[1], p[3])
def p_B_eqop_B(p):
'B : B EQOP B'
p[0] = ast.EQOP(p[2], p[1], p[3])
def p_B_lop(p):
'B : B LOP B'
p[0] = ast.LOP(p[2], p[1], p[3])
def p_B_true(p):
'B : TRUE'
p[0] = ast.CONST(True)
def p_B_false(p):
'B : FALSE'
p[0] = ast.CONST(False)
def p_B_paren(p):
'B : LPAREN B RPAREN'
# B : (B)
p[0] = p[2]
# Error handling
def p_error(p):
print("Syntax error in input!")
if p:
print("Syntax error at token:", p.type, "value:", p.value)
else:
print("Syntax error at EOF")
# Build the parser
parser = yacc.yacc() # debug=True
parser = yacc.yacc()