source: proto/matchparens/parenmatch.py @ 3689

Last change on this file since 3689 was 3064, checked in by cameron, 6 years ago

Simplify parenthesis matching; fix paren match with comments.

File size: 3.1 KB
Line 
1#
2# Recursive Parenthesis Matching
3#
4#
5# Robert D. Cameron
6# October 14, 2012
7#
8import sys
9import pablo
10
11class 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
21class Lex ():
22        LParen = 0
23        RParen = 0
24       
25class Matches() :
26        closed = {}
27        error = 0
28
29
30def 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       
42def Match_Parens(lex, matches):
43        parens = lex.LParen | lex.RParen
44        i = 0
45        pscan = pablo.AdvanceThenScanTo(lex.LParen, parens)
46        matches.closed[0] = pscan & lex.RParen
47        all_closed = matches.closed[0]
48        matches.error = pablo.atEOF(pscan)
49        # Not matched, still pending.
50        pending_LParen = pscan & lex.LParen
51        RParen_unmatched = lex.RParen &~ matches.closed[0]
52        inPlay = pending_LParen | RParen_unmatched
53        while pending_LParen:
54                i += 1
55                pscan = pablo.AdvanceThenScanTo(pending_LParen, inPlay)
56                matches.closed[i] = pscan & lex.RParen
57                all_closed |= matches.closed[i]
58                matches.error |= pablo.atEOF(pscan)
59                pending_LParen = pscan & lex.LParen
60                RParen_unmatched = lex.RParen &~ all_closed
61                inPlay = pending_LParen | RParen_unmatched
62        #
63        # Any closing paren that was not actually used to close
64        # an opener is in error.
65        matches.error |= lex.RParen &~ all_closed
66
67
68def Match_Parens0(lex, matches):
69        parens = lex.LParen | lex.RParen
70        Lscan = {}
71        Rscan = {}
72        i = 0
73        Lscan[0] = pablo.AdvanceThenScanTo(lex.LParen, parens)
74        Rscan[0] = pablo.AdvanceThenScanTo(lex.RParen, parens)
75        matches.closed[0] = Lscan[0] & lex.RParen
76        matches.error = pablo.atEOF(Lscan[0])
77        unclosed = Lscan[i] & lex.LParen | Rscan[i] & lex.RParen
78        all_closed = matches.closed[i]
79        while unclosed:
80                i += 1
81                unclosedLParen = unclosed & lex.LParen
82                unclosedRParen = unclosed & lex.RParen
83                Lscan[i] = pablo.AdvanceThenScanTo(unclosedLParen, unclosed)
84                Rscan[i] = pablo.AdvanceThenScanTo(unclosedRParen, unclosed)
85                matches.closed[i] = Lscan[i] & lex.RParen
86                matches.error |= pablo.atEOF(Lscan[i])
87                unclosed = Lscan[i] & lex.LParen | Rscan[i] & lex.RParen
88                all_closed |= matches.closed[i]
89        #
90        # Any closing paren that was not actually used to close
91        # an opener is in error.
92        matches.error |= lex.RParen &~ all_closed
93
94
95
96basis_bits = Basis_bits()
97lex = Lex()
98matches = Matches()
99
100if __name__ == "__main__":
101        #print "Starting ..."
102        if len(sys.argv) > 1:
103                u8data = pablo.readfile(sys.argv[1]) 
104                pablo.EOF_mask = pablo.transpose_streams(u8data, basis_bits)
105                Classify_bytes(basis_bits, lex)
106                Match_Parens(lex, matches)
107                lgth = len(u8data)
108                print "data:" + " "*(16-5) + u8data
109                i = 0
110                while i in matches.closed.keys():
111                  f = "closed[%i]" % i
112                  print f + ("       ") + pablo.bitstream2string(matches.closed[i], lgth)
113                  i+=1
114                print "errors" + " "*(16-6) + pablo.bitstream2string(matches.error, lgth+1)
115               
116        else:
117                print("Usage: python parenmatch.py <file>")
118       
119
120
Note: See TracBrowser for help on using the repository browser.