Skip to content

Instantly share code, notes, and snippets.

@fabian-paul
Last active August 29, 2021 21:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save fabian-paul/2647b3ea142c2db0efbe6dc60763d0aa to your computer and use it in GitHub Desktop.
Save fabian-paul/2647b3ea142c2db0efbe6dc60763d0aa to your computer and use it in GitHub Desktop.
switch_network_renderer
class Renderer:
def __init__(self, root):
self.root = root
def svg(self):
leftmost = self.root.leftmost(0)
s = min(300 / self.root.w, 300 / self.root.h)
svg = f"""
<!DOCTYPE html>
<html>
<body>
<svg height="300" width="300">
<g transform="scale({s} {s})">
{self.root.svg(-leftmost, 0, 1, 1)}
</g>
</svg>
</body>
</html>
"""
return svg
def _repr_html_(self):
return self.svg()
class Op:
style = 'stroke:rgb(255,0,0); stroke-width:0.1'
class And(Op):
def __init__(self, *children):
self.children = children
@property
def h(self):
return sum(child.h for child in self.children)
@property
def w(self):
return max(child.w for child in self.children)
def leftmost(self, x0):
return min(child.leftmost(x0) for child in self.children)
def svg(self, x0, y0, sx, sy) -> str:
y = y0
svg = ''
for child in self.children:
svg += child.svg(x0=x0, y0=y, sx=sx, sy=sy)
y += child.h*sy
return svg
class Or(Op):
def __init__(self, *children):
self.children = children
@property
def h(self):
return max(child.h for child in self.children)
@property
def w(self):
return sum(child.w for child in self.children)
def leftmost(self, x0):
return x0 - self.w/2
# shrinking does not work...
def svg(self, x0, y0, sx, sy) -> str:
leftmost = x0 - self.w/2 + self.children[0].w / 2
x = leftmost
svg = ''
h = self.h
for k, child in enumerate(self.children):
#print(dict(x0=x, y0=y0, sx=sx, sy=sy*(h/child.h)))
svg += child.svg(x0=x, y0=y0, sx=sx, sy=sy*(h/child.h))
if k + 1 < len(self.children):
x += child.w / 2 + self.children[k+1].w / 2
svg += f'<line x1="{leftmost}" y1="{y0}" x2="{x}" y2="{y0}" style="{self.style}" />'
svg += f'<line x1="{leftmost}" y1="{y0 + sy*h}" x2="{x}" y2="{y0 + sy*h}" style="{self.style}" />'
return svg
class Element(Op):
def __init__(self, name: str, w=1.):
self.h = 1.
self.w = w
self.name = name
def leftmost(self, x0):
return x0
def svg(self, x0, y0, sx, sy) -> str:
x1 = x0 + 0.
y1 = y0 + 0.
x2 = x0 + 0.
y2 = y0 + self.h*sy
#print(dict(x1=x1, y1=y1, x2=x2, y2=y2))
# <rect x="{x0}" y="{}" width="{}" height="{}" fill="red"></rect>
# <rect x="{x0}" y="{y0 + 0.25*self.h*sy}" width="{self.w}" height="{self.h / 2}" stroke="red" stroke-width="0.01px" fill="white"/>
svg = f"""
<line x1="{x1}" y1="{y1}" x2="{x2}" y2="{y2}" style="{self.style}" />
<text x="{x0}" y="{y0 + self.h*sy*0.5}" font-family="Verdana"
dominant-baseline="middle" text-anchor="middle" font-size="0.4" fill="blue">{self.name}</text>
"""
#
return svg
#f'<circle cx="{x1}" cy="{y0 + 0.5*sy}" r="0.05" stroke="black" />'
import pyparsing as pp
expression = pp.Forward()
word = pp.Word(pp.alphas)
word.setParseAction(lambda c: Element(c.asList()[0]))
pure_value = (pp.Suppress("(") + expression + pp.Suppress(")")) | word
negated_value = pp.Suppress(pp.Literal('not')) + pure_value
negated_value.setParseAction(lambda c: ('not', c.asList()[0]))
value = negated_value | pure_value
true_conjunction = value + pp.OneOrMore(pp.Suppress("and") + value)
true_conjunction.setParseAction(lambda c: And(*c.asList()))
conjunction = true_conjunction | value
true_disjunction = (conjunction + pp.OneOrMore(pp.Suppress("or") + conjunction))
true_disjunction.setParseAction(lambda c: Or(*c.asList()))
disjunction = (true_disjunction | conjunction)
expression <<= disjunction
string = pp.StringStart() + expression + pp.StringEnd()
e = Element('nm')
#x = Or(Or(And(Or(e,e,e),e,Or(e,e)), e),
# And(And(Or(e,e),e,Or(e,e,e)), e),e)
#Renderer(Or(Or(And(Or(x,e,e),x,Or(e,e)), e),
# And(And(Or(x,e),e,Or(e,e,e)), e),x))
#x = Or(And(And(Or(e,e),e),Or(e,e)), And(e,Or(e)))
#Renderer(And(Or(And(Or(e,x),e),Or(e,x)), Or(e,And(e))))
x = And(Element('re',5), Or(e, e))
#y = And(x, Or(And(x, Or(x,e)), And(x, Or(e,e))), x)
#Renderer(y)
#Renderer(And(e, Or(e,e)))
#Renderer(Or(Or(And(Or(x,e,y),x,Or(e,e)), e),
# And(And(Or(x,e),e,Or(e,y,y)), e),x))
for _ in range(3):
x = And(Or(e, x), Or(e, x))
Renderer(x)
#TODO: add labels, combine...
#Renderer(list(string.parseString("abc and def or (zz or (x and (y or t)))"))[0])
Renderer(list(string.parseString("(aaaa or bb and c or e) and f or g and (h or i) and j"))[0])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment