--- Title: 2 Lexical Structure Prev: Overview Next: Primitive Types --- ## 2. Lexical Structure ### 2.1 Comments and Directives **Single-line Comments**: ``` // Single-line comment ``` **Compiler Directives**: The language reserves the `#` character for implementation-specific compiler directives. The `#` character cannot appear in identifiers. ``` #!/usr/bin/env stack_lang ``` Directives are implementation-specific and not part of the core language specification. Implementations may support various directives for version requirements, optimization hints, or other configuration. ### 2.2 Identifiers and Constants **Regular Identifiers** - Start with letter or underscore: `[a-zA-Z_][a-zA-Z0-9_]*` - Case-sensitive - When encountered, identifiers are executed immediately - Cannot contain `#`, whitespace, `{}`, `[]`, `()`, `.`, `'`, `"`, or `::` **Identifier Literals** - Prefix with `::` to push the identifier itself onto the stack instead of executing it - Syntax: `::name` pushes the identifier `name` as a value - Example: `::Addable` pushes the identifier `Addable` onto the stack - Example: `::Point` pushes the identifier `Point` onto the stack **Constants** Constants are compile-time values that are immutable and available throughout the scope where they are defined. **Syntax**: `value ::name const` **Examples**: ``` 3.1415926535 ::pi const 9.81 ::gravity const 299792458 ::speed_of_light const // Use constants like any other value 10 pi * 2 / // Calculate circumference / 2 ``` **Properties**: - Constants can be evaluated at compile time - Constants are immutable - they cannot be reassigned - Constants defined at module scope are accessible via `Module::CONST_NAME` (when modules are implemented) - Constants can be any literal value or compile-time expression > **Advanced Usage**: See [Section 11.2](./advanced_topics.html#112-identifier-literals) for complete identifier literal rules and context-dependent behavior. ### 2.3 Literals **Integer Literals** ``` 42 // i64 (default) 42:i32 // Annotate as i32 0xFF // hexadecimal 0b1010 // binary 0o755 // octal 1_000_000 // underscore separators (ignored) ``` **Overflow Behavior**: Integer arithmetic wraps on overflow. For example, adding 1 to 127, the maximum value of an `i8`, produces -128. **Floating Point Literals** ``` 3.14 // f64 (default) 3.14:f32 // Annotate as f32 1_000.5 // underscore separators allowed ``` **Overflow Behavior**: Floating point operations follow IEEE 754 semantics, producing infinity or NaN for overflow/undefined operations. **Character Literals** ``` 'A' // Single character '\n' // Escape sequence '\x41' // Hexadecimal (A) '\u{1F600}' // Unicode (😀) ``` **String Literals** ``` "hello world" "escape sequences: \n \t \\ \"" ``` **Escape Sequences** - `\n` - Newline (LF) - `\r` - Carriage return (CR) - `\t` - Tab - `\\` - Backslash - `\"` - Double quote - `\'` - Single quote - `\0` - Null character - `\xNN` - Hexadecimal byte (e.g., `\x41` for 'A') - `\u{NNNN}` - Unicode code point (e.g., `\u{1F600}` for 😀) **Boolean Literals** ``` true false ``` **Array Literals** ``` [1 2 3 4 5] // array of i64 [1.0 2.0 3.0] // array of f64 [[1 2] [3 4]] // 2D array // Typed arrays [1 2 3 :i16] // array of i16 [[1.0 2.0] [3.0 4.0] :f32] // 2D array of f32 // Arrays of structs (when Point is defined) [{1 2} {3 4} :Point] // array of Point structs ``` ---