fjoppe / Legivel

F# Yaml 1.2 parser
https://fjoppe.github.io/Legivel
The Unlicense
60 stars 5 forks source link

Typecast question #16

Closed pkese closed 4 years ago

pkese commented 5 years ago

Frank,

I'm having a schema defined like this:

type Doc = {
    t1: string list
    t2: Map<string, int>
    t3: Map<int, string>
}

And a document:

t1: [yes, maybe, no]
t2: {true: 2, false: 0, ambiguous: 1, null: -1}
t3: {1: yes, 0: maybe, -1: no}

Legivel says the document is incorrect: it can't cast yes into a string unless it is quoted even though the schema says to specifically interpret it as string. Technically it is a valid yaml document.

Is this worth pursuing / duscussing, or should I better ask my Php and Python peers, if they can fix the document by adding additional quotes?

Thanks

pkese commented 5 years ago

Another example, just to make my case, is:

type Point = { x: int; y: int; z: int }

and

point: { x: 10, y: -1, z: 3 }

fails due to y = true

fjoppe commented 5 years ago

Hi,

Looks like a typical "balance" issue in an "opiniated" parser. Is the node a string or bool?

I'd expect that adding tag !!str as in example 6.26 should do the trick. This is supported by Legivel. Though I haven't tested it for your situation (little time, sorry).

pkese commented 5 years ago

> Is the node a string or bool?

I'd say that the type definition for the Mapper unambiguously says it is a string. Maybe the tokenizer is a bit too eager.

However, I understand that this pulls in a can of worms for comparison of scalar values, etc.
Yet the boolean aliases like Yes, No, Y, N, On, Off, etc. have been omitted from Yaml 1.2 specification. Maybe we could have an option to parse the Yaml document as 1.1 or 1.2.

Anyways, I may be pushing this too far. Feel free to close the ticket. Thanks.

fjoppe commented 5 years ago

The tag !!str will mark the scalar explicitly as a string, such that it won't be 'inferred' to a bool. The mapper in the current version actually works with a few tags from a mixed set of Tag Schema's. That's why "true", "yes" are converted to bool. I think you're right in the thought that the contract should be the driver for conversion. While currently it is the "inferred" type matching onto the contract type. I think I'm gonna solve this by looking at available conversion options per type.

fjoppe commented 4 years ago

Its been a bit quiet from my side. Meanwhile I've been working to get this one fixed. Not there yet though, because it is a bit tricky.

fjoppe commented 4 years ago

This was a hard one, but it requird some functionality I wanted anyway.

Released in 0.4.1: https://www.nuget.org/packages/Legivel/0.4.1

A bit tricky, I hope the unit tests cover all cases. This particular case has a unit test here. Hope you don't run into new issues.

pkese commented 4 years ago

You're amazing. And I'm a bit ashamed - I've switched my Yaml parsing code for that particular case to YamlDotNet (there were a few too many impedance mismatches with Legivel and I had to deliver something). But I'd like to switch back to Legivel, because I'm using it elsewhere in my code and I'm really happy with the declarativity of Legivel. So I'll do that next time I get some time to dip my nose in that part of the project. Thanks for solving my issues. I guess this ticket can now be closed?

fjoppe commented 4 years ago

If you're happy with it, we can close this one.

pkese commented 4 years ago

Yes. Thanks.