source: proto/JSON/json_prototype.py @ 672

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

Add initial JSON protoype implementation files.

File size: 8.3 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        """     
91        For example, 00 is not reported as an error case, but -- is reported as an error case.
92       
93        RFC 4627 - JavaScript Object Notation (JSON) 
94        RFC 5234 - Augmented BNF for Syntax Specifications: ABNF
95       
96        number = [ minus ] int [ frac ] [ exp ]
97        decimal-point = %x2E       ; .
98        digit1-9 = %x31-39         ; 1-9
99        e = %x65 / %x45            ; e E
100        exp = e [ minus / plus ] 1*DIGIT
101        frac = decimal-point 1*DIGIT
102        int = zero / ( digit1-9 *DIGIT )
103        minus = %x2D               ; -
104        plus = %x2B                ; +
105        zero = %x30                ; 0 
106        """     
107def demo_validate_number(data):
108        """     
109        For example, 00 is not reported as an error case, but -- is reported as an error case.
110       
111        RFC 4627 - JavaScript Object Notation (JSON) 
112        RFC 5234 - Augmented BNF for Syntax Specifications: ABNF
113       
114        number = [ minus ] int [ frac ] [ exp ]
115        decimal-point = %x2E       ; .
116        digit1-9 = %x31-39         ; 1-9
117        e = %x65 / %x45            ; e E
118        exp = e [ minus / plus ] 1*DIGIT
119        frac = decimal-point 1*DIGIT
120        int = zero / ( digit1-9 *DIGIT )
121        minus = %x2D               ; -
122        plus = %x2B                ; +
123        zero = %x30                ; 0 
124        """     
125        r"""
126        >>> demo_validate_number(',-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,')
127        Input data   : ,-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,
128        Minus        : _1_11_1_____1___1___1____1_______1_______1_________________________
129        Zero         : _________11__11__1___1____1___11___________1______1__1__1__________
130        Digit_1_9    : __________________________________111_111____111____1____111111111_
131        Digit_0_9    : __________________________________111_111____111____1____111111111_
132        Decimal_Point: __________________1___1____1_________1______1______________________
133        E_e          : _______________________1____1______________________1_______________
134        Plus_Minus   : _1_11_1_____1___1___1____1_______1_______1______1_____1____________
135        EOF_Mask     : 1111111111111111111111111111111111111111111111111111111111111111111_
136        Errors       : __1_1__1__1___1____1___1____1__1_________1______1_____1__1_________
137        <BLANKLINE>
138        """ 
139        r"""
140        >>> demo_validate_number(',-,--,-a,00,-00,-0.,-0.e,-0.E,00,-123.456-,0.456+,0e10+,0123456789,')
141        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,
142        Minus        : _________________________________1_______________1______________1________________________1__________________________________
143        Zero         : _1_______________1_______1____________11____11____11__________1____________1_1_________________________1_____________1______
144        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_
145        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_
146        Decimal_Point: __1____1____1_____________1__________________________________________1________1_______________1_____________________________
147        E_e          : ______________________1_____1___1____1____1_____1_______________________________________1_______________1_______________1___
148        Plus_Minus   : _________________________________1_________1_____1______________1________________________1_______________1__________________
149        EOF_Mask     : 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111_
150        Errors       : ____________________________________________________________________________________________________________________________
151        <BLANKLINE>
152        """     
153        r"""
154        >>> demo_validate_number(',012345,12345,0,00,-0,-00')
155        Input data   : ,012345,12345,0,00,-0,-00
156        Minus        : ___________________1__1__
157        Zero         : _1____________1_11__1__11
158        Digit_1_9    : __11111_11111____________
159        Digit_0_9    : __11111_11111____________
160        Decimal_Point: _________________________
161        E_e          : _________________________
162        Plus_Minus   : ___________________1__1__
163        EOF_Mask     : 1111111111111111111111111_
164        Errors       : __1______________1______1
165        <BLANKLINE>
166        """ 
167        global lgth
168        lgth = len(data)
169
170        (bit, EOF_mask) = bitutil.transpose_streams(data)
171        (lex) = byteclass.classify_bytes(bit)
172        Errors = validate_number(lex,EOF_mask)
173
174        bitutil.print_aligned_streams([('Input data', data), 
175                              ('Minus', bitutil.bitstream2string(lex.Minus, lgth)),
176                              ('Zero', bitutil.bitstream2string(lex.Zero, lgth)),
177                              ('Digit_1_9', bitutil.bitstream2string(lex.Digit_1_9, lgth)),
178                              ('Digit_0_9', bitutil.bitstream2string(lex.Digit_1_9, lgth)),
179                              ('Decimal_Point', bitutil.bitstream2string(lex.Decimal_Point, lgth)),
180                              ('E_e', bitutil.bitstream2string(lex.E_e, lgth)),
181                              ('Plus_Minus', bitutil.bitstream2string(lex.Plus_Minus, lgth)),
182                              ('EOF_Mask', bitutil.bitstream2string(EOF_mask, lgth+1)),
183                              ('Errors', bitutil.bitstream2string(Errors, lgth))])
184if __name__ == "__main__":
185        import doctest
186        doctest.testmod()
187
188        if len(sys.argv) < 1:
189                sys.stderr.write("Usage: " + filename + "\n")
190                sys.exit(2)
191
192        data = bitutil.readfile(sys.argv[1]) 
193        demo_validate_number(data)
194       
Note: See TracBrowser for help on using the repository browser.