1"""Samples showing the parsing of common programming-language constructs
2
3numbers
4    integers
5        int
6        int_unsigned
7
8    hexidecimal integers
9        hex
10
11    floats (including exponents, requring a '.' in the literal)
12        float
13            floats, with optional integer-only exponents
14        float_floatexp
15            floats, with optional integer or float exponents
16
17    imaginary_number
18        (float/int),[jJ]
19
20    number
21        hex/float/int
22    number_full
23        binary_number/imaginary_number/hex/float/int
24
25    binary_number
26        signed binary number
27            1001001b or 1001001B bit-field format,
28            optional sign
29            can be used with number as (binary_number/number)
30
31Interpreters:
32
33    IntInterpreter
34        int, int_unsigned
35    HexInterpreter
36        hex
37    FloatInterpreter
38        float
39    FloatFloatExpInterpreter
40        float_floatexp
41    BinaryInterpreter
42        binary_number
43    ImaginaryInterpreter
44        imaginary_number
45
46"""
47from simpleparse.parser import Parser
48from simpleparse import common, objectgenerator
49from simpleparse.common import chartypes
50from simpleparse.dispatchprocessor import *
51
52c = {}
53
54declaration = r"""
55# sample for parsing integer and float numbers
56# including hexidecimal numbers in 0xFFF format
57sign             := [-+]+
58
59<l_digits>          := digits
60<l_hexdigits>       := hexdigits
61
62decimal_fraction    := '.',int_unsigned?
63
64# float which is explicitly a float, cannot be an integer
65# because it includes a decimal point
66explicit_base       := sign?, ((int_unsigned, decimal_fraction) / decimal_fraction / (int_unsigned,'.'))
67
68exponent            := int
69exponent_loose      := explicit_base/int
70
71float               := explicit_base, ([eE],exponent)?
72float_floatexp      := explicit_base, ([eE],exponent_loose)?
73
74hex                 := sign?, '0', [xX], hexdigits
75int_unsigned        := l_digits
76int                 := sign?, l_digits
77binary_digits       := [01]+
78binary_number       := sign?, binary_digits,('b'/'B')
79
80imaginary_number    := (float/int), [jJ]
81
82##number            := binary_number/hex/float/int
83number              := hex/float/int
84number_full         := binary_number/imaginary_number/hex/float/int
85"""
86
87_p = Parser( declaration )
88for name in ["int","hex", "int_unsigned", "number", "float", "binary_number", "float_floatexp", "imaginary_number", "number_full"]:
89    c[ name ] = objectgenerator.LibraryElement(
90        generator = _p._generator,
91        production = name,
92    )
93
94if __name__ == "__main__":
95    test()
96
97common.share( c )
98
99def _toInt( s, base ):
100    try:
101        return int( s, base)
102    except TypeError:
103        return int( s, base)
104def _toLong( s, base ):
105    return int( s, base)
106
107class IntInterpreter(DispatchProcessor):
108    """Interpret an integer (or unsigned integer) string as an integer"""
109    def __call__( self, info, buffer):
110        (tag, left, right, children) = info
111        try:
112            return _toInt( buffer[left:right], 10)
113        except ValueError:
114            return _toLong( buffer[left:right], 10)
115class HexInterpreter(DispatchProcessor):
116    """Interpret a hexidecimal integer string as an integer value"""
117    def __call__( self, info, buffer):
118        (tag, left, right, children) = info
119        try:
120            return _toInt( buffer[left:right], 16)
121        except ValueError:
122            return _toLong( buffer[left:right], 16)
123
124class FloatFloatExpInterpreter(DispatchProcessor):
125    """Interpret a float string as an integer value
126    Note: we're allowing float exponentiation, which
127    gives you a nice way to write 2e.5
128    """
129    def __call__( self, info, buffer):
130        (tag, left, right, children) = info
131        tag, l, r, _ = children[0]
132        base = float( buffer[l:r] )
133        if len(children) > 1:
134            # figure out the exponent...
135            exp = children[1]
136            exp = buffer[ exp[1]:exp[2]]
137##			import pdb
138##			pdb.set_trace()
139            exp = float( exp )
140
141            base = base * (10** exp)
142        return base
143class FloatInterpreter(DispatchProcessor):
144    """Interpret a standard float value as a float"""
145    def __call__( self, info, buffer):
146        (tag, left, right, children) = info
147        return float( buffer[left:right])
148
149import sys
150if hasattr( sys,'version_info') and sys.version_info[:2] > (2,0):
151    class BinaryInterpreter(DispatchProcessor):
152        def __call__( self, info, buffer):
153            """Interpret a bitfield set as an integer"""
154            (tag, left, right, children) = info
155            return _toInt( buffer[left:right-1], 2)
156else:
157    class BinaryInterpreter(DispatchProcessor):
158        def __call__( self, info, buffer):
159            """Interpret a bitfield set as an integer, not sure this algo
160            is correct, will see I suppose"""
161            (tag, left, right, children) = info
162            sign = 1
163            if len(children) > 2:
164                s = children[0]
165                for schar in buffer[s[1]:s[2]]:
166                    if schar == '-':
167                        sign = sign * -1
168                bits = buffer[children[1][1]:children[1][2]]
169            else:
170                bits = buffer[children[0][1]:children[0][2]]
171            value = 0
172            for bit in bits:
173                value = (value << 1)
174                if bit == '1':
175                    value = value + 1
176            return value
177
178class ImaginaryInterpreter( DispatchProcessor ):
179    map = {
180        "float":FloatInterpreter(),
181        "int":IntInterpreter()
182    }
183    def __call__( self, info, buffer):
184        """Interpret a bitfield set as an integer, not sure this algo
185        is correct, will see I suppose"""
186        (tag, left, right, children) = info
187        base = children[0]
188        base = self.mapSet[base[0]](base, buffer)
189        return base * 1j
190
191