diff --git a/Makefile b/Makefile index 7387f15..e604e1f 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ all: @echo "" -dev: test flake tox +dev: test flake test: nosetests -sv @@ -32,4 +32,4 @@ d: clear dev diff: git diff --color | less -r -r: d diff +r: d tox diff diff --git a/hy/lex/states.py b/hy/lex/states.py index 5ccac85..d6b06bc 100644 --- a/hy/lex/states.py +++ b/hy/lex/states.py @@ -22,6 +22,7 @@ from hy.models.expression import HyExpression from hy.models.integer import HyInteger from hy.models.symbol import HySymbol from hy.models.string import HyString +from hy.models.dict import HyDict from hy.models.list import HyList from hy.errors import HyError @@ -121,6 +122,10 @@ class ListeyThing(State): self.machine.sub(Expression) return + if char == "{": + self.machine.sub(Dict) + return + if char == "[": self.machine.sub(List) return @@ -165,6 +170,20 @@ class Expression(ListeyThing): end_char = ")" +class Dict(ListeyThing): + """ + This state parses a Hy dict for things. + """ + + def exit(self): + self.commit() + it = iter(self.nodes) + result = dict(zip(it, it)) + self.result = HyDict(result) + + end_char = "}" + + class String(State): """ String state. This will handle stuff like: @@ -205,6 +224,9 @@ class Idle(State): if char == "(": return Expression + if char == "{": + return Dict + if char == ";": return Comment diff --git a/hy/models/dict.py b/hy/models/dict.py new file mode 100644 index 0000000..7fd9315 --- /dev/null +++ b/hy/models/dict.py @@ -0,0 +1,28 @@ +# Copyright (c) 2012 Paul Tagliamonte +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the "Software"), +# to deal in the Software without restriction, including without limitation +# the rights to use, copy, modify, merge, publish, distribute, sublicense, +# and/or sell copies of the Software, and to permit persons to whom the +# Software is furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +# THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +# DEALINGS IN THE SOFTWARE. + +from hy.models import HyObject + + +class HyDict(HyObject, dict): + """ + HyDict (just a dict) + """ + pass diff --git a/tests/lex/test_lex.py b/tests/lex/test_lex.py index 6a553fd..0fd33e2 100644 --- a/tests/lex/test_lex.py +++ b/tests/lex/test_lex.py @@ -22,6 +22,7 @@ from hy.models.expression import HyExpression from hy.models.integer import HyInteger from hy.models.symbol import HySymbol from hy.models.string import HyString +from hy.models.dict import HyDict from hy.lex.states import LexException @@ -115,3 +116,12 @@ def test_lex_line_counting_multi_inner(): assert inner.start_line == 2 assert inner.start_column == 5 + + +def tgest_dicts(): + """ Ensure that we can tokenize a dict. """ + objs = tokenize("{foo bar bar baz}") + assert objs == [HyDict({ + "foo": "bar", + "bar": "baz" + })]