Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support Unicode #1

Closed
sparkprime opened this issue Aug 10, 2014 · 14 comments
Closed

Support Unicode #1

sparkprime opened this issue Aug 10, 2014 · 14 comments
Assignees

Comments

@sparkprime
Copy link
Contributor

Currently only ASCII is supported in strings. It should not be too hard to accept UTF-8 (raising an error for invalid input), and adjust internal string routines to support unparsing those strings correctly, as well as routines for iterating over codepoints, correctly determining the length (in codepoints), etc.

@sparkprime sparkprime self-assigned this Aug 10, 2014
sparkprime pushed a commit that referenced this issue Mar 1, 2015
Merge pull from master
@johnboiles
Copy link

This would be great. How painful did this change look to be? I might be able to contribute if it's not huge.

@sparkprime
Copy link
Contributor Author

My plan was to avoid having a dependency on ICU -- store everything
internally as wstring and assume that wchar is a unicode codepoint. Then
we just need to tweak the lexer to parse utf8 in string literals and the
string output function to render it back as utf8. It shouldn't be too hard
as I left some placeholders and TODOs in there. You're very welcome to
have a try at it.

I suggest 1) modifying the internal string representation in state.h 2)
modifying the output code to encode utf8 and testing it with std.char(x)
for x > 127 and 3) modifying the lexer to parse utf8. It would be possible
to run all tests and commit upstream at each intermediate point.

This would be great. How painful did this change look to be? I might be
able to contribute if it's not huge.


Reply to this email directly or view it on GitHub
#1 (comment).

@johnboiles
Copy link

Great, thanks for the info @sparkprime. I'll update here if I get a chance to try it; I need more emoji in my json 🍻

I really love Jsonnet BTW. My team is using it along with ApiDoc to create API documentation that doubles as a mock API server for developing apps against APIs that aren't finished yet.

@sparkprime
Copy link
Contributor Author

Glad you like it!

I did some reading and it seems wstring is not what we want because it has UTF16 behavior on windows. So we probably need to do something like

typedef std::basic_string<char32_t> JsonnetString;

with functions to convert from UTF8-encoded std::string to that and back.

There are a bunch of places where the HeapString internal representation leaks out into other places as well, e.g. field names, std.extVar() keys, filenames (from std.thisFile) etc.

@sparkprime
Copy link
Contributor Author

@hotdog929 you may be interested

@sparkprime
Copy link
Contributor Author

I'm going to have a go at this because I think it's probably harder / more work than I originally thought.

@sparkprime
Copy link
Contributor Author

That was a productive 4 hours ;)

@johnboiles
Copy link

Wow @sparkprime, way to kill it!!

@davidzchen
Copy link
Contributor

Nice! :D

Perhaps I should also add a jsonnet_test Bazel rule since it is possible to write tests in Jsonnet, such as the unicode.jsonnet test you just added. :)

@johnboiles
Copy link

Looks like normal unicode characters (like etc) are working fine, but longer sequences for emoji (like 🚀 -- "\xF0\x9F\x9A\x80") always become the sequence "\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD\xEF\xBF\xBD"

I'm suspicious of the encode_utf8 method, but I'm struggling to understand what all the bit masking and shifting is doing.

@johnboiles
Copy link

I think I have a fix, looks like a typo on this line:

} else if ((c0 & 0xF8) == 0xF) { //11110zzz 10zzyyyy 10yyyyxx 10xxxxxx

Changing that to the following seems more right

} else if ((c0 & 0xF8) == 0xF0) { //11110zzz 10zzyyyy 10yyyyxx 10xxxxxx

@johnboiles
Copy link

Submitted a fix as #78.

I didn't see an easy way to test this as the \u escape sequence only supports 4 hex digit escape sequences (ie up to character code 0xFFFF). So adding this is invalid:

std.assertEqual("\u1F680", "🚀") &&

One solution for testing could be to add support for the ECMAScript6 code point escapes (like \u{1F680}).

If you have another idea for testing, I'd love to hear it!

@sparkprime
Copy link
Contributor Author

Thanks for tracking this down!

I suppose you can do things like "🚀🚀🚀"[1] which should == "🚀".

\u{XXX} should be a no-brainer though, it could be added in the lexer quite easily.

I have been worried for a long time about the limitation of \u and whether it's necessary to support e.g. things like this as well https://bugs.launchpad.net/zorba/+bug/1024448

@johnboiles
Copy link

No problem! It was enlightening to learn more about the inner workings of unicode

sbarzowski pushed a commit to sbarzowski/jsonnet that referenced this issue Jun 10, 2024
Fix build errors, implement parseCommaList
sbarzowski pushed a commit to sbarzowski/jsonnet that referenced this issue Jun 10, 2024
sbarzowski pushed a commit to sbarzowski/jsonnet that referenced this issue Jun 10, 2024
Port lexer changes from google/jsonnet 0c96da7 to 27ddf2c Fix google#1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants