diff --git a/Project-02-03-04/Source.gv.png b/Project-02-03-04/Source.gv.png new file mode 100644 index 0000000..ff30cc4 Binary files /dev/null and b/Project-02-03-04/Source.gv.png differ diff --git a/Project-02-03-04/cfg/CFG.py b/Project-02-03-04/cfg/CFG.py new file mode 100644 index 0000000..df059ea --- /dev/null +++ b/Project-02-03-04/cfg/CFG.py @@ -0,0 +1,48 @@ +from .CFG_Node import * + + +class CFG: + def __init__(self, in_node: CFG_Node, out_node: CFG_Node): + self.in_node = in_node + self.out_node = out_node + + def to_dot(self) -> str: + visited = set() + lines = ["digraph CFG {"] + + # optionale Defaults + lines.append(' node [fontname="Helvetica"];') + + def node_label(node: CFG_Node) -> str: + # Basislabel aus dem Knoten + base = node.dot_label() if hasattr(node, "dot_label") else "" + + # semantisches Label aus AST + if node.ast_node is not None: + semantic = str(node.ast_node) + return f"{base}\\n{semantic}" if base else semantic + + return base + + def node_shape(node: CFG_Node) -> str: + return node.dot_shape() if hasattr(node, "dot_shape") else "box" + + def visit(node: CFG_Node): + if node.id in visited: + return + visited.add(node.id) + + label = node_label(node) + shape = node_shape(node) + + lines.append( + f' n{node.id} [label="{label}", shape={shape}];' + ) + + for child in sorted(node.children, key=lambda n: n.id): + lines.append(f" n{node.id} -> n{child.id};") + visit(child) + + visit(self.in_node) + lines.append("}") + return "\n".join(lines) diff --git a/Project-02-03-04/cfg/CFG_Node.py b/Project-02-03-04/cfg/CFG_Node.py new file mode 100644 index 0000000..ca7aca3 --- /dev/null +++ b/Project-02-03-04/cfg/CFG_Node.py @@ -0,0 +1,67 @@ +class CFG_Node: + __counter = 1 + + def __init__(self, ast_node = None): + self.ast_node = ast_node + self.children = set() + self.parents = set() + + self.id = CFG_Node.__counter + CFG_Node.__counter += 1 + + def get_children(self): + return self.children + + def get_parents(self): + return self.parents + + def add_child(self, child: CFG_Node, propagate = True): + if propagate: + child.parents.add(self) + self.children.add(child) + + def add_parent(self, parent: CFG_Node, propagate = True): + if propagate: + parent.add_child(self) + self.parents.add(parent) + + def remove_child(self, child: CFG_Node, propagate = True): + if propagate: + child.parents.remove(self) + self.children.remove(child) + + def remove_parent(self, parent: CFG_Node, propagate = True): + if propagate: + parent.children.remove(self) + self.parents.remove(parent) + + +class CFG_START(CFG_Node): + def dot_shape(self): + return "circle" + + def dot_label(self): + return "START" + + +class CFG_END(CFG_Node): + def dot_shape(self): + return "doublecircle" + + def dot_label(self): + return "END" + + +class CFG_DIAMOND(CFG_Node): + def dot_shape(self): + return "diamond" + + +class CFG_CALL(CFG_Node): + def dot_shape(self): + return "box" + + +class CFG_RETURN(CFG_Node): + def dot_shape(self): + return "box" diff --git a/Project-02-03-04/helpers/__init__.py b/Project-02-03-04/cfg/__init__.py similarity index 100% rename from Project-02-03-04/helpers/__init__.py rename to Project-02-03-04/cfg/__init__.py diff --git a/Project-02-03-04/cfg_build.py b/Project-02-03-04/cfg_build.py new file mode 100644 index 0000000..1ef59dd --- /dev/null +++ b/Project-02-03-04/cfg_build.py @@ -0,0 +1,134 @@ +from cfg.CFG_Node import ( + CFG_Node, + CFG_CALL, + CFG_RETURN, + CFG_DIAMOND, +) + +import compiler +import syntax + + +# ------------------------------------------------- +# Expressions — NO CFG NODES +# ------------------------------------------------- + +class CONST(compiler.CONST): + def cfa(self, pred, end): + return pred + + +class ID(compiler.ID): + def cfa(self, pred, end): + return pred + + +class AOP(compiler.AOP): + def cfa(self, pred, end): + return pred + + +class COMP(compiler.COMP): + def cfa(self, pred, end): + return pred + + +class EQOP(compiler.EQOP): + def cfa(self, pred, end): + return pred + + +class LOP(compiler.LOP): + def cfa(self, pred, end): + return pred + + +# ------------------------------------------------- +# Statements +# ------------------------------------------------- + +class ASSIGN(compiler.ASSIGN): + def cfa(self, pred, end): + n = CFG_Node(self) + pred.add_child(n) + return n + + +class SEQ(compiler.SEQ): + def cfa(self, pred, end): + mid = self.exp1.cfa(pred, end) + if mid is None: + return None + return self.exp2.cfa(mid, end) + + +class IF(compiler.IF): + def cfa(self, pred, end): + cond = CFG_DIAMOND(self) + pred.add_child(cond) + + join = CFG_Node() + + then_end = self.exp1.cfa(cond, end) + else_end = self.exp2.cfa(cond, end) + + if then_end is not None: + then_end.add_child(join) + if else_end is not None: + else_end.add_child(join) + + return join + + +class WHILE(compiler.WHILE): + def cfa(self, pred, end): + cond = CFG_DIAMOND(self) + pred.add_child(cond) + + body_end = self.body.cfa(cond, end) + if body_end is not None: + body_end.add_child(cond) + + after = CFG_Node() + cond.add_child(after) + + return after + + +# ------------------------------------------------- +# Functions / calls +# ------------------------------------------------- + +class CALL(compiler.CALL): + def cfa(self, pred, end): + n = CFG_CALL(self) + pred.add_child(n) + return n + + +class DECL(compiler.DECL): + def cfa(self, pred, end): + entry = CFG_Node(self) + pred.add_child(entry) + return self.body.cfa(entry, end) + + +class LET(compiler.LET): + def cfa(self, pred, end): + current = pred + + decls = self.decl if isinstance(self.decl, list) else [self.decl] + for d in decls: + current = d.cfa(current, end) + if current is None: + return None + + return self.body.cfa(current, end) + + +class RETURN(syntax.EXPRESSION): + def cfa(self, pred, end): + n = CFG_RETURN(self) + pred.add_child(n) + n.add_child(end) # direct jump to global END + return None # no fallthrough diff --git a/Project-02-03-04/lib/__init__.py b/Project-02-03-04/lib/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/Project-02-03-04/helpers/console.py b/Project-02-03-04/lib/console.py similarity index 100% rename from Project-02-03-04/helpers/console.py rename to Project-02-03-04/lib/console.py diff --git a/Project-02-03-04/main.py b/Project-02-03-04/main.py index 58da03a..ad2bbc4 100644 --- a/Project-02-03-04/main.py +++ b/Project-02-03-04/main.py @@ -1,4 +1,5 @@ import triplayacc as yacc +import cfg_build import syntax from pathlib import Path @@ -10,9 +11,12 @@ from vistram.vistram import MachineUI import matplotlib.pyplot as plt import matplotlib.image as mpimg -import helpers.console as cnsl +import lib.console as cnsl import os +from cfg.CFG import CFG +from cfg.CFG_Node import (CFG_START, CFG_END) + import matplotlib matplotlib.use("TkAgg") @@ -21,6 +25,17 @@ def assemble(ast): code = ast.code({}, 0) return code + [halt()] +def make_cfg(ast): + start = CFG_START() + end = CFG_END() + + last = ast.cfa(start, end) + if last is not None: + last.add_child(end) + + return CFG(start, end) + + # Renders a diagram of the AST def render_diagram(dot_string: str): # Set DPI for PNG @@ -64,9 +79,9 @@ if __name__ == "__main__": print("\nTRIPLA Parser and TRIPLA to TRAM Compiler") while True: - mode = cnsl.prompt_choice("\nSelect action:", ["Parse .tripla", "Compile .tripla", "Exit"]) + mode = cnsl.prompt_choice("\nSelect action:", ["Parse .tripla", "Compile .tripla", "CFG for .tripla", "Exit"]) - if mode == 2: + if mode == 3: print("\nBye Bye.") break @@ -143,4 +158,26 @@ if __name__ == "__main__": ui.machine.reset() root.mainloop() + elif mode == 2: + cfg = make_cfg(ast) + + dot_str = cfg.to_dot() + if cnsl.prompt_confirmation("\nExport CFG as .dot file?"): + default = f"{path.stem}_cfg.dot" + filename = input(f"Filename [{default}]: ").strip() + if not filename: + filename = default + + out_path = Path(__file__).parent / filename + with open(out_path, "w") as f: + f.write(dot_str) + + print(f"Saved CFG DOT file as: {out_path}") + + if cnsl.prompt_confirmation("Display CFG diagram?"): + render_diagram(dot_str) + print("Rendered CFG diagram.") + + + diff --git a/Project-02-03-04/parser.out b/Project-02-03-04/parser.out index c11e96d..de0b1c9 100644 --- a/Project-02-03-04/parser.out +++ b/Project-02-03-04/parser.out @@ -781,6 +781,7 @@ state 38 (4) E -> E . AOP E (8) E -> E . SEMICOLON E + SEMICOLON reduce using rule 1 (E -> LET D IN E .) $end reduce using rule 1 (E -> LET D IN E .) RPAREN reduce using rule 1 (E -> LET D IN E .) EQOP reduce using rule 1 (E -> LET D IN E .) @@ -792,10 +793,9 @@ state 38 DO reduce using rule 1 (E -> LET D IN E .) RBRACE reduce using rule 1 (E -> LET D IN E .) AOP shift and go to state 8 - SEMICOLON shift and go to state 9 ! AOP [ reduce using rule 1 (E -> LET D IN E .) ] - ! SEMICOLON [ reduce using rule 1 (E -> LET D IN E .) ] + ! SEMICOLON [ shift and go to state 9 ] state 39 @@ -1056,11 +1056,10 @@ state 56 (16) V -> V COMMA V . (16) V -> V . COMMA V - ! shift/reduce conflict for COMMA resolved as shift RPAREN reduce using rule 16 (V -> V COMMA V .) - COMMA shift and go to state 51 + COMMA reduce using rule 16 (V -> V COMMA V .) - ! COMMA [ reduce using rule 16 (V -> V COMMA V .) ] + ! COMMA [ shift and go to state 51 ] state 57 @@ -1069,8 +1068,7 @@ state 57 (4) E -> E . AOP E (8) E -> E . SEMICOLON E - ! shift/reduce conflict for AOP resolved as shift - ! shift/reduce conflict for SEMICOLON resolved as shift + SEMICOLON reduce using rule 9 (E -> IF B THEN E ELSE E .) $end reduce using rule 9 (E -> IF B THEN E ELSE E .) RPAREN reduce using rule 9 (E -> IF B THEN E ELSE E .) EQOP reduce using rule 9 (E -> IF B THEN E ELSE E .) @@ -1082,10 +1080,9 @@ state 57 DO reduce using rule 9 (E -> IF B THEN E ELSE E .) RBRACE reduce using rule 9 (E -> IF B THEN E ELSE E .) AOP shift and go to state 8 - SEMICOLON shift and go to state 9 ! AOP [ reduce using rule 9 (E -> IF B THEN E ELSE E .) ] - ! SEMICOLON [ reduce using rule 9 (E -> IF B THEN E ELSE E .) ] + ! SEMICOLON [ shift and go to state 9 ] state 58 @@ -1130,6 +1127,3 @@ WARNING: WARNING: shift/reduce conflict for ID in state 23 resolved as shift WARNING: shift/reduce conflict for EQOP in state 45 resolved as shift WARNING: shift/reduce conflict for LOP in state 45 resolved as shift -WARNING: shift/reduce conflict for COMMA in state 56 resolved as shift -WARNING: shift/reduce conflict for AOP in state 57 resolved as shift -WARNING: shift/reduce conflict for SEMICOLON in state 57 resolved as shift diff --git a/Project-02-03-04/parsetab.py b/Project-02-03-04/parsetab.py index de9115a..f7cd4ec 100644 --- a/Project-02-03-04/parsetab.py +++ b/Project-02-03-04/parsetab.py @@ -6,9 +6,9 @@ _tabversion = '3.10' _lr_method = 'LALR' -_lr_signature = 'ErightINleftSEMICOLONrightASSIGNleftCOMPleftEQOPleftAOPAOP ASSIGN COMMA COMP CONST DO ELSE EQOP FALSE ID IF IN LBRACE LET LOP LPAREN RBRACE RPAREN SEMICOLON THEN TRUE WHILEE : LET D IN EE : IDE : ID LPAREN A RPARENE : E AOP EE : LPAREN E RPARENE : CONSTE : ID ASSIGN EE : E SEMICOLON EE : IF B THEN E ELSE EE : WHILE B DO LBRACE E RBRACEA : EA : A COMMA ED : ID LPAREN V RPAREN LBRACE E RBRACED : D DV : IDV : V COMMA VB : E EQOP EB : E COMP EB : B EQOP BB : B LOP BB : TRUEB : FALSEB : LPAREN B RPAREN' +_lr_signature = 'EleftSEMICOLONleftINleftELSEleftCOMMArightASSIGNleftCOMPleftEQOPleftAOPleftCOMPleftEQOPAOP ASSIGN COMMA COMP CONST DO ELSE EQOP FALSE ID IF IN LBRACE LET LOP LPAREN RBRACE RPAREN SEMICOLON THEN TRUE WHILEE : LET D IN EE : IDE : ID LPAREN A RPARENE : E AOP EE : LPAREN E RPARENE : CONSTE : ID ASSIGN EE : E SEMICOLON EE : IF B THEN E ELSE EE : WHILE B DO LBRACE E RBRACEA : EA : A COMMA ED : ID LPAREN V RPAREN LBRACE E RBRACED : D DV : IDV : V COMMA VB : E EQOP EB : E COMP EB : B EQOP BB : B LOP BB : TRUEB : FALSEB : LPAREN B RPAREN' -_lr_action_items = {'LET':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,]),'ID':([0,2,4,6,7,8,9,10,12,13,19,23,24,25,30,31,32,33,34,42,49,51,53,55,60,],[3,11,3,3,3,3,3,11,3,3,3,11,3,39,3,3,3,3,3,3,3,39,3,3,-13,]),'LPAREN':([0,3,4,6,7,8,9,11,12,13,19,24,30,31,32,33,34,42,49,53,55,],[4,12,4,19,19,4,4,25,4,4,19,4,4,19,19,4,4,4,4,4,4,]),'CONST':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'IF':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'WHILE':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'$end':([1,3,5,21,22,28,29,38,41,57,58,],[0,-2,-6,-4,-8,-7,-5,-1,-3,-9,-10,]),'AOP':([1,3,5,14,16,21,22,27,28,29,36,38,41,43,46,47,52,54,57,58,59,],[8,-2,-6,8,8,-4,8,8,8,-5,8,8,-3,8,8,8,8,8,8,-10,8,]),'SEMICOLON':([1,3,5,14,16,21,22,27,28,29,36,38,41,43,46,47,52,54,57,58,59,],[9,-2,-6,9,9,-4,-8,9,-7,-5,9,9,-3,9,9,9,9,9,9,-10,9,]),'RPAREN':([3,5,14,17,18,21,22,26,27,28,29,35,36,38,39,40,41,44,45,46,47,48,52,56,57,58,],[-2,-6,29,-21,-22,-4,-8,41,-11,-7,-5,48,29,-1,-15,50,-3,-19,-20,-17,-18,-23,-12,-16,-9,-10,]),'EQOP':([3,5,15,16,17,18,20,21,22,28,29,35,36,38,41,44,45,46,47,48,57,58,],[-2,-6,31,33,-21,-22,31,-4,-8,-7,-5,31,33,-1,-3,-19,31,-17,-18,-23,-9,-10,]),'COMP':([3,5,16,21,22,28,29,36,38,41,57,58,],[-2,-6,34,-4,-8,-7,-5,34,-1,-3,-9,-10,]),'COMMA':([3,5,21,22,26,27,28,29,38,39,40,41,52,56,57,58,],[-2,-6,-4,-8,42,-11,-7,-5,-1,-15,51,-3,-12,51,-9,-10,]),'ELSE':([3,5,21,22,28,29,38,41,43,57,58,],[-2,-6,-4,-8,-7,-5,-1,-3,53,-9,-10,]),'THEN':([3,5,15,17,18,21,22,28,29,38,41,44,45,46,47,48,57,58,],[-2,-6,30,-21,-22,-4,-8,-7,-5,-1,-3,-19,-20,-17,-18,-23,-9,-10,]),'LOP':([3,5,15,17,18,20,21,22,28,29,35,38,41,44,45,46,47,48,57,58,],[-2,-6,32,-21,-22,32,-4,-8,-7,-5,32,-1,-3,-19,32,-17,-18,-23,-9,-10,]),'DO':([3,5,17,18,20,21,22,28,29,38,41,44,45,46,47,48,57,58,],[-2,-6,-21,-22,37,-4,-8,-7,-5,-1,-3,-19,-20,-17,-18,-23,-9,-10,]),'RBRACE':([3,5,21,22,28,29,38,41,54,57,58,59,],[-2,-6,-4,-8,-7,-5,-1,-3,58,-9,-10,60,]),'ASSIGN':([3,],[13,]),'TRUE':([6,7,19,31,32,],[17,17,17,17,17,]),'FALSE':([6,7,19,31,32,],[18,18,18,18,18,]),'IN':([10,23,60,],[24,-14,-13,]),'LBRACE':([37,50,],[49,55,]),} +_lr_action_items = {'LET':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,]),'ID':([0,2,4,6,7,8,9,10,12,13,19,23,24,25,30,31,32,33,34,42,49,51,53,55,60,],[3,11,3,3,3,3,3,11,3,3,3,11,3,39,3,3,3,3,3,3,3,39,3,3,-13,]),'LPAREN':([0,3,4,6,7,8,9,11,12,13,19,24,30,31,32,33,34,42,49,53,55,],[4,12,4,19,19,4,4,25,4,4,19,4,4,19,19,4,4,4,4,4,4,]),'CONST':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,]),'IF':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,]),'WHILE':([0,4,6,7,8,9,12,13,19,24,30,31,32,33,34,42,49,53,55,],[7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,]),'$end':([1,3,5,21,22,28,29,38,41,57,58,],[0,-2,-6,-4,-8,-7,-5,-1,-3,-9,-10,]),'AOP':([1,3,5,14,16,21,22,27,28,29,36,38,41,43,46,47,52,54,57,58,59,],[8,-2,-6,8,8,-4,8,8,8,-5,8,8,-3,8,8,8,8,8,8,-10,8,]),'SEMICOLON':([1,3,5,14,16,21,22,27,28,29,36,38,41,43,46,47,52,54,57,58,59,],[9,-2,-6,9,9,-4,-8,9,-7,-5,9,-1,-3,9,9,9,9,9,-9,-10,9,]),'RPAREN':([3,5,14,17,18,21,22,26,27,28,29,35,36,38,39,40,41,44,45,46,47,48,52,56,57,58,],[-2,-6,29,-21,-22,-4,-8,41,-11,-7,-5,48,29,-1,-15,50,-3,-19,-20,-17,-18,-23,-12,-16,-9,-10,]),'EQOP':([3,5,15,16,17,18,20,21,22,28,29,35,36,38,41,44,45,46,47,48,57,58,],[-2,-6,31,33,-21,-22,31,-4,-8,-7,-5,31,33,-1,-3,-19,31,-17,-18,-23,-9,-10,]),'COMP':([3,5,16,21,22,28,29,36,38,41,57,58,],[-2,-6,34,-4,-8,-7,-5,34,-1,-3,-9,-10,]),'COMMA':([3,5,21,22,26,27,28,29,38,39,40,41,52,56,57,58,],[-2,-6,-4,-8,42,-11,-7,-5,-1,-15,51,-3,-12,-16,-9,-10,]),'ELSE':([3,5,21,22,28,29,38,41,43,57,58,],[-2,-6,-4,-8,-7,-5,-1,-3,53,-9,-10,]),'THEN':([3,5,15,17,18,21,22,28,29,38,41,44,45,46,47,48,57,58,],[-2,-6,30,-21,-22,-4,-8,-7,-5,-1,-3,-19,-20,-17,-18,-23,-9,-10,]),'LOP':([3,5,15,17,18,20,21,22,28,29,35,38,41,44,45,46,47,48,57,58,],[-2,-6,32,-21,-22,32,-4,-8,-7,-5,32,-1,-3,-19,32,-17,-18,-23,-9,-10,]),'DO':([3,5,17,18,20,21,22,28,29,38,41,44,45,46,47,48,57,58,],[-2,-6,-21,-22,37,-4,-8,-7,-5,-1,-3,-19,-20,-17,-18,-23,-9,-10,]),'RBRACE':([3,5,21,22,28,29,38,41,54,57,58,59,],[-2,-6,-4,-8,-7,-5,-1,-3,58,-9,-10,60,]),'ASSIGN':([3,],[13,]),'TRUE':([6,7,19,31,32,],[17,17,17,17,17,]),'FALSE':([6,7,19,31,32,],[18,18,18,18,18,]),'IN':([10,23,60,],[24,-14,-13,]),'LBRACE':([37,50,],[49,55,]),} _lr_action = {} for _k, _v in _lr_action_items.items(): @@ -27,27 +27,27 @@ for _k, _v in _lr_goto_items.items(): del _lr_goto_items _lr_productions = [ ("S' -> E","S'",1,None,None,None), - ('E -> LET D IN E','E',4,'p_E_let','triplayacc.py',27), - ('E -> ID','E',1,'p_E_id','triplayacc.py',31), - ('E -> ID LPAREN A RPAREN','E',4,'p_E_call','triplayacc.py',35), - ('E -> E AOP E','E',3,'p_E_aop','triplayacc.py',40), - ('E -> LPAREN E RPAREN','E',3,'p_E_paren','triplayacc.py',44), - ('E -> CONST','E',1,'p_E_const','triplayacc.py',49), - ('E -> ID ASSIGN E','E',3,'p_E_assign','triplayacc.py',53), - ('E -> E SEMICOLON E','E',3,'p_E_seq','triplayacc.py',57), - ('E -> IF B THEN E ELSE E','E',6,'p_E_if','triplayacc.py',61), - ('E -> WHILE B DO LBRACE E RBRACE','E',6,'p_E_while','triplayacc.py',65), - ('A -> E','A',1,'p_A_single','triplayacc.py',74), - ('A -> A COMMA E','A',3,'p_A_multiple','triplayacc.py',78), - ('D -> ID LPAREN V RPAREN LBRACE E RBRACE','D',7,'p_D_single','triplayacc.py',86), - ('D -> D D','D',2,'p_D_concat','triplayacc.py',90), - ('V -> ID','V',1,'p_V_single','triplayacc.py',98), - ('V -> V COMMA V','V',3,'p_V_multiple','triplayacc.py',102), - ('B -> E EQOP E','B',3,'p_B_eqop_E','triplayacc.py',110), - ('B -> E COMP E','B',3,'p_B_comp','triplayacc.py',114), - ('B -> B EQOP B','B',3,'p_B_eqop_B','triplayacc.py',118), - ('B -> B LOP B','B',3,'p_B_lop','triplayacc.py',122), - ('B -> TRUE','B',1,'p_B_true','triplayacc.py',126), - ('B -> FALSE','B',1,'p_B_false','triplayacc.py',130), - ('B -> LPAREN B RPAREN','B',3,'p_B_paren','triplayacc.py',134), + ('E -> LET D IN E','E',4,'p_E_let','triplayacc.py',30), + ('E -> ID','E',1,'p_E_id','triplayacc.py',34), + ('E -> ID LPAREN A RPAREN','E',4,'p_E_call','triplayacc.py',38), + ('E -> E AOP E','E',3,'p_E_aop','triplayacc.py',43), + ('E -> LPAREN E RPAREN','E',3,'p_E_paren','triplayacc.py',47), + ('E -> CONST','E',1,'p_E_const','triplayacc.py',52), + ('E -> ID ASSIGN E','E',3,'p_E_assign','triplayacc.py',56), + ('E -> E SEMICOLON E','E',3,'p_E_seq','triplayacc.py',60), + ('E -> IF B THEN E ELSE E','E',6,'p_E_if','triplayacc.py',64), + ('E -> WHILE B DO LBRACE E RBRACE','E',6,'p_E_while','triplayacc.py',68), + ('A -> E','A',1,'p_A_single','triplayacc.py',77), + ('A -> A COMMA E','A',3,'p_A_multiple','triplayacc.py',81), + ('D -> ID LPAREN V RPAREN LBRACE E RBRACE','D',7,'p_D_single','triplayacc.py',89), + ('D -> D D','D',2,'p_D_concat','triplayacc.py',93), + ('V -> ID','V',1,'p_V_single','triplayacc.py',101), + ('V -> V COMMA V','V',3,'p_V_multiple','triplayacc.py',105), + ('B -> E EQOP E','B',3,'p_B_eqop_E','triplayacc.py',113), + ('B -> E COMP E','B',3,'p_B_comp','triplayacc.py',117), + ('B -> B EQOP B','B',3,'p_B_eqop_B','triplayacc.py',121), + ('B -> B LOP B','B',3,'p_B_lop','triplayacc.py',125), + ('B -> TRUE','B',1,'p_B_true','triplayacc.py',129), + ('B -> FALSE','B',1,'p_B_false','triplayacc.py',133), + ('B -> LPAREN B RPAREN','B',3,'p_B_paren','triplayacc.py',137), ] diff --git a/Project-02-03-04/triplayacc.py b/Project-02-03-04/triplayacc.py index 04fcace..98c261c 100644 --- a/Project-02-03-04/triplayacc.py +++ b/Project-02-03-04/triplayacc.py @@ -3,16 +3,21 @@ # ------------------------------------------------------------ import ply.yacc as yacc -import compiler as ast +import cfg_build as ast from triplalex import tokens precedence = ( - ('right', 'IN'), ('left', 'SEMICOLON'), + ('left', 'IN'), + ('left', 'ELSE'), + ('left', 'COMMA'), ('right', 'ASSIGN'), ('left', 'COMP'), ('left', 'EQOP'), ('left', 'AOP'), + ('left', 'COMP'), + ('left', 'EQOP'), + ) start = 'E' diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..26bfc94 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +matplotlib~=3.10.8 +graphviz~=0.21 +ply~=3.11 \ No newline at end of file