Literal Expressions =================== All literal expressions are [r-values](expressions-value-categories.md). ## Boolean Literal Expressions > *`BooleanLiteral`* = (**`'true'`** \| **`'false'`**) Boolean literals represent [Boolean](types-fundamental.md#boolean) values `true` and `false`. ## Integer Literal Expressions > *`IntegerLiteral`* = (
>         *`DecIntegerLiteralBody`* \|
>         *`HexIntegerLiteralBody`* \|
>         *`BinIntegerLiteralBody`* \|
>         *`OctIntegerLiteralBody`* )
>     *`IntegerSuffix`*? > > *`DecIntegerLiteralBody`* =
>         **`'0'`** \|
>         *`DecDigitNonZero`* *`DecDigit`*\*
> > *`DecDigit`* = **`<[0-9]>`** > > *`DecDigitNonZero`* = **`<[1-9]>`** > > *`HexIntegerLiteralBody`* = (**`'0x'`**\|**`'0X'`**) *`HexDigit`*+ > > *`HexDigit`* = **`<[0-9A-Fa-f]>`** > > *`BinIntegerLiteralBody`* = (**`'0b'`**\|**`'0B'`**) *`BinDigit`*+ > > *`BinDigit`* = **`'0'`** \| **`'1'`** > > *`OctIntegerLiteralBody`* = **`'0'`** *`OctDigit`*+ > > *`OctDigit`* = **`<[0-7]>`** > > *`IntegerSuffix`* =
>     ( *`IntegerSuffixUnsigned`* *`IntegerSuffixWidth`*? ) \|
>     ( *`IntegerSuffixWidth`* *`IntegerSuffixUnsigned`*? ) > > *`IntegerSuffixUnsigned`* = **`'u'`** \| **`'U'`** > > *`IntegerSuffixWidth`* = **`'l'`** \| **`'L'`** \| **`'ll'`** \| **`'LL'`** \| **`'z'`** \| **`'Z'`** An integer literal represents an [integer](types-fundamental.md#integer) value. It consists of two parts: - the body, which consists of an optional prefix and digits. - an optional suffix, which determines the type of the literal in conjunction with the value. The body uses one of the following forms: - decimal: a non-zero decimal digit followed by zero or more decimal digits, or plain `0`. - hexadecimal: prefixed by `0x` or `0X` and followed by one or more hexadecimal digits. - binary: prefixed by `0b` or `0B` and followed by zeroes and ones. - octal: prefixed by `0` and followed by one or more octal digits. Octal integer literals are deprecated and supported only for backwards compatibility; their use triggers a warning. Note that the literal `0` alone is decimal, while `00`, `01`, etc. are (deprecated) octal literals. The integer literal suffix is optional. When specified, it consists of an unsigned specifier, a width specifier, or both in either order. The unsigned specifier forces the literal to have an unsigned integer type, and the width specifier selects the minimum width for the type. The type of the literal is the first type from the following table that fits the value: Suffix | Decimal base | Hex, binary, octal bases ------------- | -------------------------------- | --------------------------------------- (none)/`L` | `int`, `int64_t`, `uint64_t`(\*) | `int`, `uint`, `int64_t`, `uint64_t` `LL` | `int64_t`, `uint64_t`(\*) | `int64_t`, `uint64_t` `U`/`UL`/`LU` | `uint`, `uint64_t` | `uint`, `uint64_t` `ULL`/`LLU` | `uint64_t` | `uint64_t` `Z` | `intptr_t`, `uintptr_t`(\*) | `intptr_t` `UZ`/`ZU` | `uintptr_t` | `uintptr_t` Types marked with (\*) trigger a warning; they are intended only as a fallback to silently accept values that would otherwise overflow the signed integer type. In addition, the following exceptions are made to allow expressing the smallest negative integer directly: 1. If the literal is `2147483648` or `2147483648L` and it is preceded by unary minus, the resulting value is `-2147483648` and the type is `int`. 2. If the literal is `9223372036854775808`, `9223372036854775808L`, or `9223372036854775808LL`, and it is preceded by unary minus, the resulting value is `-9223372036854775808` and the type is `int64_t`. 3. If the literal is `2147483648Z` (32-bit pointers) or `9223372036854775808Z` (64-bit pointers) and it is preceded by unary minus, the resulting value is `-2147483648` (32-bit pointers) or `-9223372036854775808` (64-bit pointers) and the type is `intptr_t`. The following table summarizes the literal types given the suffix and the value. Suffix | Base | Value range | Literal type ---------------------- | ----------- | ------------------------------------------- | ------------- (none)/`L` | dec | [0, 2147483647] (\*\*) | `int` (none)/`L` | dec | [2147483648, 9223372036854775807] (\*\*) | `int64_t` (none)/`L` | dec | [9223372036854775808, 18446744073709551615] | `uint64_t` (\*) (none)/`L` | hex/bin/oct | [0x0, 0x7FFFFFFF] | `int` (none)/`L` | hex/bin/oct | [0x80000000, 0xFFFFFFFF] | `uint` (none)/`L` | hex/bin/oct | [0x100000000, 0x7FFFFFFFFFFFFFFF] | `int64_t` (none)/`L` | hex/bin/oct | [0x8000000000000000, 0xFFFFFFFFFFFFFFFF] | `uint64_t` `LL` | dec | [0, 9223372036854775807] (\*\*) | `int64_t` `LL` | dec | [9223372036854775808, 18446744073709551615] | `uint64_t` (\*) `LL` | hex/bin/oct | [0x0, 0x7FFFFFFFFFFFFFFF] | `int64_t` `LL` | hex/bin/oct | [0x8000000000000000, 0xFFFFFFFFFFFFFFFF] | `uint64_t` `U`/`UL`/`LU` | any | [0, 4294967295] | `uint` `U`/`UL`/`LU` | any | [4294967296, 18446744073709551615] | `uint64_t` `ULL`/`LLU` | any | [0, 18446744073709551615] | `uint64_t` `Z` (32-bit) | dec | [0, 2147483647] (\*\*) | `intptr_t` `Z` (32-bit) | dec | [2147483648, 4294967295] | `uintptr_t` (\*) `Z` (32-bit) | hex/bin/oct | [0x0, 0xFFFFFFFF] | `intptr_t` `UZ`/`ZU` (32-bit) | dec | [0, 4294967295] | `uintptr_t` `UZ`/`ZU` (32-bit) | hex/bin/oct | [0x0, 0xFFFFFFFF] | `uintptr_t` `Z` (64-bit) | dec | [0, 9223372036854775807] (\*\*) | `intptr_t` `Z` (64-bit) | dec | [9223372036854775808, 18446744073709551615] | `uintptr_t` (\*) `Z` (64-bit) | hex/bin/oct | [0x0, 0xFFFFFFFFFFFFFFFF] | `intptr_t` `UZ`/`ZU` (64-bit) | dec | [0, 18446744073709551615] | `uintptr_t` `UZ`/`ZU` (64-bit) | hex/bin/oct | [0x0, 0xFFFFFFFFFFFFFFFF] | `uintptr_t` (\*) marks a warning. (\*\*) marks rows whose value range is extended by one when the literal is preceded by unary minus, per the special cases listed above (for example, the `int` row also accepts `2147483648` when negated, since `-2147483648` is representable as `int`). **Examples:** ```hlsl 0 // decimal literal, type int 2147483647 // decimal literal, type int 2147483648 // decimal literal, type int64_t 18446744073709551615 // decimal literal, type uint64_t (warning) 18446744073709551616 // decimal literal, overflow error -2147483648 // expression, type int -2147483648LL // expression, type int64_t -9223372036854775808 // expression, type int64_t (no warning per special case) 0U // decimal literal, type uint 5000000000U // decimal literal, type uint64_t 18446744073709551615U // decimal literal, type uint64_t 18446744073709551616U // decimal literal, overflow error 1000 // decimal literal, type int 1000L // decimal literal, type int 1000LL // decimal literal, type int64_t 1000U // decimal literal, type uint 1000UL // decimal literal, type uint 1000ULL // decimal literal, type uint64_t 0x12345678 // hexadecimal literal, type int 0xDEADBEEF // hexadecimal literal, type uint 0x1234567890ABCDEF // hexadecimal literal, type int64_t 0xFEDCBA0987654321 // hexadecimal literal, type uint64_t 0b11010111 // binary literal, type int 0b11010111U // binary literal, type uint 0377 // octal literal, type int (warning) 0x10494810000UZ // hexadecimal literal, type uintptr_t (64-bit pointers only; // overflows on 32-bit) ``` > 📝 **Remark 1:** Hexadecimal, binary, and octal literals whose deduced type is unsigned (`uint` or > `uint64_t`) and that have no `U` or `Z` suffix may be implicitly converted to the corresponding signed > integer type without triggering a narrowing-conversion warning. This allows expressions such as > `int x = 0xFFFFFFFF;`. The binary representation is not changed by the conversion. See > [expression type conversions](expressions-conversions.md) for details. > 📝 **Remark 2:** Integer literal types follow the C++11 rules, with additional special-case handling for > minimum integer values preceded by unary minus. ## Floating-Point Literal Expressions > *`FloatLiteral`* =
>     ( *`DecFloatLiteralBody`* \| *`HexFloatLiteralBody`* )
>     *`FloatSuffix`*? > > *`DecFloatLiteralBody`* =
>     *`DecFloatLiteralBodyForm1`* \|
>     *`DecFloatLiteralBodyForm2`* \|
>     *`DecFloatLiteralBodyForm3`* > > *`DecFloatLiteralBodyForm1`* = *`DecDigit`*+ *`DecExponent`* > > *`DecFloatLiteralBodyForm2`* = *`DecDigit`*+ **`'.'`** *`DecExponent`*? > > *`DecFloatLiteralBodyForm3`* = *`DecDigit`*\* **`'.'`** *`DecDigit`*+ *`DecExponent`*? > > *`DecExponent`* = *`DecExponentNumeric`* \| *`InfinityExponent`* > > *`DecExponentNumeric`* = (**`'e'`** \| **`'E'`**) (**`'+'`** \| **`'-'`**)? *`DecDigit`*+ > > *`InfinityExponent`* = **`'#INF'`** > > *`HexFloatLiteralBody`* =
>     (**`'0x'`**\|**`'0X'`**) (
>         *`HexFloatLiteralBodyForm1`* \|
>         *`HexFloatLiteralBodyForm2`* \|
>         *`HexFloatLiteralBodyForm3`* ) > > *`HexFloatLiteralBodyForm1`* = *`HexDigit`*+ *`HexExponent`* > > *`HexFloatLiteralBodyForm2`* = *`HexDigit`*+ **`'.'`** *`HexExponent`* > > *`HexFloatLiteralBodyForm3`* = *`HexDigit`*\* **`'.'`** *`HexDigit`*+ *`HexExponent`* > > *`HexExponent`* = *`HexExponentNumeric`* \| *`InfinityExponent`* > > *`HexExponentNumeric`* = (**`'p'`** \| **`'P'`**) (**`'+'`** \| **`'-'`**)? *`DecDigit`*+ > > *`FloatSuffix`* = *`FloatSuffixF16`* \| *`FloatSuffixF32`* \| *`FloatSuffixF64`* > > *`FloatSuffixF16`* = **`'h'`** \| **`'H'`** \| **`'hf'`** \| **`'HF'`** \| **`'fh'`** \| **`'FH'`** > > *`FloatSuffixF32`* = **`'f'`** \| **`'F'`** > > *`FloatSuffixF64`* = **`'l'`** \| **`'L'`** \| **`'lf'`** \| **`'LF'`** \| **`'fl'`** \| **`'FL'`** A floating-point literal represents a [floating-point](types-fundamental.md#floating) value. The numeric form consists of three parts: - the body, which can be either decimal or hexadecimal. - an exponent, which is optional in decimal form when the body contains a decimal separator. - an optional suffix, which determines the type of the literal. If omitted, the type is `float`. The decimal body has two variants: 1. Decimal digits and exponent. (*`DecFloatLiteralBodyForm1`*) 2. Decimal digits separated by a decimal separator, and an optional exponent. (*`DecFloatLiteralBodyForm2`* and *`DecFloatLiteralBodyForm3`*) The decimal digits and the optional separator form the decimal significand. The value is *significand \* 10^x*, where *x* is the signed decimal number given by *`DecExponentNumeric`*, or 0 if no exponent is specified. The hexadecimal body consists of hexadecimal digits, an optional radix separator, and a mandatory hexadecimal exponent (*`HexFloatLiteralBodyForm1`*, *`HexFloatLiteralBodyForm2`*, *`HexFloatLiteralBodyForm3`*). The hexadecimal digits and the optional separator form the hexadecimal significand. The value of the literal is *significand \* 2^y*, where *y* is the signed decimal number given by *`HexExponentNumeric`*. Note that the exponent is always written in decimal. In either decimal or hexadecimal form, using `#INF` as the exponent signifies that the literal value is positive infinity. The digits before the exponent are ignored. Negative infinity is expressed by preceding the literal with unary minus, e.g. `-1#INFf`. The literal evaluation rules are as follows: 1. If the literal is too large for its type, its value is infinity and a warning is issued. 2. If the literal is non-zero and too small for its type, its value is `0` and a warning is issued. 3. Decimal literals are rounded to the nearest representable value (ties to even). No warning is issued when rounding changes the value. 4. Hexadecimal literals are truncated (rounded toward zero) to a representable value. A warning is issued when truncation changes the value. **Examples:** ```hlsl 123.0 // 32-bit float, value 123.0 123. // 32-bit float, value 123.0 .5 // 32-bit float, value 0.5 123e3 // 32-bit float, value 123000.0 123e+3 // 32-bit float, value 123000.0 123e-3 // 32-bit float, value 0.123 (not exact) 1.23e2 // 32-bit float, value 123.0 0x123p4 // 32-bit float, value 4656.0 (= 291 * 2^4) 0xC8p-4 // 32-bit float, value 12.5 (= 200 * 2^-4) 0xC.8p0 // 32-bit float, value 12.5 (= 12 + 8 * 2^-4) 123.0lf // 64-bit float, value 123.0 123.0hf // 16-bit float, value 123.0 1#INFhf // 16-bit float, positive infinity 1#INFf // 32-bit float, positive infinity 1#INFlf // 64-bit float, positive infinity 123f // error: '123' is an integer literal and 'f' is not a valid // integer suffix. Write '123.f' or '123e0f' for a float. ``` > 📝 **Remark 1:** A floating-point literal expression without a suffix has type `float`. ## String Literal Expressions > *`StringLiteral`* = *`StringLiteralToken`*+ > > *`StringLiteralToken`* =
>     *`DQuotedString`* \|
>     *`RawString`* > > *`DQuotedString`* = **`'"'`** *`DStringChar`*\* **`'"'`** > > *`DStringChar`* =
>     *`DStringCharUnquoted`* \|
>     *`DStringCharQuoted`* \|
>     *`DStringCharQuotedOctal`* \|
>     *`DStringCharQuotedHex`* > > *`DStringCharUnquoted`* = **`<[^\\"[:newline:]]>`** > > Note: [:newline:] consists of characters `\r` and `\n`. (See the escape sequence table below.) > > *`DStringCharQuoted`* = **`<\\[\\'"?abfnrtv]>`** > > *`DStringCharQuotedOctal`* = **`<\\[0-7]{1,3}>`** > > *`DStringCharQuotedHex`* =
>     **`<\\x[0-9A-Fa-f]+>`** \|
>     **`<\\x\{[0-9A-Fa-f]+\}>`** > > *`RawString`* =
>     **`'R"'`** *`RawStringDelim`* **`'('`**
>     *`RawStringContent`*
>     **`')'`** *`RawStringDelim`* **`'"'`** > > *`RawStringDelim`* = *`RawStringDelimChar`*\* > > *`RawStringDelimChar`* = **`<[^"()[:space:]]>`** > > Note: [:space:] consists of characters ` `, `\t`, `\r`, `\n`, `\v`, and `\f`. (See the escape > sequence table below.) > > *`RawStringContent`* is the longest sequence of characters that does not contain > **`')'`** *`RawStringDelim`* **`'"'`**, where *`RawStringDelim`* is the same delimiter > token that opened the raw string. A string literal represents a sequence of 8-bit characters. Its type is [String](../../../core-module-reference/types/string-0/index.html). The underlying data format is unspecified. A string literal expression consists of one or more consecutive string tokens. The value of the string literal is the concatenation of the string token values. Consecutive string tokens may be separated by whitespace. Unlike most other grammar productions, whitespace within a string token is significant and forms part of the string value. A string token has two forms: 1. Double-quoted string (*`DQuotedString`*) 2. Raw string (*`RawString`*) The double-quoted string token starts with a double-quote (`"`), followed by any number of *`DStringChar`* elements, and ends with a double-quote. A *`DStringChar`* element encodes a single character within a double-quoted string token. For most characters, the character is encoded as is. The exceptions are the newline character (ASCII character 10), the carriage return character (ASCII character 13), the backslash (`\`), and the double-quote character (`"`). These characters are always encoded using an escape sequence. An escape sequence begins with a backslash (`\`). The following table describes the escape sequences and their respective character values: Escape sequence | Encoded character value ---------------------------------- | -------------------------------------- `\'` | Character `'` `\"` | Character `"` `\\` | Character `\` `\?` | Character `?` `\a` | ASCII character 7 (bell) `\b` | ASCII character 8 (backspace) `\f` | ASCII character 12 (form feed) `\n` | ASCII character 10 (newline) `\r` | ASCII character 13 (carriage return) `\t` | ASCII character 9 (horizontal tab) `\v` | ASCII character 11 (vertical tab) `\`nnn | Octal number specifying an 8-bit character code (1-3 digits) `\x`nnn | Character code in hexadecimal format (one or more digits) `\x{`nnn`}` | Character code in hexadecimal format (one or more digits) The octal and hexadecimal numbers in escape sequences must be in the range 0–255. A raw string starts with **`'R"'`**, followed by a user-defined delimiter *`RawStringDelim`* and **`'('`**. The character sequence *`RawStringContent`* that follows is taken verbatim — no escape processing is performed — and may contain any sequence of characters that does not include the termination sequence. The raw string terminates with **`')'`** followed by the same *`RawStringDelim`* and the closing double quote **`'"'`**. **Examples:** ```hlsl "" // empty string "123" // string "123" "some\nstring" // "some" and ASCII 10 (newline) and "string" "a \"quoted\" string" // a "quoted" string "contains a ' quote" // single quote needs no escape in a double-quoted string "\110\145\154\154\157" // "Hello" "\x48\x65\x6C\x6C\x6F" // "Hello" "\x{41}BC" // "ABC" "\0" // String containing only the null character. R"(Raw " string)" // value: Raw " string R"xz(Raw " string)xz" // value: Raw " string R"a(Raw )a" string)a" // The raw string parses as R"a(Raw )a"; its content is // "Raw " (note the trailing space). The leftover // ' string)a"' is a syntax error. R"(ABC DEF)" // value: ABC, a newline, then DEF "123" "456" // "123456" ``` > 📝 **Remark 1:** The recommended encoding of a string literal is UTF-8. This is not enforced. > 📝 **Remark 2:** The current implementation does not fully conform to the language manual. > This is tracked by GitHub issues [#11291](https://github.com/shader-slang/slang/issues/11291) > and [#11306](https://github.com/shader-slang/slang/issues/11306). ## Character Literal Expressions > *`CharLiteral`* = **`<'>`** *`SChar`* **`<'>`** > > *`SChar`* =
>     *`SCharUnquoted`* \|
>     *`DStringCharQuoted`* \|
>     *`DStringCharQuotedOctal`* \|
>     *`DStringCharQuotedHex`* > > *`SCharUnquoted`* = **`<[^\'[:newline:]]>`** > > Note: [:newline:] consists of characters `\r` and `\n`. (See the escape sequence table below.) A character literal expression evaluates to a single character value. The type of the value is [uint](types-fundamental.md#integer). The character literal consists of an *`SChar`* enclosed in single quotes (`'`). *`SChar`* follows the same rules as *`DStringChar`* in a double-quoted string, except that an unquoted character may be a double quote (`"`) but may not be a single quote (`'`). A single quote must be escaped as `\'`. The hexadecimal numbers in escape sequences must be in the range 0–4294967295 (i.e., representable as `uint`). The octal escapes are limited to 0–255. ```hlsl '\0' // Character 0 (null character) 'A' // Character 65 (A) '\t' // Character 9 (horizontal tab) '\x53' // Character 83 (S) '"' // Character 34 (") -- double quote needs no escape '\'' // Character 39 (') -- single quote must be escaped '\\' // Character 92 (\) '\110' // Character 72 (H) via octal escape '\x{75bcd15}' // Character 123456789 via hexadecimal escape ``` > 📝 **Remark 1:** The current implementation does not fully conform to the language manual. > This is tracked by GitHub issues [#11291](https://github.com/shader-slang/slang/issues/11291) > and [#11306](https://github.com/shader-slang/slang/issues/11306).