Make jwutils.algo.Operator a class

This was a namedtuple before, but I couldn't figure out how to ex-/import it
over module boundaries, so I've made it a class.

Signed-off-by: Jan Lindemann <jan@janware.com>
This commit is contained in:
Jan Lindemann 2017-07-27 16:51:48 +02:00
commit da6c32255e

View file

@ -1,10 +1,17 @@
from collections import namedtuple from collections import namedtuple
import re import re
Operator = namedtuple("Operator", [ "func", "nargs" , "prec", "assoc" ]) # export
L, R = 'Left Right'.split() L, R = 'Left Right'.split()
ARG, KEYW, LPAREN, RPAREN = 'arg kw ( )'.split() ARG, KEYW, LPAREN, RPAREN = 'arg kw ( )'.split()
class Operator: # export
def __init__(self, func=None, nargs=2, precedence=3, assoc=L):
self.func = func
self.nargs = nargs
self.prec = precedence
self.assoc = assoc
class Stack: class Stack:
def __init__(self, itemlist=[]): def __init__(self, itemlist=[]):
@ -34,12 +41,17 @@ class ShuntingYard(object): # export
for k, v in operators.iteritems(): for k, v in operators.iteritems():
self.add_operator(k, v.func, v.nargs, v.prec, v.assoc) self.add_operator(k, v.func, v.nargs, v.prec, v.assoc)
def token_string(): def token_string(self):
for k, v in self.__ops: r = ""
buf = ", " + k for k, v in self.__ops.iteritems():
if v.nargs > 1: buf = ", \"" + k
buf += "xxx" if v.nargs == 1:
if k[len(k)-1].isalnum():
buf = buf + ' '
buf = buf + "xxx"
buf = buf + "\""
r = r + buf r = r + buf
if len(r): if len(r):
return r[2:] return r[2:]
return r return r
@ -87,12 +99,12 @@ class ShuntingYard(object): # export
table.append( (token, action, ' '.join(outq), ' '.join(s[0] for s in stack), note) ) table.append( (token, action, ' '.join(outq), ' '.join(s[0] for s in stack), note) )
elif toktype == KEYW: elif toktype == KEYW:
val = self.__ops[token] val = self.__ops[token]
t1, (f1, n1, p1, a1) = token, val t1, op1 = token, val
v = t1 v = t1
note = 'Pop ops from stack to output' note = 'Pop ops from stack to output'
while stack: while stack:
t2, (f2, n2, p2, a2) = stack[-1] t2, op2 = stack[-1]
if (a1 == L and p1 <= p2) or (a1 == R and p1 < p2): if (op1.assoc == L and op1.prec <= op2.prec) or (op1.assoc == R and op1.prec < op2.prec):
if t1 != RPAREN: if t1 != RPAREN:
if t2 != LPAREN: if t2 != LPAREN:
stack.pop() stack.pop()
@ -126,7 +138,7 @@ class ShuntingYard(object): # export
note = 'Drain stack to output' note = 'Drain stack to output'
while stack: while stack:
v = '' v = ''
t2, (f2, n2, p2, a2) = stack[-1] t2, op2 = stack[-1]
action = '(Pop op)' action = '(Pop op)'
stack.pop() stack.pop()
outq.append(t2) outq.append(t2)