"""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
syntax highlighted by Code2HTML, v. 0.9.1