source: proto/JSON/json_prototype.py @ 674

Last change on this file since 674 was 674, checked in by ksherdy, 9 years ago

Update def comments.

File size: 7.8 KB
Line 
1# -*- coding: utf-8 -*-
2#
3# json_prototype.py
4#
5# Ken Herdy
6# Oct. 13, 2010
7#
8#----------------------------------------------------------------------------
9#
10# We use python's unlimited precision integers for unbounded bit streams.
11# This permits simple logical operations on the entire stream.
12# Assumption: bitstreams are little-endian (e.g., as on x86).
13#
14#----------------------------------------------------------------------------
15#
16
17import bitutil
18import byteclass
19import sys
20
21debug = False
22filename = "json_prototype.py"
23
24# Globals
25# Bitstream function defs input/output *only* bitstream type variables.
26# Global declarations allow debug blocks in bitstream defs. Do not shadow variables.
27data = ""
28lgth = 0
29
30def validate_number(lex, EOF_mask):
31        Errors = 0     
32        M0 = 0                                                  # Assume the cursor is at the first Minus, Zero, or Digit_1_9 character
33        M0 = bitutil.Advance(lex.Comma)                         # WARNING - A hack to set initial cursor postions and ease testing. The 'lexical' FIRST SET for the JSON number production is {-,0,1,..,9} .     
34
35        M1 = bitutil.ScanThru(M0, lex.Minus & M0)               # ? Optional character class [-]
36        E1 = M1 &~(lex.Zero|lex.Digit_1_9)
37
38        M1a = M1 & lex.Zero                                     # Split
39        M1b = M1 & lex.Digit_0_9                               
40        M2a = bitutil.Advance(M1a)
41        M2b = bitutil.Advance(M1b)
42        M3b = bitutil.ScanThru(M2b,lex.Digit_0_9)
43        M4 = M2a | M3b                                          # Join
44       
45        M4a = M4 &~(lex.Decimal_Point)                          # Split
46        M4b = M4 & (lex.Decimal_Point)
47        M5b = bitutil.Advance(M4b)
48        E5b = M5b &~(lex.Digit_0_9)                             # + [0-9]+
49        M6 = bitutil.ScanThru(M5b,lex.Digit_0_9)
50        M7 = M4a | M6                                           # Join
51       
52        M7a = M7 &~(lex.E_e)                                    # Split
53        E7a = M7a &~(lex.Number_Follow_Set)
54        M7b = M7 &(lex.E_e)
55        M8b = bitutil.Advance(M7b)
56        M9b = bitutil.ScanThru(M8b, lex.Plus_Minus & M8b)       # ? Optional character class [+-]               
57        E9b  = M9b &~(lex.Digit_0_9)                            # + [0-9]+
58        M10b = bitutil.ScanThru(M9b,lex.Digit_0_9)
59        E10b = M10b &~(lex.Number_Follow_Set)
60        M11 = M7a | M10b                                        # Join
61       
62        Errors = E1 | E5b | E7a | E10b
63       
64        if debug:
65                bitutil.print_aligned_streams([('Input data', data), 
66                              ('M0', bitutil.bitstream2string(M0, lgth)),
67                              ('M1', bitutil.bitstream2string(M1, lgth)),
68                              ('E1', bitutil.bitstream2string(E1, lgth)),
69                              ('M1a', bitutil.bitstream2string(M1a, lgth)),
70                              ('M2a', bitutil.bitstream2string(M2a, lgth)),
71                              ('M2b', bitutil.bitstream2string(M2b, lgth)),
72                              ('M3b', bitutil.bitstream2string(M3b, lgth)),
73                              ('M4', bitutil.bitstream2string(M4, lgth)),
74                              ('M4a', bitutil.bitstream2string(M4a, lgth)),
75                              ('M4b', bitutil.bitstream2string(M4b, lgth)),
76                              ('M5b', bitutil.bitstream2string(M5b, lgth)),
77                              ('E5b', bitutil.bitstream2string(E5b, lgth)),           
78                              ('M6', bitutil.bitstream2string(M6, lgth)),
79                              ('M7', bitutil.bitstream2string(M7, lgth)),
80                              ('M7a', bitutil.bitstream2string(M7a, lgth)),
81                              ('E7a', bitutil.bitstream2string(E7a, lgth)),                                                   
82                              ('M7b', bitutil.bitstream2string(M7b, lgth)),
83                              ('M8b', bitutil.bitstream2string(M8b, lgth)),
84                              ('M9b', bitutil.bitstream2string(M9b, lgth)),           
85                              ('E9b', bitutil.bitstream2string(E9b, lgth)),           
86                              ('M10b', bitutil.bitstream2string(M10b, lgth)),                         
87                              ('M11', bitutil.bitstream2string(M11, lgth)),                                                   
88                              ('Errors', bitutil.bitstream2string(Errors, lgth))])             
89        return Errors
90       
91def demo_validate_number(data):
92        """     
93        For example, 00 is not reported as an error case, but -- is reported as an error case.
94       
95        RFC 4627 - JavaScript Object Notation (JSON) 
96        RFC 5234 - Augmented BNF for Syntax Specifications: ABNF
97       
98        number = [ minus ] int [ frac ] [ exp ]
99        decimal-point = %x2E       ; .
100        digit1-9 = %x31-39         ; 1-9
101        e = %x65 / %x45            ; e E
102        exp = e [ minus / plus ] 1*DIGIT
103        frac = decimal-point 1*DIGIT
104        int = zero / ( digit1-9 *DIGIT )
105        minus = %x2D               ; -
106        plus = %x2B                ; +
107        zero = %x30                ; 0 
108        """     
109        r"""
110        >>> demo_validate_number(',-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,')
111        Input data   : ,-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,
112        Minus        : _1_11_1_____1___1___1____1_______1_______1_________________________
113        Zero         : _________11__11__1___1____1___11___________1______1__1__1__________
114        Digit_1_9    : __________________________________111_111____111____1____111111111_
115        Digit_0_9    : __________________________________111_111____111____1____111111111_
116        Decimal_Point: __________________1___1____1_________1______1______________________
117        E_e          : _______________________1____1______________________1_______________
118        Plus_Minus   : _1_11_1_____1___1___1____1_______1_______1______1_____1____________
119        EOF_Mask     : 1111111111111111111111111111111111111111111111111111111111111111111_
120        Errors       : __1_1__1__1___1____1___1____1__1_________1______1_____1__1_________
121        <BLANKLINE>
122        """ 
123        r"""
124        >>> demo_validate_number(',-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,')
125        Input data   : ,0.5,98.6,99.44,1066,1e1,0.1e1,1e-1,1e00,2e+00,2e-00,1234567890,-9876.543210,0.123456789e-12,1.234567890E+34,23456789012E66,
126        Minus        : _________________________________1_______________1______________1________________________1__________________________________
127        Zero         : _1_______________1_______1____________11____11____11__________1____________1_1_________________________1_____________1______
128        Digit_1_9    : ___1_11_1_11_11_1_11_1_1___1_1_1__1_1____1_____1_____111111111___1111_11111____111111111__11_1_11111111___11_11111111_11_11_
129        Digit_0_9    : ___1_11_1_11_11_1_11_1_1___1_1_1__1_1____1_____1_____111111111___1111_11111____111111111__11_1_11111111___11_11111111_11_11_
130        Decimal_Point: __1____1____1_____________1__________________________________________1________1_______________1_____________________________
131        E_e          : ______________________1_____1___1____1____1_____1_______________________________________1_______________1_______________1___
132        Plus_Minus   : _________________________________1_________1_____1______________1________________________1_______________1__________________
133        EOF_Mask     : 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_
134        Errors       : ____________________________________________________________________________________________________________________________
135        <BLANKLINE>
136        """     
137        r"""
138        >>> demo_validate_number(',012345,12345,0,00,-0,-00')
139        Input data   : ,012345,12345,0,00,-0,-00
140        Minus        : ___________________1__1__
141        Zero         : _1____________1_11__1__11
142        Digit_1_9    : __11111_11111____________
143        Digit_0_9    : __11111_11111____________
144        Decimal_Point: _________________________
145        E_e          : _________________________
146        Plus_Minus   : ___________________1__1__
147        EOF_Mask     : 1111111111111111111111111_
148        Errors       : __1______________1______1
149        <BLANKLINE>
150        """ 
151        global lgth
152        lgth = len(data)
153
154        (bit, EOF_mask) = bitutil.transpose_streams(data)
155        (lex) = byteclass.classify_bytes(bit)
156        Errors = validate_number(lex,EOF_mask)
157
158        bitutil.print_aligned_streams([('Input data', data), 
159                              ('Minus', bitutil.bitstream2string(lex.Minus, lgth)),
160                              ('Zero', bitutil.bitstream2string(lex.Zero, lgth)),
161                              ('Digit_1_9', bitutil.bitstream2string(lex.Digit_1_9, lgth)),
162                              ('Digit_0_9', bitutil.bitstream2string(lex.Digit_1_9, lgth)),
163                              ('Decimal_Point', bitutil.bitstream2string(lex.Decimal_Point, lgth)),
164                              ('E_e', bitutil.bitstream2string(lex.E_e, lgth)),
165                              ('Plus_Minus', bitutil.bitstream2string(lex.Plus_Minus, lgth)),
166                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1)),
167                              ('Errors', bitutil.bitstream2string(Errors, lgth))])
168if __name__ == "__main__":
169        import doctest
170        doctest.testmod()
171
172        if len(sys.argv) < 1:
173                sys.stderr.write("Usage: " + filename + "\n")
174                sys.exit(2)
175
176        data = bitutil.readfile(sys.argv[1]) 
177        demo_validate_number(data)
178       
Note: See TracBrowser for help on using the repository browser.