Class Ek9LiteralParser

java.lang.Object
org.ek9lang.compiler.support.Ek9LiteralParser

public final class Ek9LiteralParser extends Object
Shared utility for parsing EK9 literals that the grammar supports but standard Java parse methods do not handle directly.

Covers hex/octal/underscore integer formats, underscore float formats, and character escape sequences (\t, A, octal \101).

🔑 canonicalTextForOf(String, String) is THE single place that turns a literal's raw source lexeme into the text an org.ek9.lang _of(String) factory can actually read. Any back end or evaluator that reconstructs a literal by calling _of(String) must go through it — _of is a RUNTIME parser and is radix-blind, so handing it the raw lexeme makes 0xFF unset and 0777 silently decimal 777 instead of 511.

  • Method Details

    • parseInteger

      public static long parseInteger(String literal)
      Parse an EK9 integer literal string to a long value. EK9 Integer is 64-bit, so literals are parsed as long (e.g. 10000000000000 is valid). Handles decimal, hex (0x/0X), octal (0 prefix), and underscore-separated (1_000) formats.
    • parseFloat

      public static float parseFloat(String literal)
      Parse an EK9 float literal string to a float value. Handles underscore-separated formats (1_000.5).
    • parseDouble

      public static double parseDouble(String literal)
      Parse an EK9 float literal string to a double value. Handles underscore-separated formats (1_000.5).
    • parseCharacter

      public static char parseCharacter(String literal)
      Parse an EK9 character literal (quotes already stripped) to a char. Handles single characters, standard escapes (\t, \n), unicode escapes (A), and octal escapes (\101).
    • canonicalTextForOf

      public static String canonicalTextForOf(String ek9TypeName, String literalText)
      THE canonical text for reconstructing a literal through an org.ek9.lang _of(String) factory.

      _of(String) is the RUNTIME string parser for a type; it understands that type's canonical external form and nothing else. The EK9 GRAMMAR admits richer forms than that - 0xFF, 0777, 1_000_000, 1_000.5 - so the raw source lexeme must be normalised first or the value is silently wrong:

      • Integer._of("0xFF") -> UNSET (not 255)
      • Integer._of("0777") -> 777 (not 511) - set, and WRONG, which is worse
      • Integer._of("1_000_000") -> UNSET
      • Float._of("1_000.5") -> UNSET
      • Bits._of("0b1111_0000") -> UNSET

      Every other literal type takes its raw source text unchanged, because for those the lexeme already IS the canonical form (2024-01-15, PT2H, #FF0000, 12.50#USD). Character arrives with its quotes ALREADY STRIPPED.

      Parameters:
      ek9TypeName - fully-qualified EK9 type name, e.g. org.ek9.lang::Integer
      literalText - the raw literal text as it appeared in source
      Returns:
      text that _of(String) will read back as the intended value
    • processStringEscapes

      public static String processStringEscapes(String literal)
      Process escape sequences in an EK9 string literal (quotes already stripped). Resolves \t, \n, A, \101, etc. Unrecognized escapes (e.g., \T) are passed through as-is. Returns the input unchanged if no backslash is present.
    • isUnicodeEscapeAt

      public static boolean isUnicodeEscapeAt(String text, int offset)
      THE test for a unicode escape: a backslash, a 'u', then exactly four ASCII hex digits - the lexer's own UnicodeEscape. Integer.parseInt(hex, 16) alone also takes a sign and any Unicode digit, so backslash-u "+041" decoded to 'A' and backslash-u "-001" to U+FFFF (front-end audit FE73). Decode only when this holds. (Not written literally: javac decodes unicode escapes even in comments.)
      Parameters:
      text - the literal's text
      offset - the offset of the backslash