about summary refs log tree commit diff stats
path: root/js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html
diff options
context:
space:
mode:
Diffstat (limited to 'js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html')
-rw-r--r--js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html1769
1 files changed, 0 insertions, 1769 deletions
diff --git a/js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html b/js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html
deleted file mode 100644
index 9858678..0000000
--- a/js/scripting-lang/docs/baba-yaga/0.0.1/parser.js.html
+++ /dev/null
@@ -1,1769 +0,0 @@
-<!DOCTYPE html>
-<html lang="en">
-<head>
-    <meta charset="utf-8">
-    <meta name="viewport" content="width=device-width,initial-scale=1">
-    <title>parser.js - Documentation</title>
-
-    <script src="scripts/prettify/prettify.js"></script>
-    <script src="scripts/prettify/lang-css.js"></script>
-    <!--[if lt IE 9]>
-      <script src="//html5shiv.googlecode.com/svn/trunk/html5.js"></script>
-    <![endif]-->
-    <link type="text/css" rel="stylesheet" href="https://code.ionicframework.com/ionicons/2.0.1/css/ionicons.min.css">
-    <link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
-    <link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
-</head>
-<body>
-
-<input type="checkbox" id="nav-trigger" class="nav-trigger" />
-<label for="nav-trigger" class="navicon-button x">
-  <div class="navicon"></div>
-</label>
-
-<label for="nav-trigger" class="overlay"></label>
-
-<nav>
-    <li class="nav-link nav-home-link"><a href="index.html">Home</a></li><li class="nav-heading">Tutorials</li><li class="nav-item"><a href="tutorial-00_Introduction.html">00_Introduction</a></li><li class="nav-item"><a href="tutorial-01_Function_Calls.html">01_Function_Calls</a></li><li class="nav-item"><a href="tutorial-02_Function_Composition.html">02_Function_Composition</a></li><li class="nav-item"><a href="tutorial-03_Table_Operations.html">03_Table_Operations</a></li><li class="nav-item"><a href="tutorial-04_Currying.html">04_Currying</a></li><li class="nav-item"><a href="tutorial-05_Pattern_Matching.html">05_Pattern_Matching</a></li><li class="nav-item"><a href="tutorial-06_Immutable_Tables.html">06_Immutable_Tables</a></li><li class="nav-item"><a href="tutorial-07_Function_References.html">07_Function_References</a></li><li class="nav-item"><a href="tutorial-08_Combinators.html">08_Combinators</a></li><li class="nav-item"><a href="tutorial-09_Expression_Based.html">09_Expression_Based</a></li><li class="nav-item"><a href="tutorial-10_Tables_Deep_Dive.html">10_Tables_Deep_Dive</a></li><li class="nav-item"><a href="tutorial-11_Standard_Library.html">11_Standard_Library</a></li><li class="nav-item"><a href="tutorial-12_IO_Operations.html">12_IO_Operations</a></li><li class="nav-item"><a href="tutorial-13_Error_Handling.html">13_Error_Handling</a></li><li class="nav-item"><a href="tutorial-14_Advanced_Combinators.html">14_Advanced_Combinators</a></li><li class="nav-item"><a href="tutorial-15_Integration_Patterns.html">15_Integration_Patterns</a></li><li class="nav-item"><a href="tutorial-16_Best_Practices.html">16_Best_Practices</a></li><li class="nav-item"><a href="tutorial-README.html">README</a></li><li class="nav-heading"><a href="global.html">Globals</a></li><li class="nav-item"><span class="nav-item-type type-member">M</span><span class="nav-item-name"><a href="global.html#callStackTracker">callStackTracker</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#debugError">debugError</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#debugLog">debugLog</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#executeFile">executeFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#initializeStandardLibrary">initializeStandardLibrary</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#interpreter">interpreter</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#lexer">lexer</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#main">main</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#parser">parser</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#readFile">readFile</a></span></li><li class="nav-item"><span class="nav-item-type type-function">F</span><span class="nav-item-name"><a href="global.html#run">run</a></span></li>
-</nav>
-
-<div id="main">
-    
-    <h1 class="page-title">parser.js</h1>
-    
-
-    
-
-
-
-    
-    <section>
-        <article>
-            <pre class="prettyprint source linenums"><code>// Parser for the scripting language
-// Exports: parser(tokens)
-// Converts tokens to an Abstract Syntax Tree (AST)
-
-import { TokenType } from './lexer.js';
-
-// Cross-platform environment detection
-const isNode = typeof process !== 'undefined' &amp;&amp; process.versions &amp;&amp; process.versions.node;
-const isBun = typeof process !== 'undefined' &amp;&amp; process.versions &amp;&amp; process.versions.bun;
-const isBrowser = typeof window !== 'undefined' &amp;&amp; typeof document !== 'undefined';
-
-// Cross-platform debug flag
-const DEBUG = (isNode &amp;&amp; process.env.DEBUG) || (isBrowser &amp;&amp; window.DEBUG) || false;
-
-/**
- * AST node types for the language
- * 
- * @typedef {Object} ASTNode
- * @property {string} type - The node type identifier
- * @property {*} [value] - Node value (for literals)
- * @property {string} [name] - Identifier name (for identifiers)
- * @property {Array.&lt;ASTNode>} [body] - Program or function body
- * @property {Array.&lt;ASTNode>} [args] - Function call arguments
- * @property {Array.&lt;string>} [params] - Function parameters
- * @property {Array.&lt;string>} [parameters] - Function parameters (alternative)
- * @property {ASTNode} [left] - Left operand (for binary expressions)
- * @property {ASTNode} [right] - Right operand (for binary expressions)
- * @property {ASTNode} [operand] - Operand (for unary expressions)
- * @property {ASTNode} [table] - Table expression (for table access)
- * @property {ASTNode} [key] - Key expression (for table access)
- * @property {Array.&lt;Object>} [entries] - Table entries (for table literals)
- * @property {Array.&lt;ASTNode>} [cases] - When expression cases
- * @property {Array.&lt;ASTNode>} [pattern] - Pattern matching patterns
- * @property {Array.&lt;ASTNode>} [result] - Pattern matching results
- * @property {ASTNode} [value] - When expression value
- */
-
-/**
- * Parser: Converts tokens to an Abstract Syntax Tree (AST) using combinator-based architecture.
- * 
- * @param {Array.&lt;Token>} tokens - Array of tokens from the lexer
- * @returns {ASTNode} Abstract Syntax Tree with program body
- * @throws {Error} For parsing errors like unexpected tokens or missing delimiters
- * 
- * @description The parser implements a combinator-based architecture where all
- * operators are translated to function calls to standard library combinators.
- * This reduces parsing ambiguity while preserving the original syntax.
- * 
- * The parser uses a recursive descent approach with proper operator precedence
- * handling. Each operator expression (e.g., x + y) is translated to a FunctionCall
- * node (e.g., add(x, y)) that will be executed by the interpreter using the
- * corresponding combinator function.
- * 
- * Key architectural decisions:
- * - All operators become FunctionCall nodes to eliminate ambiguity
- * - Operator precedence is handled through recursive parsing functions
- * - Function calls are detected by looking for identifiers followed by expressions
- * - When expressions and case patterns are parsed with special handling
- * - Table literals and access are parsed as structured data
- * - Function composition uses 'via' keyword with right-associative precedence
- * - Function application uses juxtaposition with left-associative precedence
- * 
- * The parser maintains a current token index and advances through the token
- * stream, building the AST bottom-up from primary expressions to logical
- * expressions. This approach ensures that all operations are consistently
- * represented as function calls, enabling the interpreter to use the combinator
- * foundation for execution.
- * 
- * This design choice reduces the need for special operator handling in the
- * interpreter and enables abstractions through the combinator foundation.
- * All operations become function calls, providing a consistent and extensible
- * execution model that can be enhanced by adding new combinator functions.
- * 
- * The parser implements a top-down recursive descent strategy where each
- * parsing function handles a specific precedence level. This approach ensures
- * that operator precedence is correctly enforced while maintaining clear
- * separation of concerns for different language constructs.
- * 
- * Error handling is designed to provide meaningful feedback by including
- * context about what was expected and what was found. This enables users
- * to quickly identify and fix parsing errors in their code.
- */
-export function parser(tokens) {
-    let current = 0;
-    
-    /**
-     * Main parsing function that processes the entire token stream
-     * 
-     * @returns {ASTNode} Complete AST with program body
-     * @description Iterates through all tokens, parsing each statement or expression
-     * and building the program body. Handles empty programs gracefully.
-     * 
-     * This function orchestrates the parsing process by repeatedly calling walk()
-     * until all tokens are consumed. It ensures that the final AST contains all
-     * statements and expressions in the correct order, ready for interpretation
-     * by the combinator-based interpreter.
-     * 
-     * The function implements the top-level parsing strategy by processing each
-     * statement or expression in sequence. This approach enables the parser to
-      * handle programs with multiple statements while maintaining the
- * combinator-based architecture where all operations become function calls.
- * 
- * Each call to walk() processes one complete statement or expression, ensuring
- * that the parser can handle programs of various sizes while maintaining
-     * clear separation between different language constructs.
-     * 
-     * The function returns a Program node that contains all parsed statements
-     * and expressions in the order they appeared in the source code. This
-     * structure enables the interpreter to execute statements sequentially
-     * while maintaining proper scope and state management.
-     */
-    function parse() {
-        const body = [];
-        
-        while (current &lt; tokens.length) {
-            const node = walk();
-            if (node) {
-                body.push(node);
-            }
-        }
-        
-        return { type: 'Program', body };
-    }
-    
-    /**
-     * Main walk function that dispatches to appropriate parsing functions
-     * 
-     * @returns {ASTNode|null} Parsed AST node or null for empty statements
-     * @description Determines the type of construct at the current position
-     * and delegates to the appropriate parsing function. The order of checks
-     * determines parsing precedence for top-level constructs.
-     * 
-     * Parsing order:
-     * 1. IO operations (highest precedence for top-level constructs)
-     * 2. Assignments (identifier followed by assignment token)
-     * 3. When expressions (pattern matching)
-     * 4. Function definitions (explicit function declarations)
-     * 5. Logical expressions (default case for all other expressions)
-     * 
-     * This function implements the top-level parsing strategy by checking for
-     * specific token patterns that indicate different language constructs.
-     * The order of checks is crucial for correct parsing precedence and
-      * ensures that expressions are properly decomposed into their
- * constituent parts for combinator translation.
- * 
- * The function uses a pattern-matching approach to identify language constructs
- * based on token sequences. This design enables the parser to handle various
-     * syntax while maintaining clear separation between different constructs.
-     * Each parsing function is responsible for handling its specific syntax
-     * and translating it into appropriate AST nodes for the combinator-based
-     * interpreter.
-     * 
-     * The function returns null for empty statements or whitespace, allowing
-     * the parser to gracefully handle programs with empty lines or comments
-     * without affecting the AST structure.
-     */
-    function walk() {
-        const token = tokens[current];
-        
-        if (!token) return null;
-        
-        // Handle IO operations first
-        if (token.type === TokenType.IO_IN) {
-            return parseIOIn();
-        }
-        if (token.type === TokenType.IO_OUT) {
-            return parseIOOut();
-        }
-        if (token.type === TokenType.IO_ASSERT) {
-            return parseIOAssert();
-        }
-        if (token.type === TokenType.IO_LISTEN) {
-            return parseIOListen();
-        }
-        if (token.type === TokenType.IO_EMIT) {
-            return parseIOEmit();
-        }
-        
-        // Handle assignments
-        if (token.type === TokenType.IDENTIFIER &amp;&amp; 
-            current + 1 &lt; tokens.length &amp;&amp; 
-            tokens[current + 1].type === TokenType.ASSIGNMENT) {
-            return parseAssignment();
-        }
-        
-        // Handle when expressions
-        if (token.type === TokenType.WHEN) {
-            return parseWhenExpression();
-        }
-        
-        // Handle function definitions
-        if (token.type === TokenType.FUNCTION) {
-            return parseFunctionDefinition();
-        }
-        
-
-        
-        // For all other expressions, parse as logical expressions
-        return parseLogicalExpression();
-    }
-    
-    /**
-     * Parse assignment statements: identifier : expression;
-     * 
-     * @returns {ASTNode} Assignment AST node
-     * @throws {Error} For malformed assignments or missing semicolons
-     * @description Parses variable assignments and function definitions.
-     * Supports both simple assignments (x : 42) and arrow function definitions
-     * (f : x y -> x + y). Also handles when expressions as assignment values.
-     * 
-     * The function uses lookahead to distinguish between different assignment
-     * types and parses the value according to the detected type.
-     * 
-     * Assignment parsing is crucial for the language's variable binding system.
-     * The function supports multiple assignment patterns to provide flexibility
-     * while maintaining clear syntax. This includes traditional variable
-     * assignments, function definitions using arrow syntax, and when expressions
-     * that can be assigned to variables.
-     * 
-     * The function implements forward declaration support for recursive functions
-     * by allowing function definitions to reference themselves during parsing.
-     * This enables natural recursive function definitions without requiring
-     * special syntax or pre-declaration.
-     * 
-     * Error handling includes checks for missing semicolons and malformed
-     * assignment syntax, providing clear feedback to help users fix syntax errors.
-     */
-    function parseAssignment() {
-        const identifier = tokens[current].value;
-        current++; // Skip identifier
-        current++; // Skip assignment token (:)
-        
-        // Check if the value is a when expression
-        if (tokens[current].type === TokenType.WHEN) {
-            const value = parseWhenExpression();
-            
-            // Expect semicolon
-            if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-                current++;
-            }
-            
-            return {
-                type: 'Assignment',
-                identifier,
-                value
-            };
-        } else {
-            // Check if this is an arrow function: param1 param2 -> body
-            const params = [];
-            let isArrowFunction = false;
-            
-            // Look ahead to see if this is an arrow function
-            let lookAhead = current;
-            while (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.IDENTIFIER) {
-                lookAhead++;
-            }
-            
-            if (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.ARROW) {
-                // This is an arrow function
-                isArrowFunction = true;
-                
-                // Parse parameters
-                while (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.IDENTIFIER) {
-                    params.push(tokens[current].value);
-                    current++;
-                }
-                
-                if (current >= tokens.length || tokens[current].type !== TokenType.ARROW) {
-                    throw new Error('Expected "->" after parameters in arrow function');
-                }
-                current++; // Skip '->'
-                
-                // Check if the body is a when expression
-                let body;
-                if (tokens[current].type === TokenType.WHEN) {
-                    body = parseWhenExpression();
-                } else {
-                    body = parseLogicalExpression();
-                }
-                
-                // Expect semicolon
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-                    current++;
-                }
-                
-                return {
-                    type: 'Assignment',
-                    identifier,
-                    value: {
-                        type: 'FunctionDeclaration',
-                        params,
-                        body
-                    }
-                };
-            } else {
-                // Parse the value as an expression (function calls will be handled by expression parsing)
-                const value = parseLogicalExpression();
-                
-                // Expect semicolon
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-                    current++;
-                }
-                
-                return {
-                    type: 'Assignment',
-                    identifier,
-                    value
-                };
-            }
-        }
-    }
-    
-    /**
-     * Parse when expressions: when value is pattern then result pattern then result;
-     * 
-     * @returns {ASTNode} WhenExpression AST node
-     * @throws {Error} For malformed when expressions
-     * @description Parses pattern matching expressions with support for single
-     * and multiple values/patterns. The when expression is the primary pattern
-     * matching construct in the language.
-     * 
-     * Supports:
-     * - Single value patterns: when x is 42 then "correct" _ then "wrong"
-     * - Multiple value patterns: when x y is 0 0 then "both zero" _ _ then "not both"
-     * - Wildcard patterns: _ (matches any value)
-     * - Function references: @functionName
-     * 
-     * The function parses values, patterns, and results, building a structured
-     * AST that the interpreter can efficiently evaluate.
-     * 
-     * When expression parsing is essential for pattern matching and conditional
-     * execution. It allows for flexible conditional logic where
-     * a single value or multiple values can be matched against a set of patterns,
-     * and the result of the match determines the next action.
-     * 
-     * The function implements a recursive descent parser that handles nested
-     * patterns and results. It correctly identifies the 'when' keyword,
-     * parses the value(s), and then iterates through cases, parsing patterns
-     * and results. The 'then' keyword is used to separate patterns from results.
-     * 
-     * Error handling includes checks for missing 'is' after value, malformed
-     * patterns, and unexpected tokens during pattern parsing.
-     */
-    function parseWhenExpression() {
-        if (DEBUG) {
-            console.log(`[DEBUG] parseWhenExpression: starting, current token = ${tokens[current].type}`);
-        }
-        current++; // Skip 'when'
-        
-        // Parse the value(s) - can be single value or multiple values
-        const values = [];
-        while (current &lt; tokens.length &amp;&amp; tokens[current].type !== TokenType.IS) {
-            // Use parsePrimary to handle all types of expressions including table access and function calls
-            let value;
-            if (tokens[current].type === TokenType.IO_LISTEN) {
-                // Handle IO listen in when expressions
-                value = parseIOListen();
-            } else if (tokens[current].type === TokenType.IO_EMIT) {
-                // Handle IO emit in when expressions
-                value = parseIOEmit();
-            } else {
-                // For all other types, use parsePrimary to handle expressions
-                value = parsePrimary();
-            }
-            values.push(value);
-        }
-        
-        if (current >= tokens.length || tokens[current].type !== TokenType.IS) {
-            throw new Error('Expected "is" after value in when expression');
-        }
-        current++; // Skip 'is'
-        
-        const cases = [];
-        
-        while (current &lt; tokens.length) {
-            if (DEBUG) {
-                console.log(`[DEBUG] parseWhenExpression: starting new case, current token = ${tokens[current].type}, value = ${tokens[current].value || 'N/A'}`);
-            }
-            // Parse pattern(s) - can be single pattern or multiple patterns
-            const patterns = [];
-            
-            // Parse patterns until we hit THEN
-            while (current &lt; tokens.length &amp;&amp; tokens[current].type !== TokenType.THEN) {
-                let pattern;
-                if (DEBUG) {
-                    console.log(`[DEBUG] parseWhenExpression: parsing pattern, current token = ${tokens[current].type}, value = ${tokens[current].value || 'N/A'}`);
-                }
-                
-                // Check if this is a comparison expression (starts with identifier followed by comparison operator)
-                if (tokens[current].type === TokenType.IDENTIFIER &amp;&amp; 
-                    current + 1 &lt; tokens.length &amp;&amp;
-                    (tokens[current + 1].type === TokenType.LESS_THAN ||
-                     tokens[current + 1].type === TokenType.GREATER_THAN ||
-                     tokens[current + 1].type === TokenType.LESS_EQUAL ||
-                     tokens[current + 1].type === TokenType.GREATER_EQUAL ||
-                     tokens[current + 1].type === TokenType.EQUALS ||
-                     tokens[current + 1].type === TokenType.NOT_EQUAL)) {
-                    // Parse as a comparison expression
-                    pattern = parseExpression();
-                } else if (tokens[current].type === TokenType.IDENTIFIER) {
-                    // Check if this is a function call (identifier followed by arguments)
-                    if (current + 1 &lt; tokens.length &amp;&amp; isValidArgumentStart(tokens[current + 1])) {
-                        // Parse as a function call, but stop at THEN or semicolon
-                        const functionName = tokens[current].value;
-                        current++; // Skip function name
-                        
-                        // Parse arguments until we hit THEN, semicolon, or end of tokens
-                        const args = [];
-                        while (current &lt; tokens.length &amp;&amp; 
-                               tokens[current].type !== TokenType.THEN &amp;&amp;
-                               tokens[current].type !== TokenType.SEMICOLON) {
-                            const arg = parseLogicalExpression();
-                            args.push(arg);
-                        }
-                        
-                        pattern = {
-                            type: 'FunctionCall',
-                            name: functionName,
-                            args
-                        };
-                    } else {
-                        pattern = { type: 'Identifier', value: tokens[current].value };
-                        current++;
-                    }
-                } else if (tokens[current].type === TokenType.NUMBER) {
-                    pattern = { type: 'NumberLiteral', value: tokens[current].value };
-                    current++;
-                } else if (tokens[current].type === TokenType.STRING) {
-                    pattern = { type: 'StringLiteral', value: tokens[current].value };
-                    current++;
-                } else if (tokens[current].type === TokenType.WILDCARD) {
-                    pattern = { type: 'WildcardPattern' };
-                    current++;
-                } else if (tokens[current].type === TokenType.FUNCTION_REF) {
-                    pattern = { type: 'FunctionReference', name: tokens[current].name };
-                    current++;
-                } else if (tokens[current].type === TokenType.TRUE) {
-                    pattern = { type: 'BooleanLiteral', value: true };
-                    current++;
-                } else if (tokens[current].type === TokenType.FALSE) {
-                    pattern = { type: 'BooleanLiteral', value: false };
-                    current++;
-                } else if (tokens[current].type === TokenType.MINUS || tokens[current].type === TokenType.UNARY_MINUS) {
-                    // Handle negative numbers in patterns
-                    current++; // Skip minus token
-                    if (current >= tokens.length || tokens[current].type !== TokenType.NUMBER) {
-                        throw new Error('Expected number after minus in pattern');
-                    }
-                    pattern = { type: 'NumberLiteral', value: -tokens[current].value };
-                    current++;
-                } else if (tokens[current].type === TokenType.LEFT_BRACE) {
-                    // Handle table literals in patterns
-                    pattern = parseTableLiteral();
-                } else if (tokens[current].type === TokenType.LEFT_PAREN) {
-                    // Handle parenthesized expressions in patterns
-                    current++; // Skip '('
-                    pattern = parseLogicalExpression();
-                    if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_PAREN) {
-                        throw new Error('Expected ")" after parenthesized expression in pattern');
-                    }
-                    current++; // Skip ')'
-                } else {
-                    throw new Error(`Expected pattern (identifier, number, string, wildcard, function reference, boolean, or comparison) in when expression, got ${tokens[current].type}`);
-                }
-                patterns.push(pattern);
-                
-                // If we have multiple patterns, we need to handle them correctly
-                // Check if the next token is a valid pattern start (not THEN)
-                if (current &lt; tokens.length &amp;&amp; 
-                    tokens[current].type !== TokenType.THEN &amp;&amp;
-                    tokens[current].type !== TokenType.SEMICOLON) {
-                    // Continue parsing more patterns
-                    continue;
-                }
-            }
-            
-            if (current >= tokens.length || tokens[current].type !== TokenType.THEN) {
-                throw new Error('Expected "then" after pattern in when expression');
-            }
-            current++; // Skip 'then'
-            
-            // Parse result - be careful not to parse beyond the result
-            let result;
-            
-            // Check if the next token after THEN is a pattern start
-            if (current &lt; tokens.length) {
-                const nextToken = tokens[current];
-                if (nextToken.type === TokenType.IDENTIFIER ||
-                    nextToken.type === TokenType.NUMBER ||
-                    nextToken.type === TokenType.STRING ||
-                    nextToken.type === TokenType.WILDCARD ||
-                    nextToken.type === TokenType.FUNCTION_REF) {
-                    // Look ahead to see if this is actually a pattern
-                    let lookAhead = current;
-                    while (lookAhead &lt; tokens.length &amp;&amp; 
-                           tokens[lookAhead].type !== TokenType.THEN &amp;&amp;
-                           tokens[lookAhead].type !== TokenType.SEMICOLON) {
-                        lookAhead++;
-                    }
-                    
-                    if (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.THEN) {
-                        // This is a pattern start, so the result is just the current token
-                        if (nextToken.type === TokenType.IDENTIFIER) {
-                            result = { type: 'Identifier', value: nextToken.value };
-                        } else if (nextToken.type === TokenType.NUMBER) {
-                            result = { type: 'NumberLiteral', value: nextToken.value };
-                        } else if (nextToken.type === TokenType.STRING) {
-                            result = { type: 'StringLiteral', value: nextToken.value };
-                        } else if (nextToken.type === TokenType.WILDCARD) {
-                            result = { type: 'WildcardPattern' };
-                        } else if (nextToken.type === TokenType.FUNCTION_REF) {
-                            result = { type: 'FunctionReference', name: nextToken.name };
-                        }
-                        current++; // Consume the token
-                    } else {
-                        // This is part of the result, parse normally
-                        result = parseLogicalExpression();
-                    }
-                } else if (nextToken.type === TokenType.WHEN) {
-                    // This is a nested when expression, parse it directly
-                    result = parseWhenExpression();
-                } else {
-                    // Not a pattern start, parse normally
-                    result = parseLogicalExpression();
-                }
-            } else {
-                result = parseLogicalExpression();
-            }
-            
-            cases.push({
-                pattern: patterns,
-                result: [result]
-            });
-            
-            if (DEBUG) {
-                console.log(`[DEBUG] parseWhenExpression: finished case, current token = ${tokens[current].type}, value = ${tokens[current].value || 'N/A'}`);
-            }
-            
-            // Enhanced termination logic for when expressions
-            if (current &lt; tokens.length) {
-                const nextToken = tokens[current];
-                
-                if (DEBUG) {
-                    console.log(`[DEBUG] parseWhenExpression: checking termination, nextToken = ${nextToken.type}, value = ${nextToken.value || 'N/A'}`);
-                }
-                
-                // Stop on semicolon
-                if (nextToken.type === TokenType.SEMICOLON) {
-                    if (DEBUG) {
-                        console.log(`[DEBUG] parseWhenExpression: terminating on SEMICOLON`);
-                    }
-                    current++;
-                    break;
-                }
-                
-                // Stop on assignment (for consecutive assignments)
-                if (nextToken.type === TokenType.ASSIGNMENT) {
-                    if (DEBUG) {
-                        console.log(`[DEBUG] parseWhenExpression: terminating on ASSIGNMENT`);
-                    }
-                    break;
-                }
-                
-                // Stop on identifier that starts a new assignment
-                if (nextToken.type === TokenType.IDENTIFIER) {
-                    // Look ahead to see if this is the start of a new assignment
-                    let lookAhead = current;
-                    while (lookAhead &lt; tokens.length &amp;&amp; 
-                           tokens[lookAhead].type !== TokenType.ASSIGNMENT &amp;&amp;
-                           tokens[lookAhead].type !== TokenType.SEMICOLON &amp;&amp;
-                           tokens[lookAhead].type !== TokenType.THEN) {
-                        lookAhead++;
-                    }
-                    
-                    if (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.ASSIGNMENT) {
-                        // This is the start of a new assignment, terminate the when expression
-                        if (DEBUG) {
-                            console.log(`[DEBUG] parseWhenExpression: terminating on new assignment starting with ${nextToken.value}`);
-                        }
-                        break;
-                    }
-                }
-                
-                // Stop on right brace (for when expressions inside table literals)
-                if (nextToken.type === TokenType.RIGHT_BRACE) {
-                    if (DEBUG) {
-                        console.log(`[DEBUG] parseWhenExpression: terminating on RIGHT_BRACE`);
-                    }
-                    break;
-                }
-                
-                // Stop on comma (for when expressions inside table literals)
-                if (nextToken.type === TokenType.COMMA) {
-                    if (DEBUG) {
-                        console.log(`[DEBUG] parseWhenExpression: terminating on COMMA`);
-                    }
-                    break;
-                }
-            }
-        }
-        
-        return {
-            type: 'WhenExpression',
-            value: values.length === 1 ? values[0] : values,
-            cases
-        };
-    }
-    
-
-
-    /**
-     * Parse function definitions: function (params) : body
-     * 
-     * @returns {ASTNode} FunctionDefinition AST node
-     * @throws {Error} For malformed function definitions
-     * @description Parses explicit function declarations with parameter lists
-     * and function bodies. This is the traditional function definition syntax
-     * as opposed to arrow functions.
-     * 
-     * The function expects:
-     * - function keyword
-     * - Parenthesized parameter list
-     * - Assignment token (:)
-     * - Function body expression
-     * 
-     * Function definition parsing is fundamental to the language's ability to
-     * define reusable functions. It supports traditional function declarations
-     * with explicit parameter lists and function bodies.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * 'function' keyword, parameter parsing, and the assignment token.
-     * It then recursively parses the function body, which can be any valid
-     * expression.
-     * 
-     * Error handling includes checks for missing '(' after function keyword,
-     * missing ')' after function parameters, and missing ':' after parameters.
-     */
-    function parseFunctionDefinition() {
-        current++; // Skip 'function'
-        
-        if (current >= tokens.length || tokens[current].type !== TokenType.LEFT_PAREN) {
-            throw new Error('Expected "(" after function keyword');
-        }
-        current++; // Skip '('
-        
-        const parameters = [];
-        while (current &lt; tokens.length &amp;&amp; tokens[current].type !== TokenType.RIGHT_PAREN) {
-            if (tokens[current].type === TokenType.IDENTIFIER) {
-                parameters.push(tokens[current].value);
-                current++;
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.COMMA) {
-                    current++; // Skip comma
-                }
-            } else {
-                throw new Error('Expected parameter name in function definition');
-            }
-        }
-        
-        if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_PAREN) {
-            throw new Error('Expected ")" after function parameters');
-        }
-        current++; // Skip ')'
-        
-        if (current >= tokens.length || tokens[current].type !== TokenType.ASSIGNMENT) {
-            throw new Error('Expected ":" after function parameters');
-        }
-        current++; // Skip ':'
-        
-        const body = parseLogicalExpression();
-        
-        return {
-            type: 'FunctionDefinition',
-            parameters,
-            body
-        };
-    }
-    
-    /**
-     * Parse IO input operations: ..in
-     * 
-     * @returns {ASTNode} IOInExpression AST node
-     * @description Parses input operations that read from standard input.
-     * The operation is represented as a simple AST node that the interpreter
-     * will handle by prompting for user input.
-     * 
-     * IO input parsing is crucial for interactive programs that require
-     * user interaction. It allows for simple and direct input operations
-     * that read values from the standard input stream.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * '..in' keyword and expects a semicolon after the operation.
-     * 
-     * Error handling includes checks for missing semicolon after input operation.
-     */
-    function parseIOIn() {
-        current++; // Skip IO_IN token
-        return { type: 'IOInExpression' };
-    }
-    
-    /**
-     * Parse IO output operations: ..out expression
-     * 
-     * @returns {ASTNode} IOOutExpression AST node
-     * @throws {Error} For malformed output expressions
-     * @description Parses output operations that write to standard output.
-     * The expression to output is parsed as a logical expression and will
-     * be evaluated by the interpreter before being printed.
-     * 
-     * IO output parsing is essential for programs that need to display
-     * information to the user. It allows for expressions to be evaluated
-     * and their results to be printed to the standard output stream.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * '..out' keyword and expects a semicolon after the expression.
-     * 
-     * Error handling includes checks for missing semicolon after output expression.
-     */
-    function parseIOOut() {
-        current++; // Skip IO_OUT token
-        const value = parseLogicalExpression();
-        
-        // Expect semicolon
-        if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-            current++;
-        }
-        
-        return {
-            type: 'IOOutExpression',
-            value
-        };
-    }
-    
-    /**
-     * Parse IO assert operations: ..assert expression
-     * 
-     * @returns {ASTNode} IOAssertExpression AST node
-     * @throws {Error} For malformed assert expressions
-     * @description Parses assertion operations that verify conditions.
-     * The expression is parsed as a logical expression and will be evaluated
-     * by the interpreter. If the result is falsy, an assertion error is thrown.
-     * 
-     * IO assert parsing is important for programs that need to perform
-     * runtime checks or assertions. It allows for expressions to be evaluated
-     * and their boolean results to be used for conditional execution or
-     * error reporting.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * '..assert' keyword and expects a semicolon after the expression.
-     * 
-     * Error handling includes checks for missing semicolon after assert expression.
-     */
-    function parseIOAssert() {
-        current++; // Skip IO_ASSERT token
-        const value = parseLogicalExpression();
-        
-        // Expect semicolon
-        if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-            current++;
-        }
-        
-        return {
-            type: 'IOAssertExpression',
-            value
-        };
-    }
-
-    /**
-     * Parse IO listen operations: ..listen
-     * 
-     * @returns {ASTNode} IOListenExpression AST node
-     * @description Parses listen operations that retrieve current state.
-     * Returns the current state from the external system without any parameters.
-     * 
-     * IO listen parsing is useful for programs that need to query the
-     * current state of an external system or environment. It allows for
-     * simple retrieval of state without requiring any input parameters.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * '..listen' keyword and expects a semicolon after the operation.
-     * 
-     * Error handling includes checks for missing semicolon after listen operation.
-     */
-    function parseIOListen() {
-        current++; // Skip IO_LISTEN token
-        
-        // Expect semicolon
-        if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-            current++;
-        }
-        
-        return {
-            type: 'IOListenExpression'
-        };
-    }
-
-    /**
-     * Parse IO emit operations: ..emit expression
-     * 
-     * @returns {ASTNode} IOEmitExpression AST node
-     * @throws {Error} For malformed emit expressions
-     * @description Parses emit operations that send values to external system.
-     * The expression is parsed as a logical expression and will be evaluated
-     * by the interpreter before being sent to the external system.
-     * 
-     * IO emit parsing is essential for programs that need to interact with
-     * external systems or environments. It allows for expressions to be
-     * evaluated and their results to be sent to the external system.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * '..emit' keyword and expects a semicolon after the expression.
-     * 
-     * Error handling includes checks for missing semicolon after emit expression.
-     */
-    function parseIOEmit() {
-        current++; // Skip IO_EMIT token
-        const value = parseLogicalExpression();
-        
-        // Expect semicolon
-        if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.SEMICOLON) {
-            current++;
-        }
-        
-        return {
-            type: 'IOEmitExpression',
-            value
-        };
-    }
-    
-    /**
-     * Parse logical expressions with proper precedence
-     * 
-     * @returns {ASTNode} AST node representing the logical expression
-     * @description Parses logical expressions (and, or, xor) with the lowest
-     * precedence. All logical operators are translated to FunctionCall nodes
-     * using the corresponding combinator functions.
-     * 
-     * Logical expression parsing is the foundation for conditional logic
-     * in the language. It handles the lowest precedence operators (and, or, xor)
-     * and translates them to combinator function calls.
-     * 
-     * The function implements a recursive descent parser that handles
-     * operator precedence by repeatedly calling itself with the right operand
-     * until no more operators of the same precedence are found.
-     * 
-     * Error handling includes checks for missing operators or operands.
-     */
-    function parseLogicalExpression() {
-        let left = parseExpression();
-        
-        while (current &lt; tokens.length) {
-            const token = tokens[current];
-            
-            if (token.type === TokenType.AND || 
-                token.type === TokenType.OR || 
-                token.type === TokenType.XOR) {
-                current++;
-                const right = parseExpression();
-                left = {
-                    type: 'FunctionCall',
-                    name: token.type === TokenType.AND ? 'logicalAnd' :
-                          token.type === TokenType.OR ? 'logicalOr' : 'logicalXor',
-                    args: [left, right]
-                };
-            } else {
-                break;
-            }
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Parse comparison expressions
-     * 
-     * @returns {ASTNode} AST node representing the comparison expression
-     * @description Parses comparison expressions (=, !=, &lt;, >, &lt;=, >=) and
-     * additive expressions (+, -). All operators are translated to FunctionCall
-     * nodes using the corresponding combinator functions.
-     * 
-     * This function implements the core of the combinator-based architecture
-     * by translating operator expressions to function calls that will be
-     * executed by the interpreter using standard library combinators.
-     * 
-     * Comparison expression parsing is crucial for conditional logic
-     * and arithmetic operations. It handles equality, inequality,
-     * comparison operators, and additive operators.
-     * 
-     * The function implements a recursive descent parser that handles
-     * operator precedence by repeatedly calling itself with the right operand
-     * until no more operators of the same precedence are found.
-     * 
-     * Error handling includes checks for missing operators or operands.
-     */
-    function parseExpression() {
-        if (DEBUG) {
-            console.log(`[DEBUG] parseExpression: starting, current token = ${tokens[current].type}`);
-        }
-        
-        // Handle IO operations in expressions
-        if (current &lt; tokens.length) {
-            const token = tokens[current];
-            if (token.type === TokenType.IO_LISTEN) {
-                return parseIOListen();
-            }
-            if (token.type === TokenType.IO_EMIT) {
-                return parseIOEmit();
-            }
-        }
-        
-        // Handle unary minus at the beginning of expressions
-        let left;
-        if (current &lt; tokens.length &amp;&amp; (tokens[current].type === TokenType.MINUS || tokens[current].type === TokenType.UNARY_MINUS)) {
-            if (DEBUG) {
-                console.log(`[DEBUG] parseExpression: handling unary minus`);
-            }
-            current++;
-            const operand = parseTerm();
-            left = {
-                type: 'FunctionCall',
-                name: 'negate',
-                args: [operand]
-            };
-        } else {
-            left = parseTerm();
-        }
-        
-        if (DEBUG) {
-            console.log(`[DEBUG] parseExpression: after parseTerm, current token = ${tokens[current].type}`);
-        }
-        
-        while (current &lt; tokens.length) {
-            const token = tokens[current];
-            
-            if (DEBUG) {
-                console.log(`[DEBUG] parseExpression: while loop, current token = ${token.type}, value = ${token.value || 'N/A'}`);
-            }
-            
-            if (token.type === TokenType.PLUS) {
-                current++;
-                const right = parseTerm();
-                left = {
-                    type: 'FunctionCall',
-                    name: 'add',
-                    args: [left, right]
-                };
-            } else if (token.type === TokenType.MINUS || token.type === TokenType.BINARY_MINUS) {
-                current++;
-                const right = parseTerm();
-                left = {
-                    type: 'FunctionCall',
-                    name: 'subtract',
-                    args: [left, right]
-                };
-            } else if (token.type === TokenType.EQUALS || 
-                       token.type === TokenType.NOT_EQUAL ||
-                       token.type === TokenType.LESS_THAN ||
-                       token.type === TokenType.GREATER_THAN ||
-                       token.type === TokenType.LESS_EQUAL ||
-                       token.type === TokenType.GREATER_EQUAL) {
-                current++;
-                const right = parseTerm();
-                left = {
-                    type: 'FunctionCall',
-                    name: token.type === TokenType.EQUALS ? 'equals' :
-                          token.type === TokenType.NOT_EQUAL ? 'notEquals' :
-                          token.type === TokenType.LESS_THAN ? 'lessThan' :
-                          token.type === TokenType.GREATER_THAN ? 'greaterThan' :
-                          token.type === TokenType.LESS_EQUAL ? 'lessEqual' : 'greaterEqual',
-                    args: [left, right]
-                };
-            } else {
-                break;
-            }
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Parse multiplication and division expressions
-     * 
-     * @returns {ASTNode} AST node representing the multiplicative expression
-     * @description Parses multiplicative expressions (*, /, %) with higher
-     * precedence than additive expressions. All operators are translated to
-     * FunctionCall nodes using the corresponding combinator functions.
-     * 
-     * Multiplicative expression parsing is crucial for arithmetic operations
-     * and mathematical calculations. It handles multiplication, division,
-     * and modulo operations.
-     * 
-     * The function implements a recursive descent parser that handles
-     * operator precedence by repeatedly calling itself with the right operand
-     * until no more operators of the same precedence are found.
-     * 
-     * Error handling includes checks for missing operators or operands.
-     */
-    function parseTerm() {
-        if (DEBUG) {
-            console.log(`[DEBUG] parseTerm: starting, current token = ${tokens[current].type}`);
-        }
-        let left = parseApplication();
-        
-        while (current &lt; tokens.length) {
-            const token = tokens[current];
-            
-            if (token.type === TokenType.MULTIPLY || 
-                token.type === TokenType.DIVIDE || 
-                token.type === TokenType.MODULO) {
-                current++;
-                const right = parseFactor();
-                left = {
-                    type: 'FunctionCall',
-                    name: token.type === TokenType.MULTIPLY ? 'multiply' :
-                          token.type === TokenType.DIVIDE ? 'divide' : 'modulo',
-                    args: [left, right]
-                };
-            } else if (token.type === TokenType.MINUS) {
-                current++;
-                const right = parseFactor();
-                left = {
-                    type: 'FunctionCall',
-                    name: 'subtract',
-                    args: [left, right]
-                };
-            } else {
-                break;
-            }
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Parse power expressions and unary operators
-     * 
-     * @returns {ASTNode} AST node representing the factor expression
-     * @description Parses power expressions (^) and unary operators (not, -)
-     * with the highest precedence among operators. All operators are translated
-     * to FunctionCall nodes using the corresponding combinator functions.
-     * 
-     * Factor expression parsing is crucial for exponentiation and unary
-     * operators. It handles power expressions and unary operators (not, -).
-     * 
-     * The function implements a recursive descent parser that handles
-     * operator precedence by repeatedly calling itself with the right operand
-     * until no more operators of the same precedence are found.
-     * 
-     * Error handling includes checks for missing operators or operands.
-     */
-    function parseFactor() {
-        if (DEBUG) {
-            console.log(`[DEBUG] parseFactor: starting, current token = ${tokens[current].type}`);
-        }
-        let left = parsePrimary();
-        
-        // Parse power expressions (existing logic)
-        while (current &lt; tokens.length) {
-            const token = tokens[current];
-            
-            if (token.type === TokenType.POWER) {
-                current++;
-                const right = parsePrimary();
-                left = {
-                    type: 'FunctionCall',
-                    name: 'power',
-                    args: [left, right]
-                };
-            } else {
-                break;
-            }
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Parse function composition expressions using the 'via' keyword
-     * 
-     * @returns {ASTNode} AST node representing the composition expression
-     * @throws {Error} For malformed composition expressions
-     * @description Parses function composition using the 'via' keyword
-     * with right-associative precedence: f via g via h = compose(f, compose(g, h))
-     * 
-     * The 'via' operator provides natural function composition syntax that reads
-     * from right to left, matching mathematical function composition notation.
-     * 
-     * Precedence and associativity:
-     * - 'via' has higher precedence than function application (juxtaposition)
-     * - 'via' is right-associative: f via g via h = compose(f, compose(g, h))
-     * - This means: f via g via h(x) = compose(f, compose(g, h))(x) = f(g(h(x)))
-     * 
-     * Translation examples:
-     * - f via g → compose(f, g)
-     * - f via g via h → compose(f, compose(g, h))
-     * - f via g via h via i → compose(f, compose(g, compose(h, i)))
-     * 
-     * The right-associative design choice enables natural reading of composition
-     * chains that matches mathematical notation where (f ∘ g ∘ h)(x) = f(g(h(x))).
-     * 
-     * Function composition is a fundamental feature that allows functions to be
-     * combined naturally. The right-associative precedence means that composition
-     * chains are built from right to left, which matches mathematical function
-      * composition notation. This enables functional programming patterns
- * where transformations can be built from simple, composable functions.
-     * 
-     * Composition parsing is essential for functional programming patterns
-     * where functions are composed together. It handles the 'via' keyword
-     * and recursively composes functions from right to left.
-     * 
-     * The function implements a recursive descent parser that handles the
-     * 'via' keyword and recursively composes functions.
-     * 
-     * Error handling includes checks for missing 'via' keyword or malformed
-     * composition chains.
-     */
-    function parseComposition() {
-        let left = parseFactor();
-        
-        // Parse right-associative composition: f via g via h = compose(f, compose(g, h))
-        while (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.COMPOSE) {
-            current++; // Skip 'via'
-            const right = parseFactor();
-            
-            left = {
-                type: 'FunctionCall',
-                name: 'compose',
-                args: [left, right]
-            };
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Parse function application (juxtaposition)
-     * 
-     * @returns {ASTNode} AST node representing the function application
-     * @description Parses function application using juxtaposition (f x)
-     * with left-associative precedence: f g x = apply(apply(f, g), x)
-     * 
-     * Function application using juxtaposition is the primary mechanism for
-     * calling functions in the language. The left-associative precedence means
-     * that application chains are built from left to right, which is intuitive
-     * for most programmers. This approach reduces the need for parentheses
-     * in many cases while maintaining clear precedence rules.
-     * 
-     * Function application parsing is essential for calling functions in
-     * the language. It handles juxtaposition of function and argument expressions.
-     * 
-     * The function implements a recursive descent parser that handles
-     * left-associative function application. It repeatedly calls itself
-     * with the right operand until no more function applications are found.
-     * 
-     * Error handling includes checks for missing function or argument expressions.
-     */
-    function parseApplication() {
-        let left = parseComposition();
-        
-        // Parse left-associative function application: f g x = apply(apply(f, g), x)
-        while (current &lt; tokens.length &amp;&amp; isValidArgumentStart(tokens[current])) {
-            const arg = parseComposition(); // Parse the argument as a composition expression
-            left = {
-                type: 'FunctionCall',
-                name: 'apply',
-                args: [left, arg]
-            };
-        }
-        
-        return left;
-    }
-    
-    /**
-     * Check if a token is a valid start of a function argument
-     * 
-     * @param {Token} token - Token to check
-     * @returns {boolean} True if the token can start a function argument
-     * @description Determines if a token can be the start of a function argument.
-     * This is used to detect function application (juxtaposition) where function
-     * application binds tighter than infix operators.
-     * 
-     * This function is crucial for the juxtaposition-based function application
-     * system. It determines when the parser should treat an expression as a
-     * function argument rather than as part of an infix operator expression.
-     * The tokens that can start arguments are carefully chosen to ensure that
-     * function application has the correct precedence relative to operators.
-     */
-    function isValidArgumentStart(token) {
-        return token.type === TokenType.IDENTIFIER ||
-               token.type === TokenType.NUMBER ||
-               token.type === TokenType.STRING ||
-               token.type === TokenType.LEFT_PAREN ||
-               token.type === TokenType.LEFT_BRACE ||
-               token.type === TokenType.TRUE ||
-               token.type === TokenType.FALSE ||
-               token.type === TokenType.FUNCTION_REF ||
-               token.type === TokenType.FUNCTION_ARG ||
-               token.type === TokenType.NOT ||
-               token.type === TokenType.UNARY_MINUS;
-    }
-    
-    /**
-     * Parse table literals: {key: value, key2: value2} or {value1, value2, value3}
-     * 
-     * @returns {ASTNode} TableLiteral AST node
-     * @throws {Error} For malformed table literals
-     * @description Parses table literals with support for both key-value pairs
-     * and array-like entries. Tables are the primary data structure in the language.
-     * 
-     * Supports:
-     * - Key-value pairs: {name: "Alice", age: 30}
-     * - Array-like entries: {1, 2, 3}
-     * - Mixed entries: {1, 2, name: "Alice", 3}
-     * 
-     * Array-like entries are automatically assigned numeric keys starting from 1.
-     * 
-     * Table literal parsing is essential for defining and accessing
-     * key-value or array-like data structures. It handles curly braces,
-     * keys, and values.
-     * 
-     * The function implements a recursive descent parser that handles
-     * nested structures and supports both key-value and array-like entries.
-     * 
-     * Error handling includes checks for missing braces, malformed keys,
-     * and unexpected tokens.
-     */
-    function parseTableLiteral() {
-        current++; // Skip '{'
-        
-        const entries = [];
-        
-        while (current &lt; tokens.length &amp;&amp; tokens[current].type !== TokenType.RIGHT_BRACE) {
-            // Check if this is a key-value pair or just a value
-            let key = null;
-            let value;
-            
-            // Parse the first element
-            if (tokens[current].type === TokenType.IDENTIFIER) {
-                // Could be a key or a value
-                const identifier = tokens[current].value;
-                current++;
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.ASSIGNMENT) {
-                    // This is a key-value pair: key : value
-                    key = { type: 'Identifier', value: identifier };
-                    current++; // Skip ':'
-                    
-                    // Check if the value is an arrow function
-                    let isArrowFunction = false;
-                    let lookAhead = current;
-                    
-                    // Look ahead to see if this is an arrow function
-                    while (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.IDENTIFIER) {
-                        lookAhead++;
-                    }
-                    
-                    if (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.ARROW) {
-                        // This is an arrow function
-                        isArrowFunction = true;
-                        
-                        // Parse parameters
-                        const params = [];
-                        while (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.IDENTIFIER) {
-                            params.push(tokens[current].value);
-                            current++;
-                        }
-                        
-                        if (current >= tokens.length || tokens[current].type !== TokenType.ARROW) {
-                            throw new Error('Expected "->" after parameters in arrow function');
-                        }
-                        current++; // Skip '->'
-                        
-                        // Check if the body is a when expression
-                        let body;
-                        if (tokens[current].type === TokenType.WHEN) {
-                            body = parseWhenExpression();
-                        } else {
-                            body = parseLogicalExpression();
-                        }
-                        
-                        value = {
-                            type: 'FunctionDeclaration',
-                            params,
-                            body
-                        };
-                    } else {
-                        // This is a regular value
-                        value = parseLogicalExpression();
-                    }
-                } else {
-                    // This is just a value (array-like entry)
-                    value = { type: 'Identifier', value: identifier };
-                }
-            } else if (tokens[current].type === TokenType.NUMBER) {
-                // Could be a numeric key or a value
-                const number = tokens[current].value;
-                current++;
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.ASSIGNMENT) {
-                    // This is a key-value pair: number : value
-                    key = { type: 'NumberLiteral', value: number };
-                    current++; // Skip ':'
-                    value = parseLogicalExpression();
-                } else {
-                    // This is just a value (array-like entry)
-                    value = { type: 'NumberLiteral', value: number };
-                }
-            } else if (tokens[current].type === TokenType.TRUE) {
-                // Could be a boolean key or a value
-                current++;
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.ASSIGNMENT) {
-                    // This is a key-value pair: true : value
-                    key = { type: 'BooleanLiteral', value: true };
-                    current++; // Skip ':'
-                    value = parseLogicalExpression();
-                } else {
-                    // This is just a value (array-like entry)
-                    value = { type: 'BooleanLiteral', value: true };
-                }
-            } else if (tokens[current].type === TokenType.FALSE) {
-                // Could be a boolean key or a value
-                current++;
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.ASSIGNMENT) {
-                    // This is a key-value pair: false : value
-                    key = { type: 'BooleanLiteral', value: false };
-                    current++; // Skip ':'
-                    value = parseLogicalExpression();
-                } else {
-                    // This is just a value (array-like entry)
-                    value = { type: 'BooleanLiteral', value: false };
-                }
-            } else if (tokens[current].type === TokenType.LEFT_PAREN) {
-                // This could be a computed key or a value
-                const expression = parseLogicalExpression();
-                
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.ASSIGNMENT) {
-                    // This is a key-value pair: (expression) : value
-                    key = expression;
-                    current++; // Skip ':'
-                    value = parseLogicalExpression();
-                } else {
-                    // This is just a value (array-like entry)
-                    value = expression;
-                }
-            } else {
-                // Check if this is an arrow function: param1 param2 -> body
-                let isArrowFunction = false;
-                let lookAhead = current;
-                
-                // Look ahead to see if this is an arrow function
-                while (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.IDENTIFIER) {
-                    lookAhead++;
-                }
-                
-                if (lookAhead &lt; tokens.length &amp;&amp; tokens[lookAhead].type === TokenType.ARROW) {
-                    // This is an arrow function
-                    isArrowFunction = true;
-                    
-                    // Parse parameters
-                    const params = [];
-                    while (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.IDENTIFIER) {
-                        params.push(tokens[current].value);
-                        current++;
-                    }
-                    
-                    if (current >= tokens.length || tokens[current].type !== TokenType.ARROW) {
-                        throw new Error('Expected "->" after parameters in arrow function');
-                    }
-                    current++; // Skip '->'
-                    
-                    // Check if the body is a when expression
-                    let body;
-                    if (tokens[current].type === TokenType.WHEN) {
-                        body = parseWhenExpression();
-                    } else {
-                        body = parseLogicalExpression();
-                    }
-                    
-                    value = {
-                        type: 'FunctionDeclaration',
-                        params,
-                        body
-                    };
-                } else {
-                    // This is a regular value (array-like entry)
-                    value = parseLogicalExpression();
-                }
-            }
-            
-            entries.push({ key, value });
-            
-            // Skip comma if present
-            if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.COMMA) {
-                current++;
-            }
-        }
-        
-        if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_BRACE) {
-            throw new Error('Expected "}" after table literal');
-        }
-        current++; // Skip '}'
-        
-        return {
-            type: 'TableLiteral',
-            entries
-        };
-    }
-    
-
-    
-    /**
-     * Parse function calls: functionName arg1 arg2 ...
-     * 
-     * @returns {ASTNode} FunctionCall AST node
-     * @description Parses function calls with multiple arguments. This function
-     * is used by parsePrimary to detect when an identifier is followed by
-     * expressions that should be treated as function arguments.
-     * 
-     * Function calls are detected by the presence of an identifier followed
-     * by expressions that are not operators. The parser uses lookahead to
-     * determine if an identifier should be treated as a function call.
-     * 
-     * Function call parsing is essential for calling functions in the language.
-     * It handles the juxtaposition of function names and their arguments.
-     * 
-     * The function implements a recursive descent parser that handles
-     * the function name, followed by a parenthesized list of arguments.
-     * 
-     * Error handling includes checks for missing function name or arguments.
-     */
-    function parseFunctionCall() {
-        const functionName = tokens[current].value;
-        current++; // Skip function name
-        
-        // Parse arguments until we hit a semicolon or end of tokens
-        const args = [];
-        while (current &lt; tokens.length &amp;&amp; tokens[current].type !== TokenType.SEMICOLON) {
-            const arg = parseLogicalExpression();
-            args.push(arg);
-        }
-        
-        return {
-            type: 'FunctionCall',
-            name: functionName,
-            args
-        };
-    }
-    
-    /**
-     * Parse primary expressions (literals, identifiers, parenthesized expressions)
-     * 
-     * @returns {ASTNode} AST node representing the primary expression
-     * @throws {Error} For unexpected tokens or malformed expressions
-     * @description Parses the highest precedence expressions including literals,
-     * identifiers, function calls, table access, and parenthesized expressions.
-     * This is the foundation of the expression parsing hierarchy.
-     * 
-     * The function implements function call detection by looking
-     * for identifiers followed by expressions that could be arguments. This
-     * approach allows the language to support both traditional function calls
-     * and the ML-style function application syntax.
-     * 
-     * Supports:
-     * - Literals: numbers, strings, booleans
-     * - Identifiers: variables and function names
-     * - Function calls: f(x, y) or f x y
-     * - Table access: table[key] or table.property
-     * - Parenthesized expressions: (x + y)
-     * - Unary operators: not x, -x
-     * - Function references: @functionName
-     * 
-     * Primary expression parsing is the foundation of all other expression
-     * parsing. It handles literals, identifiers, function calls, table access,
-     * parenthesized expressions, and unary operators.
-     * 
-     * The function implements a recursive descent parser that handles
-     * each specific type of primary expression.
-     * 
-     * Error handling includes checks for missing literals, malformed
-     * identifiers, and unexpected tokens.
-     */
-    function parsePrimary() {
-        const token = tokens[current];
-        
-        if (!token) {
-            throw new Error('Unexpected end of input');
-        }
-        
-        if (DEBUG) {
-            console.log(`[DEBUG] parsePrimary: current token = ${token.type}, value = ${token.value || 'N/A'}`);
-        }
-        
-        switch (token.type) {
-            case TokenType.NUMBER:
-                current++;
-                return { type: 'NumberLiteral', value: token.value };
-                
-            case TokenType.STRING:
-                current++;
-                return { type: 'StringLiteral', value: token.value };
-                
-            case TokenType.TRUE:
-                current++;
-                return { type: 'BooleanLiteral', value: true };
-                
-            case TokenType.FALSE:
-                current++;
-                return { type: 'BooleanLiteral', value: false };
-                
-            case TokenType.WHEN:
-                return parseWhenExpression();
-                
-
-                
-            case TokenType.IDENTIFIER:
-                const identifierValue = token.value;
-                current++;
-                
-                // Check for table access: identifier[key] or identifier.property
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.LEFT_BRACKET) {
-                    current++; // Skip '['
-                    const keyExpression = parseLogicalExpression();
-                    
-                    if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_BRACKET) {
-                        throw new Error('Expected "]" after table key');
-                    }
-                    current++; // Skip ']'
-                    
-                    let tableNode = {
-                        type: 'TableAccess',
-                        table: { type: 'Identifier', value: identifierValue },
-                        key: keyExpression
-                    };
-                    
-                    // Check for chained access: table[key].property or table[key][key2]
-                    while (current &lt; tokens.length &amp;&amp; (tokens[current].type === TokenType.DOT || tokens[current].type === TokenType.LEFT_BRACKET)) {
-                        if (tokens[current].type === TokenType.DOT) {
-                            current++; // Skip '.'
-                            
-                            if (current >= tokens.length || tokens[current].type !== TokenType.IDENTIFIER) {
-                                throw new Error('Expected identifier after "." in table access');
-                            }
-                            
-                            const propertyName = tokens[current].value;
-                            current++; // Skip property name
-                            
-                            tableNode = {
-                                type: 'TableAccess',
-                                table: tableNode,
-                                key: { type: 'Identifier', value: propertyName }
-                            };
-                        } else if (tokens[current].type === TokenType.LEFT_BRACKET) {
-                            current++; // Skip '['
-                            const keyExpression2 = parseLogicalExpression();
-                            
-                            if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_BRACKET) {
-                                throw new Error('Expected "]" after table key');
-                            }
-                            current++; // Skip ']'
-                            
-                            tableNode = {
-                                type: 'TableAccess',
-                                table: tableNode,
-                                key: keyExpression2
-                            };
-                        }
-                    }
-                    
-                    return tableNode;
-                } else if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.DOT) {
-                    current++; // Skip '.'
-                    
-                    if (current >= tokens.length || tokens[current].type !== TokenType.IDENTIFIER) {
-                        throw new Error('Expected identifier after "." in table access');
-                    }
-                    
-                    const propertyName = tokens[current].value;
-                    current++; // Skip property name
-                    
-                    let tableNode = {
-                        type: 'TableAccess',
-                        table: { type: 'Identifier', value: identifierValue },
-                        key: { type: 'Identifier', value: propertyName }
-                    };
-                    
-                    // Check for chained access: table.property[key] or table.property.property2
-                    while (current &lt; tokens.length &amp;&amp; (tokens[current].type === TokenType.DOT || tokens[current].type === TokenType.LEFT_BRACKET)) {
-                        if (tokens[current].type === TokenType.DOT) {
-                            current++; // Skip '.'
-                            
-                            if (current >= tokens.length || tokens[current].type !== TokenType.IDENTIFIER) {
-                                throw new Error('Expected identifier after "." in table access');
-                            }
-                            
-                            const propertyName2 = tokens[current].value;
-                            current++; // Skip property name
-                            
-                            tableNode = {
-                                type: 'TableAccess',
-                                table: tableNode,
-                                key: { type: 'Identifier', value: propertyName2 }
-                            };
-                        } else if (tokens[current].type === TokenType.LEFT_BRACKET) {
-                            current++; // Skip '['
-                            const keyExpression = parseLogicalExpression();
-                            
-                            if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_BRACKET) {
-                                throw new Error('Expected "]" after table key');
-                            }
-                            current++; // Skip ']'
-                            
-                            tableNode = {
-                                type: 'TableAccess',
-                                table: tableNode,
-                                key: keyExpression
-                            };
-                        }
-                    }
-                    
-                    return tableNode;
-                }
-                
-                // Parenthesized expressions after identifiers are handled by parseApplication
-                // to support function calls like f(x)
-                if (current &lt; tokens.length &amp;&amp; tokens[current].type === TokenType.LEFT_PAREN) {
-                    // Don't handle this here, let parseApplication handle it
-                    // This ensures that f(x) is parsed as apply(f, x) not just x
-                }
-                
-                // Juxtaposition function calls are now handled in parseFactor() with proper precedence
-                return { type: 'Identifier', value: identifierValue };
-
-            case TokenType.LEFT_PAREN:
-                current++;
-                            if (DEBUG) {
-                console.log(`[DEBUG] parsePrimary: parsing LEFT_PAREN, current token = ${tokens[current].type}`);
-            }
-                const expression = parseLogicalExpression();
-                if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_PAREN) {
-                    throw new Error('Expected ")" after expression');
-                }
-                current++;
-                
-                // Check if this is just a simple identifier in parentheses
-                if (expression.type === 'Identifier') {
-                    return { 
-                        type: 'FunctionCall', 
-                        name: 'identity', 
-                        args: [expression] 
-                    };
-                }
-                
-                return expression;
-
-            case TokenType.WILDCARD:
-                current++;
-                return { type: 'WildcardPattern' };
-                
-            case TokenType.LEFT_BRACE:
-                return parseTableLiteral();
-                
-
-                
-                                                case TokenType.NOT:
-                current++;
-                const operand = parsePrimary();
-                return { 
-                    type: 'FunctionCall',
-                    name: 'logicalNot',
-                    args: [operand]
-                };
-                
-            case TokenType.MINUS:
-            case TokenType.UNARY_MINUS:
-                // Delegate unary minus to parseExpression for proper precedence
-                return parseExpression();
-                
-            case TokenType.ARROW:
-                current++;
-                const arrowBody = parseLogicalExpression();
-                return { type: 'ArrowExpression', body: arrowBody };
-                
-            case TokenType.FUNCTION_REF:
-                const functionRef = { type: 'FunctionReference', name: tokens[current].name };
-                current++;
-                return functionRef;
-                
-            case TokenType.FUNCTION_ARG:
-                // @(expression) - parse the parenthesized expression as a function argument
-                current++; // Skip FUNCTION_ARG token
-                if (current >= tokens.length || tokens[current].type !== TokenType.LEFT_PAREN) {
-                    throw new Error('Expected "(" after @');
-                }
-                current++; // Skip '('
-                const argExpression = parseLogicalExpression();
-                if (current >= tokens.length || tokens[current].type !== TokenType.RIGHT_PAREN) {
-                    throw new Error('Expected ")" after function argument expression');
-                }
-                current++; // Skip ')'
-                return argExpression;
-                
-            default:
-                throw new Error(`Unexpected token in parsePrimary: ${token.type}`);
-        }
-    }
-    
-    return parse();
-} </code></pre>
-        </article>
-    </section>
-
-
-
-
-</div>
-
-<br class="clear">
-
-<footer>
-    Generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc 4.0.4</a> on Tue Jul 29 2025 23:15:00 GMT-0400 (Eastern Daylight Time) using the Minami theme.
-</footer>
-
-<script>prettyPrint();</script>
-<script src="scripts/linenumber.js"></script>
-</body>
-</html>