#
# Recursive Parenthesis Matching
#
#
# Robert D. Cameron
# October 14, 2012
#
class Basis_bits():
bit_0 = 0
bit_1 = 0
bit_2 = 0
bit_3 = 0
bit_4 = 0
bit_5 = 0
bit_6 = 0
bit_7 = 0
class Lex ():
LParen = 0
RParen = 0
class Matches() :
closed = 0
instring = 0
error = 0
def Classify_bytes(basis_bits, lex):
temp1 = (basis_bits.bit_0 | basis_bits.bit_1)
temp2 = (basis_bits.bit_2 &~ basis_bits.bit_3)
temp3 = (temp2 &~ temp1)
temp4 = (basis_bits.bit_4 &~ basis_bits.bit_5)
temp5 = (basis_bits.bit_6 | basis_bits.bit_7)
temp6 = (temp4 &~ temp5)
lex.LParen = (temp3 & temp6)
temp7 = (basis_bits.bit_7 &~ basis_bits.bit_6)
temp8 = (temp4 & temp7)
lex.RParen = (temp3 & temp8)
def Match_Parens(lex, matches):
unmatched = lex.RParen
pscan = 0
qscan = 0
pscan = pablo.ScanTo(pablo.Advance(lex.LParen), lex.LParen | lex.RParen)
qscan = pablo.ScanTo(pablo.Advance(lex.RParen), lex.LParen | lex.RParen)
matches.instring = pablo.ExclusiveSpan(lex.LParen, pscan)
matches.closed = pscan & lex.RParen
unclosed = pscan & lex.LParen | qscan & lex.RParen
matches.error = pablo.atEOF(pscan)
all_closed = matches.closed
while unclosed:
pscan = pablo.ScanTo(pablo.Advance(unclosed & lex.LParen), unclosed)
qscan = pablo.ScanTo(pablo.Advance(unclosed & lex.RParen), unclosed)
matches.instring = matches.instring | pablo.SpanUpTo(unclosed & lex.LParen, pscan)
matches.closed = pscan & lex.RParen
unclosed = pscan & lex.LParen | qscan & lex.RParen
all_closed |= matches.closed
matches.error |= pablo.atEOF(pscan)
#
# Any closing paren that was not actually used to close
# an opener is in error.
matches.error = matches.error | (lex.RParen &~ all_closed)
def Main(basis_bits, lex, matches):
Classify_bytes(basis_bits, lex)
Match_Parens(lex, matches)