Skip to content

Commit

Permalink
Handle fractions
Browse files Browse the repository at this point in the history
  • Loading branch information
swaroopch authored and bfontaine committed Aug 24, 2018
1 parent 7a3865c commit eec8248
Show file tree
Hide file tree
Showing 4 changed files with 23 additions and 5 deletions.
3 changes: 3 additions & 0 deletions edn_format/edn_dump.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import datetime
import decimal
import fractions
import itertools
import re
import sys
Expand Down Expand Up @@ -105,6 +106,8 @@ def udump(obj,
pairs = ((Keyword(k) if isinstance(k, (bytes, basestring)) else k, v) for k, v in pairs)

return '{{{}}}'.format(seq(itertools.chain.from_iterable(pairs), **kwargs))
elif isinstance(obj, fractions.Fraction):
return str(obj)
elif isinstance(obj, datetime.datetime):
return '#inst "{}"'.format(pyrfc3339.generate(obj, microseconds=True))
elif isinstance(obj, datetime.date):
Expand Down
4 changes: 2 additions & 2 deletions edn_format/edn_lex.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ def __str__(self):
'BOOLEAN',
'INTEGER',
'FLOAT',
'DIVIDE',
'SYMBOL',
'KEYWORD',
'VECTOR_START',
Expand Down Expand Up @@ -124,8 +125,6 @@ def __str__(self):
r"\/"
"[{all}]+"
"|"
r"\/"
"|"
"{start}"
"[{all}]*"
")").format(**PARTS)
Expand All @@ -147,6 +146,7 @@ def __str__(self):
"[{all}]*"
")").format(**PARTS)

t_DIVIDE = r'\/'
t_VECTOR_START = r'\['
t_VECTOR_END = r'\]'
t_LIST_START = r'\('
Expand Down
10 changes: 9 additions & 1 deletion edn_format/edn_parse.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
from __future__ import absolute_import, division, print_function, unicode_literals

import datetime
import fractions
import sys
import uuid

Expand Down Expand Up @@ -52,7 +53,8 @@ def p_term_leaf(p):
| NIL
| KEYWORD
| SYMBOL
| WHITESPACE"""
| WHITESPACE
| DIVIDE"""
p[0] = p[1]


Expand Down Expand Up @@ -91,6 +93,11 @@ def p_empty_map(p):
p[0] = ImmutableDict({})


def p_fraction(p):
"""fraction : INTEGER DIVIDE INTEGER"""
p[0] = fractions.Fraction(p[1], p[3])


def p_map(p):
"""map : MAP_START expressions MAP_OR_SET_END"""
terms = p[2]
Expand All @@ -115,6 +122,7 @@ def p_expression(p):
| list
| set
| map
| fraction
| term"""
p[0] = p[1]

Expand Down
11 changes: 9 additions & 2 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
from uuid import uuid4
import random
import datetime
import fractions
import unittest

import pytz

from edn_format import edn_lex, edn_parse, \
Expand Down Expand Up @@ -58,14 +58,15 @@ def test_lexer(self):
"abc")
self.check_lex("[LexToken(SYMBOL,Symbol(?abc),1,0)]",
"?abc")
self.check_lex("[LexToken(SYMBOL,Symbol(/),1,0)]",
self.check_lex("[LexToken(DIVIDE,'/',1,0)]",
"/")
self.check_lex("[LexToken(SYMBOL,Symbol(prefix/name),1,0)]",
"prefix/name")
self.check_lex("[LexToken(SYMBOL,Symbol(true.),1,0)]",
"true.")
self.check_lex("[LexToken(SYMBOL,Symbol($:ABC?),1,0)]",
"$:ABC?")

self.check_lex("[LexToken(MAP_START,'{',1,0), "
"LexToken(KEYWORD,Keyword(a),1,2), "
"LexToken(BOOLEAN,False,1,5), "
Expand All @@ -74,6 +75,11 @@ def test_lexer(self):
"LexToken(MAP_OR_SET_END,'}',1,21)]",
"{ :a false, :b false }")

self.check_lex(("[LexToken(INTEGER,2,1,0), "
"LexToken(DIVIDE,'/',1,1), "
"LexToken(INTEGER,3,1,2)]"),
"2/3")

def check_parse(self, expected_output, actual_input):
self.assertEqual(expected_output, edn_parse.parse(actual_input))

Expand Down Expand Up @@ -129,6 +135,7 @@ def test_parser(self):
self.check_parse(frozenset({ImmutableList([u"ab", u"cd"]),
ImmutableList([u"ef"])}),
'#{["ab", "cd"], ["ef"]}')
self.check_parse(fractions.Fraction(2, 3), "2/3")

def check_roundtrip(self, data_input, **kw):
self.assertEqual(data_input, loads(dumps(data_input, **kw)))
Expand Down

0 comments on commit eec8248

Please sign in to comment.