swaroopch / edn_format

EDN reader and writer implementation in Python, using PLY (lex, yacc)
https://swaroopch.com/2012/12/24/edn-format-python/
Other
131 stars 31 forks source link

Cannot correctly parse exact precision floats #67

Closed gabrielferreira95 closed 4 years ago

gabrielferreira95 commented 4 years ago

When parsing exact precision floats that do not contain the dot (e.g. 12M, 1M or 0M), the parser considers only the integer part and the output is an int instead of a Decimal.

Example of this behaviour:

>>> from edn_format import loads

>>> loads('1M')
1

>>> loads('{:a 1M}')
---------------------------------------------------------------------------
EDNDecodeError                            Traceback (most recent call last)
<ipython-input-5-94ea5fa6da57> in <module>
----> 1 loads('{:a 1M}')

~/miniconda3/envs/nucli-edn_format/lib/python3.6/site-packages/edn_format/edn_parse.py in parse(text, input_encoding)
    201     Parse one object from the text. Return None if the text is empty.
    202     """
--> 203     expressions = parse_all(text, input_encoding=input_encoding)
    204     return expressions[0] if expressions else None

~/miniconda3/envs/nucli-edn_format/lib/python3.6/site-packages/edn_format/edn_parse.py in parse_all(text, input_encoding)
    193         kwargs = dict(debug=True)
    194     p = ply.yacc.yacc(**kwargs)
--> 195     expressions = p.parse(text, lexer=lex())
    196     return list(expressions)
    197

~/miniconda3/envs/nucli-edn_format/lib/python3.6/site-packages/ply/yacc.py in parse(self, input, lexer, debug, tracking, tokenfunc)
    331             return self.parseopt(input, lexer, debug, tracking, tokenfunc)
    332         else:
--> 333             return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
    334
    335

~/miniconda3/envs/nucli-edn_format/lib/python3.6/site-packages/ply/yacc.py in parseopt_notrack(self, input, lexer, debug, tracking, tokenfunc)
   1118                             del symstack[-plen:]
   1119                             self.state = state
-> 1120                             p.callable(pslice)
   1121                             del statestack[-plen:]
   1122                             symstack.append(sym)

~/miniconda3/envs/nucli-edn_format/lib/python3.6/site-packages/edn_format/edn_parse.py in p_map(p)
    107     terms = p[2]
    108     if len(terms) % 2 != 0:
--> 109         raise EDNDecodeError('Even number of terms required for map')
    110     # partition terms in pairs
    111     p[0] = ImmutableDict((terms[i], terms[i+1]) for i in range(0, len(terms), 2))

EDNDecodeError: Even number of terms required for map

Another wrong behavior (it apparently interprets 1M as 1 M):

>>> loads('{:a 1M :b}')

{Keyword(a): 1, Symbol(M): Keyword(b)}

Expected behaviour:

>>> from edn_format import loads

>>> loads('1M')
Decimal('1')

>>> loads('{:a 1M}')
{Keyword(a): Decimal('1')}