File: numbers.py

package info (click to toggle)
simpleparse 2.1.0a1-6
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 2,776 kB
  • ctags: 4,332
  • sloc: python: 7,036; ansic: 6,395; makefile: 22
file content (187 lines) | stat: -rwxr-xr-x 5,087 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
"""Samples showing the parsing of common programming-language constructs

numbers
	integers
		int
		int_unsigned
		
	hexidecimal integers
		hex
		
	floats (including exponents, requring a '.' in the literal)
		float
			floats, with optional integer-only exponents
		float_floatexp
			floats, with optional integer or float exponents

	imaginary_number
		(float/int),[jJ]

	number
		hex/float/int
	number_full
		binary_number/imaginary_number/hex/float/int

	binary_number
		signed binary number
			1001001b or 1001001B bit-field format,
			optional sign
			can be used with number as (binary_number/number)

Interpreters:

	IntInterpreter
		int, int_unsigned
	HexInterpreter
		hex
	FloatInterpreter
		float
	FloatFloatExpInterpreter
		float_floatexp
	BinaryInterpreter
		binary_number
	ImaginaryInterpreter
		imaginary_number
	
"""
from simpleparse.parser import Parser
from simpleparse import common, objectgenerator
from simpleparse.common import chartypes
from simpleparse.dispatchprocessor import *
import string

c = {}

declaration = r"""
# sample for parsing integer and float numbers
# including hexidecimal numbers in 0xFFF format
sign             := [-+]+

<l_digits>          := digits
<l_hexdigits>       := hexdigits

decimal_fraction    := '.',int_unsigned?

# float which is explicitly a float, cannot be an integer
# because it includes a decimal point
explicit_base       := sign?, ((int_unsigned, decimal_fraction) / decimal_fraction / (int_unsigned,'.'))

exponent            := int
exponent_loose      := explicit_base/int

float               := explicit_base, ([eE],exponent)?
float_floatexp      := explicit_base, ([eE],exponent_loose)?
 
hex                 := sign?, '0', [xX], hexdigits
int_unsigned        := l_digits
int                 := sign?, l_digits
binary_digits       := [01]+
binary_number       := sign?, binary_digits,('b'/'B')

imaginary_number    := (float/int), [jJ]

##number            := binary_number/hex/float/int
number              := hex/float/int
number_full         := binary_number/imaginary_number/hex/float/int
"""

_p = Parser( declaration )
for name in ["int","hex", "int_unsigned", "number", "float", "binary_number", "float_floatexp", "imaginary_number", "number_full"]:
	c[ name ] = objectgenerator.LibraryElement(
		generator = _p._generator,
		production = name,
	)

if __name__ == "__main__":
	test()

common.share( c )

def _toInt( s, base ):
	try:
		return int( s, base)
	except TypeError:
		return string.atoi( s, base)
def _toLong( s, base ):
	try:
		return long( s, base)
	except TypeError:
		return string.atol( s, base)

class IntInterpreter(DispatchProcessor):
	"""Interpret an integer (or unsigned integer) string as an integer"""
	def __call__( self, (tag, left, right, children), buffer):
		try:
			return _toInt( buffer[left:right], 10)
		except ValueError:
			return _toLong( buffer[left:right], 10)
class HexInterpreter(DispatchProcessor):
	"""Interpret a hexidecimal integer string as an integer value"""
	def __call__( self, (tag, left, right, children), buffer):
		try:
			return _toInt( buffer[left:right], 16)
		except ValueError:
			return _toLong( buffer[left:right], 16)
		
class FloatFloatExpInterpreter(DispatchProcessor):
	"""Interpret a float string as an integer value
	Note: we're allowing float exponentiation, which
	gives you a nice way to write 2e.5
	"""
	def __call__( self, (tag, left, right, children), buffer):
		tag, l, r, _ = children[0]
		base = float( buffer[l:r] )
		if len(children) > 1:
			# figure out the exponent...
			exp = children[1]
			exp = buffer[ exp[1]:exp[2]]
##			import pdb
##			pdb.set_trace()
			exp = float( exp )
			
			base = base * (10** exp)
		return base
class FloatInterpreter(DispatchProcessor):
	"""Interpret a standard float value as a float"""
	def __call__( self, (tag, left, right, children), buffer):
		return float( buffer[left:right])

import sys
if hasattr( sys,'version_info') and sys.version_info[:2] > (2,0):
	class BinaryInterpreter(DispatchProcessor):
		def __call__( self, (tag, left, right, children), buffer):
			"""Interpret a bitfield set as an integer"""
			return _toInt( buffer[left:right-1], 2)
else:
	class BinaryInterpreter(DispatchProcessor):
		def __call__( self, (tag, left, right, children), buffer):
			"""Interpret a bitfield set as an integer, not sure this algo
			is correct, will see I suppose"""
			sign = 1
			if len(children) > 2:
				s = children[0]
				for schar in buffer[s[1]:s[2]]:
					if schar == '-':
						sign = sign * -1
				bits = buffer[children[1][1]:children[1][2]]
			else:
				bits = buffer[children[0][1]:children[0][2]]
			value = 0
			for bit in bits:
				value = (value << 1)
				if bit == '1':
					value = value + 1
			return value
		
class ImaginaryInterpreter( DispatchProcessor ):
	map = {
		"float":FloatInterpreter(),
		"int":IntInterpreter()
	}
	def __call__( self, (tag, left, right, children), buffer):
		"""Interpret a bitfield set as an integer, not sure this algo
		is correct, will see I suppose"""
		base = children[0]
		base = self.mapSet[base[0]](base, buffer)
		return base * 1j