tomland 1.1.0.0 → 1.1.0.1
raw patch · 11 files changed
+595/−2 lines, 11 filesdep +directorydep ~parser-combinatorsPVP ok
version bump matches the API change (PVP)
Dependencies added: directory
Dependency ranges changed: parser-combinators
API changes (from Hackage documentation)
Files
- CHANGELOG.md +6/−0
- src/Toml/Parser/TOML.hs +1/−1
- test/Test/Toml/Parsing/Examples.hs +21/−0
- test/Test/Toml/Parsing/Unit.hs +8/−0
- test/examples/example-v0.3.0.toml +182/−0
- test/examples/example-v0.4.0.toml +244/−0
- test/examples/example.toml +47/−0
- test/examples/fruit.toml +13/−0
- test/examples/hard_example.toml +33/−0
- test/examples/hard_example_unicode.toml +36/−0
- tomland.cabal +4/−1
CHANGELOG.md view
@@ -3,6 +3,12 @@ tomland uses [PVP Versioning][1]. The changelog is available [on GitHub][2]. +## 1.1.0.1 — Jul 10, 2019++* [#206](https://github.com/kowainik/tomland/issues/206):+ Fix in parser of inline tables inside tables, add tests for official TOML examples+ (by [@jiegillet](https://github.com/jiegillet))+ ## 1.1.0.0 — Jul 8, 2019 * [#154](https://github.com/kowainik/tomland/issues/154):
src/Toml/Parser/TOML.hs view
@@ -101,7 +101,7 @@ -- | Parser for a toml under a certain key localTomlP :: Maybe Key -> Parser TOML-localTomlP key = mconcat <$> many (subArray <|> subTable <|> hasKeyP key)+localTomlP key = mconcat <$> many (subArray <|> subTable <|> (try $ hasKeyP key)) where subTable :: Parser TOML subTable = do
+ test/Test/Toml/Parsing/Examples.hs view
@@ -0,0 +1,21 @@+module Test.Toml.Parsing.Examples where++import Data.Either (isRight)+import System.Directory (listDirectory)+import Test.Tasty.Hspec (Spec, describe, it, runIO, shouldBe)+import Toml.Parser (parse)++import qualified Data.Text.IO as TIO++spec_Examples :: Spec+spec_Examples = describe "Can parse official TOML examples" $ do+ files <- runIO $ listDirectory exampleDir+ mapM_ example files++example :: FilePath -> Spec+example file = it ("can parse file " ++ file) $ do+ toml <- TIO.readFile (exampleDir ++ file)+ isRight (parse toml) `shouldBe` True++exampleDir :: FilePath+exampleDir = "test/examples/"
test/Test/Toml/Parsing/Unit.hs view
@@ -395,6 +395,14 @@ (tomlFromTable [(makeKey ["table"], tomlFromKeyVal [str, int])]) it "can parse an empty inline TOML table" $ parseToml "table = {}" (tomlFromTable [(makeKey ["table"], mempty)])+ it "can parse a table followed by an inline table" $+ parseToml "[table1] \n key1 = \"some string\" \n table2 = {key2 = 123}"+ (tomlFromTable [(makeKey ["table1"], tomlFromKeyVal [str])+ ,(makeKey ["table2"], tomlFromKeyVal [int])])+ it "can parse an empty table followed by an inline table" $+ parseToml "[table1] \n table2 = {key2 = 123}"+ (tomlFromTable [(makeKey ["table1"], mempty)+ ,(makeKey ["table2"], tomlFromKeyVal [int])]) it "allows the name of the table to be any valid TOML key" $ do parseToml "dog.\"tater.man\"={}" (tomlFromTable [(makeKey ["dog", dquote "tater.man"], mempty)])
+ test/examples/example-v0.3.0.toml view
@@ -0,0 +1,182 @@+# Comment+# I am a comment. Hear me roar. Roar.++# Table+# Tables (also known as hash tables or dictionaries) are collections of key/value pairs.+# They appear in square brackets on a line by themselves.++[Table]++key = "value" # Yeah, you can do this.++# Nested tables are denoted by table names with dots in them. Name your tables whatever crap you please, just don't use #, ., [ or ].++[dog.tater]+type = "pug"++# You don't need to specify all the super-tables if you don't want to. TOML knows how to do it for you.++# [x] you+# [x.y] don't+# [x.y.z] need these+[x.y.z.w] # for this to work++# String+# There are four ways to express strings: basic, multi-line basic, literal, and multi-line literal.+# All strings must contain only valid UTF-8 characters.++[String]+basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."++[String.Multiline]++# The following strings are byte-for-byte equivalent:+key1 = "One\nTwo"+key2 = """One\nTwo"""+key3 = """+One+Two"""++[String.Multilined.Singleline]++# The following strings are byte-for-byte equivalent:+key1 = "The quick brown fox jumps over the lazy dog."++key2 = """+The quick brown \+++ fox jumps over \+ the lazy dog."""++key3 = """\+ The quick brown \+ fox jumps over \+ the lazy dog.\+ """++[String.Literal]++# What you see is what you get.+winpath = 'C:\Users\nodejs\templates'+winpath2 = '\\ServerX\admin$\system32\'+quoted = 'Tom "Dubs" Preston-Werner'+regex = '<\i\c*\s*>'+++[String.Literal.Multiline]++regex2 = '''I [dw]on't need \d{2} apples'''+lines = '''+The first newline is+trimmed in raw strings.+ All other whitespace+ is preserved.+'''++# Integer+# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.+# Negative numbers are prefixed with a minus sign.++[Integer]+key1 = +99+key2 = 42+key3 = 0+key4 = -17++# Float+# A float consists of an integer part (which may be prefixed with a plus or minus sign)+# followed by a fractional part and/or an exponent part.++[Float.fractional]++# fractional+key1 = +1.0+key2 = 3.1415+key3 = -0.01++[Float.exponent]++# exponent+key1 = 5e+22+key2 = 1e6+key3 = -2E-2++[Float.both]++# both+key = 6.626e-34++# Boolean+# Booleans are just the tokens you're used to. Always lowercase.++[Booleans]+True = true+False = false++# Datetime+# Datetimes are RFC 3339 dates.++[Datetime]+key1 = 1979-05-27T07:32:00Z+key2 = 1979-05-27T00:32:00-07:00+key3 = 1979-05-27T00:32:00.999999-07:00++# Array+# Arrays are square brackets with other primitives inside. Whitespace is ignored. Elements are separated by commas. Data types may not be mixed.++[Array]+key1 = [ 1, 2, 3 ]+key2 = [ "red", "yellow", "green" ]+key3 = [ [ 1, 2 ], [3, 4, 5] ]+key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok++#Arrays can also be multiline. So in addition to ignoring whitespace, arrays also ignore newlines between the brackets.+# Terminating commas are ok before the closing bracket.++key5 = [+ 1, 2, 3+]+key6 = [+ 1,+ 2, # this is ok+]++# Array of Tables+# These can be expressed by using a table name in double brackets.+# Each table with the same double bracketed name will be an element in the array.+# The tables are inserted in the order encountered.++[[products]]+name = "Hammer"+sku = 738594937++[[products]]++[[products]]+name = "Nail"+sku = 284758393+color = "gray"+++# You can create nested arrays of tables as well.++[[fruit]]+ name = "apple"++ [fruit.physical]+ color = "red"+ shape = "round"++ [[fruit.variety]]+ name = "red delicious"++ [[fruit.variety]]+ name = "granny smith"++[[fruit]]+ name = "banana"++ [[fruit.variety]]+ name = "plantain"+
+ test/examples/example-v0.4.0.toml view
@@ -0,0 +1,244 @@+################################################################################+## Comment++# Speak your mind with the hash symbol. They go from the symbol to the end of+# the line.+++################################################################################+## Table++# Tables (also known as hash tables or dictionaries) are collections of+# key/value pairs. They appear in square brackets on a line by themselves.++[table]++key = "value" # Yeah, you can do this.++# Nested tables are denoted by table names with dots in them. Name your tables+# whatever crap you please, just don't use #, ., [ or ].++[table.subtable]++key = "another value"++# You don't need to specify all the super-tables if you don't want to. TOML+# knows how to do it for you.++# [x] you+# [x.y] don't+# [x.y.z] need these+[x.y.z.w] # for this to work+++################################################################################+## Inline Table++# Inline tables provide a more compact syntax for expressing tables. They are+# especially useful for grouped data that can otherwise quickly become verbose.+# Inline tables are enclosed in curly braces `{` and `}`. No newlines are+# allowed between the curly braces unless they are valid within a value.++[table.inline]++name = { first = "Tom", last = "Preston-Werner" }+point = { x = 1, y = 2 }+++################################################################################+## String++# There are four ways to express strings: basic, multi-line basic, literal, and+# multi-line literal. All strings must contain only valid UTF-8 characters.++[string.basic]++basic = "I'm a string. \"You can quote me\". Name\tJos\u00E9\nLocation\tSF."++[string.multiline]++# The following strings are byte-for-byte equivalent:+key1 = "One\nTwo"+key2 = """One\nTwo"""+key3 = """+One+Two"""++[string.multiline.continued]++# The following strings are byte-for-byte equivalent:+key1 = "The quick brown fox jumps over the lazy dog."++key2 = """+The quick brown \+++ fox jumps over \+ the lazy dog."""++key3 = """\+ The quick brown \+ fox jumps over \+ the lazy dog.\+ """++[string.literal]++# What you see is what you get.+winpath = 'C:\Users\nodejs\templates'+winpath2 = '\\ServerX\admin$\system32\'+quoted = 'Tom "Dubs" Preston-Werner'+regex = '<\i\c*\s*>'+++[string.literal.multiline]++regex2 = '''I [dw]on't need \d{2} apples'''+lines = '''+The first newline is+trimmed in raw strings.+ All other whitespace+ is preserved.+'''+++################################################################################+## Integer++# Integers are whole numbers. Positive numbers may be prefixed with a plus sign.+# Negative numbers are prefixed with a minus sign.++[integer]++key1 = +99+key2 = 42+key3 = 0+key4 = -17++[integer.underscores]++# For large numbers, you may use underscores to enhance readability. Each+# underscore must be surrounded by at least one digit.+key1 = 1_000+key2 = 5_349_221+key3 = 1_2_3_4_5 # valid but inadvisable+++################################################################################+## Float++# A float consists of an integer part (which may be prefixed with a plus or+# minus sign) followed by a fractional part and/or an exponent part.++[float.fractional]++key1 = +1.0+key2 = 3.1415+key3 = -0.01++[float.exponent]++key1 = 5e+22+key2 = 1e6+key3 = -2E-2++[float.both]++key = 6.626e-34++[float.underscores]++key1 = 9_224_617.445_991_228_313+key2 = 1e1_000+++################################################################################+## Boolean++# Booleans are just the tokens you're used to. Always lowercase.++[boolean]++True = true+False = false+++################################################################################+## Datetime++# Datetimes are RFC 3339 dates.++[datetime]++key1 = 1979-05-27T07:32:00Z+key2 = 1979-05-27T00:32:00-07:00+key3 = 1979-05-27T00:32:00.999999-07:00+++################################################################################+## Array++# Arrays are square brackets with other primitives inside. Whitespace is+# ignored. Elements are separated by commas. Data types may not be mixed.++[array]++key1 = [ 1, 2, 3 ]+key2 = [ "red", "yellow", "green" ]+key3 = [ [ 1, 2 ], [3, 4, 5] ]+key4 = [ [ 1, 2 ], ["a", "b", "c"] ] # this is ok++# Arrays can also be multiline. So in addition to ignoring whitespace, arrays+# also ignore newlines between the brackets. Terminating commas are ok before+# the closing bracket.++key5 = [+ 1, 2, 3+]+key6 = [+ 1,+ 2, # this is ok+]+++################################################################################+## Array of Tables++# These can be expressed by using a table name in double brackets. Each table+# with the same double bracketed name will be an element in the array. The+# tables are inserted in the order encountered.++[[products]]++name = "Hammer"+sku = 738594937++[[products]]++[[products]]++name = "Nail"+sku = 284758393+color = "gray"+++# You can create nested arrays of tables as well.++[[fruit]]+ name = "apple"++ [fruit.physical]+ color = "red"+ shape = "round"++ [[fruit.variety]]+ name = "red delicious"++ [[fruit.variety]]+ name = "granny smith"++[[fruit]]+ name = "banana"++ [[fruit.variety]]+ name = "plantain"
+ test/examples/example.toml view
@@ -0,0 +1,47 @@+# This is a TOML document. Boom.++title = "TOML Example"++[owner]+name = "Tom Preston-Werner"+organization = "GitHub"+bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."+dob = 1979-05-27T07:32:00Z # First class dates? Why not?++[database]+server = "192.168.1.1"+ports = [ 8001, 8001, 8002 ]+connection_max = 5000+enabled = true++[servers]++ # You can indent as you please. Tabs or spaces. TOML don't care.+ [servers.alpha]+ ip = "10.0.0.1"+ dc = "eqdc10"++ [servers.beta]+ ip = "10.0.0.2"+ dc = "eqdc10"+ country = "中国" # This should be parsed as UTF-8++[clients]+data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it++# Line breaks are OK when inside arrays+hosts = [+ "alpha",+ "omega"+]++# Products++ [[products]]+ name = "Hammer"+ sku = 738594937++ [[products]]+ name = "Nail"+ sku = 284758393+ color = "gray"
+ test/examples/fruit.toml view
@@ -0,0 +1,13 @@+[[fruit.blah]]+ name = "apple"++ [fruit.blah.physical]+ color = "red"+ shape = "round"++[[fruit.blah]]+ name = "banana"++ [fruit.blah.physical]+ color = "yellow"+ shape = "bent"
+ test/examples/hard_example.toml view
@@ -0,0 +1,33 @@+# Test file for TOML+# Only this one tries to emulate a TOML file written by a user of the kind of parser writers probably hate+# This part you'll really hate++[the]+test_string = "You'll hate me after this - #" # " Annoying, isn't it?++ [the.hard]+ test_array = [ "] ", " # "] # ] There you go, parse this!+ test_array2 = [ "Test #11 ]proved that", "Experiment #9 was a success" ]+ # You didn't think it'd as easy as chucking out the last #, did you?+ another_test_string = " Same thing, but with a string #"+ harder_test_string = " And when \"'s are in the string, along with # \"" # "and comments are there too"+ # Things will get harder++ [the.hard."bit#"]+ "what?" = "You don't think some user won't do that?"+ multi_line_array = [+ "]",+ # ] Oh yes I did+ ]++# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test++#[error] if you didn't catch this, your parser is broken+#string = "Anything other than tabs, spaces and newline after a keygroup or key value pair has ended should produce an error unless it is a comment" like this+#array = [+# "This might most likely happen in multiline arrays",+# Like here,+# "or here,+# and here"+# ] End of array comment, forgot the #+#number = 3.14 pi <--again forgot the #
+ test/examples/hard_example_unicode.toml view
@@ -0,0 +1,36 @@+# Tèƨƭ ƒïℓè ƒôř TÓM£++# Óñℓ¥ ƭλïƨ ôñè ƭřïèƨ ƭô è₥úℓáƭè á TÓM£ ƒïℓè ωřïƭƭèñ β¥ á úƨèř ôƒ ƭλè ƙïñδ ôƒ ƥářƨèř ωřïƭèřƨ ƥřôβáβℓ¥ λáƭè+# Tλïƨ ƥářƭ ¥ôú'ℓℓ řèáℓℓ¥ λáƭè++[the]+test_string = "Ýôú'ℓℓ λáƭè ₥è áƒƭèř ƭλïƨ - #" # " Âññô¥ïñϱ, ïƨñ'ƭ ïƭ?+++ [the.hard]+ test_array = [ "] ", " # "] # ] Tλèřè ¥ôú ϱô, ƥářƨè ƭλïƨ!+ test_array2 = [ "Tèƨƭ #11 ]ƥřôƲèδ ƭλáƭ", "Éжƥèřï₥èñƭ #9 ωáƨ á ƨúççèƨƨ" ]+ # Ýôú δïδñ'ƭ ƭλïñƙ ïƭ'δ áƨ èáƨ¥ áƨ çλúçƙïñϱ ôúƭ ƭλè ℓáƨƭ #, δïδ ¥ôú?+ another_test_string = "§á₥è ƭλïñϱ, βúƭ ωïƭλ á ƨƭřïñϱ #"+ harder_test_string = " Âñδ ωλèñ \"'ƨ ářè ïñ ƭλè ƨƭřïñϱ, áℓôñϱ ωïƭλ # \"" # "áñδ çô₥₥èñƭƨ ářè ƭλèřè ƭôô"+ # Tλïñϱƨ ωïℓℓ ϱèƭ λářδèř++ [the.hard."βïƭ#"]+ "ωλáƭ?" = "Ýôú δôñ'ƭ ƭλïñƙ ƨô₥è úƨèř ωôñ'ƭ δô ƭλáƭ?"+ multi_line_array = [+ "]",+ # ] Óλ ¥èƨ Ì δïδ+ ]++# Each of the following keygroups/key value pairs should produce an error. Uncomment to them to test++#[error] ïƒ ¥ôú δïδñ'ƭ çáƭçλ ƭλïƨ, ¥ôúř ƥářƨèř ïƨ βřôƙèñ+#string = "Âñ¥ƭλïñϱ ôƭλèř ƭλáñ ƭáβƨ, ƨƥáçèƨ áñδ ñèωℓïñè áƒƭèř á ƙè¥ϱřôúƥ ôř ƙè¥ Ʋáℓúè ƥáïř λáƨ èñδèδ ƨλôúℓδ ƥřôδúçè áñ èřřôř úñℓèƨƨ ïƭ ïƨ á çô₥₥èñƭ" ℓïƙè ƭλïƨ++#array = [+# "Tλïƨ ₥ïϱλƭ ₥ôƨƭ ℓïƙèℓ¥ λáƥƥèñ ïñ ₥úℓƭïℓïñè ářřá¥ƨ",+# £ïƙè λèřè,+# "ôř λèřè,+# áñδ λèřè"+# ] Éñδ ôƒ ářřᥠçô₥₥èñƭ, ƒôřϱôƭ ƭλè #+#number = 3.14 ƥï <--áϱáïñ ƒôřϱôƭ ƭλè #
tomland.cabal view
@@ -1,6 +1,6 @@ cabal-version: 2.4 name: tomland-version: 1.1.0.0+version: 1.1.0.1 synopsis: Bidirectional TOML serialization description: Implementation of bidirectional TOML serialization. Simple codecs look like this:@@ -33,6 +33,7 @@ extra-doc-files: README.md , CHANGELOG.md extra-source-files: test/golden/*.golden+ , test/examples/*.toml tested-with: GHC == 8.2.2 , GHC == 8.4.4 , GHC == 8.6.5@@ -132,6 +133,7 @@ Test.Toml.Property Test.Toml.Parsing.Property Test.Toml.Parsing.Unit+ Test.Toml.Parsing.Examples Test.Toml.PrefixTree.Property Test.Toml.PrefixTree.Unit Test.Toml.Printer.Golden@@ -148,6 +150,7 @@ , tasty-hedgehog ^>= 1.0.0.0 , tasty-hspec ^>= 1.1.5.1 , tasty-silver ^>= 3.1.11+ , directory ^>= 1.3 , text , time , tomland