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

Provide macros corresponding to the Unicode general categories #126

Open
sjakobi opened this issue Jul 27, 2018 · 11 comments
Open

Provide macros corresponding to the Unicode general categories #126

sjakobi opened this issue Jul 27, 2018 · 11 comments

Comments

@sjakobi
Copy link
Member

sjakobi commented Jul 27, 2018

Right now it seems very difficult to write a rule e.g. for words starting with an uppercase letter.

@erikd
Copy link
Member

erikd commented Jul 27, 2018

What have you tried? I thought this was as simple as:

   [A-Z][a-zA-Z]*

which means one upper case and then zero or more mixed case.

@sjakobi
Copy link
Member Author

sjakobi commented Jul 28, 2018

The Unicode uppercase letter category is quite a bit larger than [A-Z]. Then there are questions like, should e.g. $upper include titlecase letters?

It might make sense to have macros both for the predicates Haskell programmers are used to from Data.Char and for the Unicode general categories…

@erikd
Copy link
Member

erikd commented Jul 28, 2018

Ah ok. I think my response shows that your initial question was not specific enough.

If you specify exactly what it is you want to do and why the current functionality is insufficient, you will get much more useful responses than my one above.

@sjakobi
Copy link
Member Author

sjakobi commented Jul 28, 2018

If you specify exactly what it is you want to do and why the current functionality is insufficient

Right. :) I should have done that first. :)

I want to detect Haskell identifiers. For that I need the following character sets:

  • lowercase, uppercase and titlecase letters
  • decimal digits
  • symbols and punctuation

@erikd
Copy link
Member

erikd commented Jul 29, 2018

Forgive me for being pedantic here, but that is not what you are asking for.

You rejected my suggesting above saying that [A-Z] does not include Unicode. This suggests you want more than just "lowercase, uppercase and titlecase letters" because for most people with English as a first language, that means [a-z] for lowercase and [A-Z] for uppercase.

Furthermore "symbols and punctuation" can mean different things in different programming languages and even in different human languages so there is not one single solution.

Maybe looking at the lexer for CHG itself will provide you some inspiration.

@sjakobi
Copy link
Member Author

sjakobi commented Jul 29, 2018

Maybe looking at the lexer for CHG itself will provide you some inspiration.

Thanks. Yeah, in the end I want a lexer that detects the same identifiers that GHC itself will lex.

But I don't want to replicate GHC's strange Unicode workaround.

If Alex could provide macros corresponding to the Unicode general categories, building the lexer would be quite easy.

@sjakobi sjakobi changed the title Provide macros corresponding to the Data.Char predicates Provide macros corresponding to the Unicode general categories Jul 29, 2018
@simonmar
Copy link
Member

I think my concern with lexing UTF-8 directly in Alex for Haskell source code was that the generated state machine might be huge. I didn't actually do that experiment though, I'd be interested in the results.

@JKTKops
Copy link

JKTKops commented Jan 3, 2021

I'm not sure what to look at in the generated Haskell files to see if that's a problem. Language.Javascript lexes UTF-8 directly. I did something similar while experimenting with R7RS Scheme parsing. Perhaps someone who knows what they're looking for could check if this approach causes problems?

@Ericson2314
Copy link
Collaborator

Per #165, I would like to unfuse the UTF-8 and user-written automata to decluttter the implementation, which we speculate is a bit confused because it might predate Char properly supporting Unicode.

(Even better would be to then go implement proper automaton composition to allow the the user to choose whether to fuse or not fuse the automata (when the underlying string is byte- rather than character-oriented), and start exploring the proper categorical semantics of the language specs themselves! But I am getting star-eyed and off-topic.)

Back to the point, once things can work Char-by-Char nice and simply, I hope character classes for arbitrary Unicode code-points will be a breeze.

@Javran
Copy link

Javran commented Mar 18, 2021

This will be very useful indeed! I just did something similar to #126 (comment) and wish such a support exist.

@Javran
Copy link

Javran commented Mar 20, 2021

Just want to add few notes on this issue:

(A bit of background: I'm following Java SE 16 Spec to write a parser for fun, so my knowledge below is based on my experience following that spec)

One workaround I tried is to let Alex accept a wider language, say Java forbids Unicode outside identifier and literals. So I can take advantage of that fact to be specific only on \x00~\x7F range:

$JavaIdentifierStartLite = [\x24\x41-\x5A\x5F\x61-\x7A\x80-\x10ffff]
$JavaIdentifierPartLite = [$JavaIdentifierStartLite\x00-\x08\x0E-\x1B\x30-\x39\x7F\x80-x10ffff]

and then I can deal with them in AlexAction. However this doesn't work for several reasons:

  • Java SE 16 follows Unicode 13.0, but Data.Char.generalCategory depends on UnicideData shipped with GHC itself so I'm observing some differences due to this misalignment
  • Another thing I attempted is to store the set of accepted Char as a set (this set can be obtained by calling Character.isJavaIdentifierStart and Character.isJavaIdentifierPart iterating through all Unicode codepoint values on a JVM language), however both Data.IntSet and Data.HashSet are very slow even on my small test suites, in comparision making Alex to accurately recognize identifers has way better performance.

My key takeaways:

  • Data.IntSet and Data.Set are way slower than having Alex handle it (please let me know if there are other alternatives, as my Alex approach kind of "cheated" by grouping consecutive ranges like x30000-\x3134A rather than storing every integer individually)
  • If we were to support general category macros, should we provide a way to allow user to supply a UnicideData version? (and how exactly should this be implemented?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants