Skip to content

compiler-common rejects names that gren make compiles: x中, xʰ, xDž and Dža #38

Closed

Description

@gilramir

Found against: gren 0.6.6, gren-lang/compiler-common 3.0.0, gren-lang/core 7.4.2, node 22
Reproduction: in https://github.com/gilramir/gren-bug-reports, 2026-09-13-identifier-letters; ./run.sh prints the table below.

Summary

This compiles with gren make:

x中 : Int
x中 =
    1

and compiler-common's parser cannot parse it. Compiler.Parse.Variable.lowerCase
stops at the 中 and gives back "x", and the declaration then fails to parse.
Anything built on compiler-common refuses a source file that the compiler accepts.

The two parsers disagree about which letters may appear in a name. Both
decide by a character's Unicode General Category, a two-letter code the
Unicode Character Database gives every character (UAX #44, General_Category values).
Letters fall into five categories:

category meaning example
Lu uppercase letter A, É
Ll lowercase letter a, é
Lt titlecase letter: a single character written as two letters, in the form that starts a capitalized word Dž (U+01C5), between DŽ and dž
Lm modifier letter ʰ (U+02B0)
Lo other letter, with no case 中 (U+4E2D), א, ก

In a regular expression, \p{Ll} matches one character of category Ll, and
\p{L} matches any of the five. What each parser accepts:

gren make compiler-common
first letter of a lower-case name lowercase letter (Ll) \p{Ll} — the same
first letter of an upper-case name uppercase or titlecase letter (Lu, Lt) \p{Lu}
every later character ASCII letter, digit or _, or any letter (Lu, Ll, Lt, Lm, Lo) ASCII letter, digit or _, or \p{Ll} or \p{Lu}

So the letters compiler-common is missing are titlecase (Lt, 31 characters,
such as Dž), modifier letters (Lm, such as ʰ) and "other" letters (Lo,
which is most of CJK, Arabic, Hebrew, Devanagari and Thai, among others).

Reproduction

./run.sh asks both questions about each name and prints the table below. For
gren make it compiles a module declaring the name, as a value (lower) or as
a type with one constructor of the same name (upper). For compiler-common it
runs lowerCase or upperCase followed by end, so a name counts as accepted
only if the parser consumed all of it.

kind name gren make compiler-common
lower xé accepts accepts
lower xDž (U+01C5, Lt) accepts rejects
lower xʰ (U+02B0, Lm) accepts rejects
lower x中 (U+4E2D, Lo) accepts rejects
upper Éa accepts accepts
upper Dža (U+01C5, Lt) accepts rejects

The two accepts rows are the control: an Ll or Lu letter, which both
parsers accept.

The cause and possible fixes

gren makeasks Haskell'sData.Char: isUpper(which isLuorLt) for the first letter of an upper-case name, isLowerfor a lower-case one, andisAlpha(everyL*category) after that —compiler/src/Parse/Variable.hs. compiler-common's Compiler/Parse/Variable.gren` uses two regexes instead:

lowerCaseLetterRegex = Regex.fromString "\\p{Ll}" ...
upperCaseLetterRegex = Regex.fromString "\\p{Lu}" ...

isInner char =
    Char.isAlphaNum char
        || char == '_'
        || isLowerCaseLetter char
        || isUpperCaseLetter char

Matching gren make would need to change two things.

  1. An upper-case first letter becomes[\p{Lu}\p{Lt}]
  2. A later character may be any \p{L}.

The lower-case first letter stays \p{Ll}, which already agrees.

Or, of course, document this as change in the language.

Activity

  1. robinheghan commented on Oct 6, 2026

    @robinheghan
    Member

    Fixed on main

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions