First try

This commit is contained in:
Jan-Niclas Loosen
2026-01-16 16:48:34 +01:00
parent a2cc0adb52
commit 530c597fc1
12 changed files with 330 additions and 42 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 82 KiB

View File

@@ -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)

View File

@@ -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"

View File

@@ -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

View File

View File

@@ -1,4 +1,5 @@
import triplayacc as yacc import triplayacc as yacc
import cfg_build
import syntax import syntax
from pathlib import Path from pathlib import Path
@@ -10,9 +11,12 @@ from vistram.vistram import MachineUI
import matplotlib.pyplot as plt import matplotlib.pyplot as plt
import matplotlib.image as mpimg import matplotlib.image as mpimg
import helpers.console as cnsl import lib.console as cnsl
import os import os
from cfg.CFG import CFG
from cfg.CFG_Node import (CFG_START, CFG_END)
import matplotlib import matplotlib
matplotlib.use("TkAgg") matplotlib.use("TkAgg")
@@ -21,6 +25,17 @@ def assemble(ast):
code = ast.code({}, 0) code = ast.code({}, 0)
return code + [halt()] 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 # Renders a diagram of the AST
def render_diagram(dot_string: str): def render_diagram(dot_string: str):
# Set DPI for PNG # Set DPI for PNG
@@ -64,9 +79,9 @@ if __name__ == "__main__":
print("\nTRIPLA Parser and TRIPLA to TRAM Compiler") print("\nTRIPLA Parser and TRIPLA to TRAM Compiler")
while True: 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.") print("\nBye Bye.")
break break
@@ -143,4 +158,26 @@ if __name__ == "__main__":
ui.machine.reset() ui.machine.reset()
root.mainloop() 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.")

View File

@@ -781,6 +781,7 @@ state 38
(4) E -> E . AOP E (4) E -> E . AOP E
(8) E -> E . SEMICOLON 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 .) $end reduce using rule 1 (E -> LET D IN E .)
RPAREN 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 .) 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 .) DO reduce using rule 1 (E -> LET D IN E .)
RBRACE 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 AOP shift and go to state 8
SEMICOLON shift and go to state 9
! AOP [ reduce using rule 1 (E -> LET D IN E .) ] ! 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 state 39
@@ -1056,11 +1056,10 @@ state 56
(16) V -> V COMMA V . (16) V -> V COMMA V .
(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 .) 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 state 57
@@ -1069,8 +1068,7 @@ state 57
(4) E -> E . AOP E (4) E -> E . AOP E
(8) E -> E . SEMICOLON E (8) E -> E . SEMICOLON E
! shift/reduce conflict for AOP resolved as shift SEMICOLON reduce using rule 9 (E -> IF B THEN E ELSE E .)
! shift/reduce conflict for SEMICOLON resolved as shift
$end 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 .) RPAREN reduce using rule 9 (E -> IF B THEN E ELSE E .)
EQOP 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 .) DO reduce using rule 9 (E -> IF B THEN E ELSE E .)
RBRACE 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 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 .) ] ! 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 state 58
@@ -1130,6 +1127,3 @@ WARNING:
WARNING: shift/reduce conflict for ID in state 23 resolved as shift 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 EQOP in state 45 resolved as shift
WARNING: shift/reduce conflict for LOP 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

View File

@@ -6,9 +6,9 @@ _tabversion = '3.10'
_lr_method = 'LALR' _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 = {} _lr_action = {}
for _k, _v in _lr_action_items.items(): for _k, _v in _lr_action_items.items():
@@ -27,27 +27,27 @@ for _k, _v in _lr_goto_items.items():
del _lr_goto_items del _lr_goto_items
_lr_productions = [ _lr_productions = [
("S' -> E","S'",1,None,None,None), ("S' -> E","S'",1,None,None,None),
('E -> LET D IN E','E',4,'p_E_let','triplayacc.py',27), ('E -> LET D IN E','E',4,'p_E_let','triplayacc.py',30),
('E -> ID','E',1,'p_E_id','triplayacc.py',31), ('E -> ID','E',1,'p_E_id','triplayacc.py',34),
('E -> ID LPAREN A RPAREN','E',4,'p_E_call','triplayacc.py',35), ('E -> ID LPAREN A RPAREN','E',4,'p_E_call','triplayacc.py',38),
('E -> E AOP E','E',3,'p_E_aop','triplayacc.py',40), ('E -> E AOP E','E',3,'p_E_aop','triplayacc.py',43),
('E -> LPAREN E RPAREN','E',3,'p_E_paren','triplayacc.py',44), ('E -> LPAREN E RPAREN','E',3,'p_E_paren','triplayacc.py',47),
('E -> CONST','E',1,'p_E_const','triplayacc.py',49), ('E -> CONST','E',1,'p_E_const','triplayacc.py',52),
('E -> ID ASSIGN E','E',3,'p_E_assign','triplayacc.py',53), ('E -> ID ASSIGN E','E',3,'p_E_assign','triplayacc.py',56),
('E -> E SEMICOLON E','E',3,'p_E_seq','triplayacc.py',57), ('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',61), ('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',65), ('E -> WHILE B DO LBRACE E RBRACE','E',6,'p_E_while','triplayacc.py',68),
('A -> E','A',1,'p_A_single','triplayacc.py',74), ('A -> E','A',1,'p_A_single','triplayacc.py',77),
('A -> A COMMA E','A',3,'p_A_multiple','triplayacc.py',78), ('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',86), ('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',90), ('D -> D D','D',2,'p_D_concat','triplayacc.py',93),
('V -> ID','V',1,'p_V_single','triplayacc.py',98), ('V -> ID','V',1,'p_V_single','triplayacc.py',101),
('V -> V COMMA V','V',3,'p_V_multiple','triplayacc.py',102), ('V -> V COMMA V','V',3,'p_V_multiple','triplayacc.py',105),
('B -> E EQOP E','B',3,'p_B_eqop_E','triplayacc.py',110), ('B -> E EQOP E','B',3,'p_B_eqop_E','triplayacc.py',113),
('B -> E COMP E','B',3,'p_B_comp','triplayacc.py',114), ('B -> E COMP E','B',3,'p_B_comp','triplayacc.py',117),
('B -> B EQOP B','B',3,'p_B_eqop_B','triplayacc.py',118), ('B -> B EQOP B','B',3,'p_B_eqop_B','triplayacc.py',121),
('B -> B LOP B','B',3,'p_B_lop','triplayacc.py',122), ('B -> B LOP B','B',3,'p_B_lop','triplayacc.py',125),
('B -> TRUE','B',1,'p_B_true','triplayacc.py',126), ('B -> TRUE','B',1,'p_B_true','triplayacc.py',129),
('B -> FALSE','B',1,'p_B_false','triplayacc.py',130), ('B -> FALSE','B',1,'p_B_false','triplayacc.py',133),
('B -> LPAREN B RPAREN','B',3,'p_B_paren','triplayacc.py',134), ('B -> LPAREN B RPAREN','B',3,'p_B_paren','triplayacc.py',137),
] ]

View File

@@ -3,16 +3,21 @@
# ------------------------------------------------------------ # ------------------------------------------------------------
import ply.yacc as yacc import ply.yacc as yacc
import compiler as ast import cfg_build as ast
from triplalex import tokens from triplalex import tokens
precedence = ( precedence = (
('right', 'IN'),
('left', 'SEMICOLON'), ('left', 'SEMICOLON'),
('left', 'IN'),
('left', 'ELSE'),
('left', 'COMMA'),
('right', 'ASSIGN'), ('right', 'ASSIGN'),
('left', 'COMP'), ('left', 'COMP'),
('left', 'EQOP'), ('left', 'EQOP'),
('left', 'AOP'), ('left', 'AOP'),
('left', 'COMP'),
('left', 'EQOP'),
) )
start = 'E' start = 'E'

3
requirements.txt Normal file
View File

@@ -0,0 +1,3 @@
matplotlib~=3.10.8
graphviz~=0.21
ply~=3.11