[2904] | 1 | # |
---|

| 2 | # Recursive Parenthesis Matching |
---|

| 3 | # |
---|

| 4 | # |
---|

| 5 | # Robert D. Cameron |
---|

| 6 | # October 14, 2012 |
---|

| 7 | # |
---|

| 8 | import sys |
---|

| 9 | import pablo |
---|

| 10 | |
---|

| 11 | class Basis_bits(): |
---|

| 12 | bit_0 = 0 |
---|

| 13 | bit_1 = 0 |
---|

| 14 | bit_2 = 0 |
---|

| 15 | bit_3 = 0 |
---|

| 16 | bit_4 = 0 |
---|

| 17 | bit_5 = 0 |
---|

| 18 | bit_6 = 0 |
---|

| 19 | bit_7 = 0 |
---|

| 20 | |
---|

| 21 | class Lex (): |
---|

| 22 | LParen = 0 |
---|

| 23 | RParen = 0 |
---|

| 24 | |
---|

| 25 | class Matches() : |
---|

[3064] | 26 | closed = 0 |
---|

[2904] | 27 | error = 0 |
---|

| 28 | |
---|

| 29 | |
---|

| 30 | def Classify_bytes(basis_bits, lex): |
---|

| 31 | temp1 = (basis_bits.bit_0 | basis_bits.bit_1) |
---|

| 32 | temp2 = (basis_bits.bit_2 &~ basis_bits.bit_3) |
---|

| 33 | temp3 = (temp2 &~ temp1) |
---|

| 34 | temp4 = (basis_bits.bit_4 &~ basis_bits.bit_5) |
---|

| 35 | temp5 = (basis_bits.bit_6 | basis_bits.bit_7) |
---|

| 36 | temp6 = (temp4 &~ temp5) |
---|

| 37 | lex.LParen = (temp3 & temp6) |
---|

| 38 | temp7 = (basis_bits.bit_7 &~ basis_bits.bit_6) |
---|

| 39 | temp8 = (temp4 & temp7) |
---|

| 40 | lex.RParen = (temp3 & temp8) |
---|

| 41 | |
---|

| 42 | def Match_Parens(lex, matches): |
---|

[3031] | 43 | parens = lex.LParen | lex.RParen |
---|

[3064] | 44 | pscan = pablo.AdvanceThenScanTo(lex.LParen, parens) |
---|

| 45 | matches.closed = pscan & lex.RParen |
---|

| 46 | matches.error = pablo.atEOF(pscan) |
---|

| 47 | # Not matched, still pending. |
---|

| 48 | pending_LParen = pscan & lex.LParen |
---|

| 49 | RParen_unmatched = lex.RParen &~ matches.closed |
---|

| 50 | inPlay = pending_LParen | RParen_unmatched |
---|

| 51 | while pending_LParen: |
---|

| 52 | pscan = pablo.AdvanceThenScanTo(pending_LParen, inPlay) |
---|

| 53 | matches.closed |= pscan & lex.RParen |
---|

| 54 | matches.error |= pablo.atEOF(pscan) |
---|

| 55 | pending_LParen = pscan & lex.LParen |
---|

| 56 | RParen_unmatched = lex.RParen &~ matches.closed |
---|

| 57 | inPlay = pending_LParen | RParen_unmatched |
---|

[2904] | 58 | # |
---|

| 59 | # Any closing paren that was not actually used to close |
---|

| 60 | # an opener is in error. |
---|

[3031] | 61 | matches.error |= lex.RParen &~ matches.closed |
---|

[2904] | 62 | |
---|

| 63 | basis_bits = Basis_bits() |
---|

| 64 | lex = Lex() |
---|

| 65 | matches = Matches() |
---|

| 66 | |
---|

| 67 | if __name__ == "__main__": |
---|

| 68 | #print "Starting ..." |
---|

| 69 | if len(sys.argv) > 1: |
---|

| 70 | u8data = pablo.readfile(sys.argv[1]) |
---|

| 71 | pablo.EOF_mask = pablo.transpose_streams(u8data, basis_bits) |
---|

| 72 | Classify_bytes(basis_bits, lex) |
---|

| 73 | Match_Parens(lex, matches) |
---|

| 74 | lgth = len(u8data) |
---|

| 75 | print "data:" + " "*(16-5) + u8data |
---|

| 76 | print "errors" + " "*(16-6) + pablo.bitstream2string(matches.error, lgth+1) |
---|

| 77 | |
---|

| 78 | else: |
---|

| 79 | print("Usage: python parenmatch.py <file>") |
---|

| 80 | |
---|

| 81 | |
---|

| 82 | |
---|