# ------------------------------------------------------------ # Grammar of the TRIPLA language # ------------------------------------------------------------ import ply.yacc as yacc import syntax as ast from triplalex import tokens # Operator precedence precedence = ( ('left', 'COMP'), ('left', 'EQOP'), ('left', 'AOP'), ) 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_E_seq(p): 'E : E SEMICOLON E' p[0] = ast.SEQ(p[1], p[3]) def p_E_if(p): 'E : IF B THEN E ELSE E' p[0] = ast.IF(p[2], p[4], p[6]) def p_E_while(p): 'E : WHILE B DO LBRACE E RBRACE' p[0] = ast.WHILE(p[2], p[5]) # ------------------------------------------------------------ # 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] # ------------------------------------------------------------ # 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): if p: print("Syntax error at token:", p.type, "value:", p.value) else: print("Syntax error at EOF") parser = yacc.yacc()