Module parser

Module parser 

Source
Expand description

Command-line and REPL parsing

This module provides comprehensive parsing functionality for both traditional command-line interfaces (CLI) and interactive REPL mode.

§Module Structure

The parser module consists of three main components:

  • type_parser: Type conversion functions (string → typed values)
  • cli_parser: CLI argument parser (Unix-style options)
  • repl_parser: REPL line parser (interactive mode)

§Architecture

┌─────────────────────────────────────────┐
│         User Input                      │
│   "process file.txt --verbose"          │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│       ReplParser (REPL mode)            │
│   - Tokenize line                       │
│   - Resolve command name via Registry   │
│   - Delegate to CliParser               │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│       CliParser (CLI mode)              │
│   - Parse positional arguments          │
│   - Parse options (-v, --verbose)       │
│   - Apply defaults                      │
│   - Use TypeParser for conversion       │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│       TypeParser                        │
│   - Convert strings to typed values     │
│   - Validate type constraints           │
└──────────────┬──────────────────────────┘
               │
               ▼
┌─────────────────────────────────────────┐
│   HashMap<String, String>               │
│   {"input": "file.txt",                 │
│    "verbose": "true"}                   │
└─────────────────────────────────────────┘

§Design Principles

§1. Separation of Concerns

Each parser has a specific responsibility:

  • TypeParser: Handles type conversion only
  • CliParser: Handles CLI syntax (options, arguments)
  • ReplParser: Handles REPL-specific concerns (tokenization, command resolution)

§2. Composability

Parsers compose naturally:

  • ReplParser uses CliParser for argument parsing
  • CliParser uses TypeParser for type conversion
  • Each can be used independently when needed

§3. Error Clarity

All parsers provide detailed error messages with:

  • Clear descriptions of what went wrong
  • Suggestions for typos (via Levenshtein distance)
  • Hints for correct usage

§Usage Examples

§CLI Mode (Direct Argument Parsing)

use dynamic_cli::parser::cli_parser::CliParser;
use dynamic_cli::config::schema::{CommandDefinition, ArgumentDefinition, ArgumentType};

let definition = CommandDefinition {
    name: "process".to_string(),
    aliases: vec![],
    description: "Process files".to_string(),
    required: false,
    arguments: vec![
        ArgumentDefinition {
            name: "input".to_string(),
            arg_type: ArgumentType::Path,
            required: true,
            description: "Input file".to_string(),
            validation: vec![],
        }
    ],
    options: vec![],
    implementation: "handler".to_string(),
};

let parser = CliParser::new(&definition);
let args = vec!["input.txt".to_string()];
let parsed = parser.parse(&args).unwrap();

assert_eq!(parsed.get("input"), Some(&"input.txt".to_string()));

§REPL Mode (Interactive Parsing)

use dynamic_cli::parser::repl_parser::ReplParser;
use dynamic_cli::registry::CommandRegistry;

let registry = CommandRegistry::new();
// ... register commands ...

let parser = ReplParser::new(&registry);

// Parse user input
let line = "process input.txt --verbose";
let parsed = parser.parse_line(line).unwrap();

println!("Command: {}", parsed.command_name);
println!("Arguments: {:?}", parsed.arguments);

§Type Parsing (Low-Level)

use dynamic_cli::parser::type_parser::{parse_integer, parse_bool};

let number = parse_integer("42").unwrap();
assert_eq!(number, 42);

let flag = parse_bool("yes").unwrap();
assert_eq!(flag, true);

§Error Handling

All parsing functions return Result<T> where errors are instances of [ParseError]. Common error scenarios:

  • Unknown command: User typed a non-existent command

    Error: Unknown command: 'simulat'
    ? Did you mean:
      • simulate
      • validation
  • Type mismatch: Value cannot be converted to expected type

    Error: Failed to parse count as integer: 'abc'
  • Missing argument: Required argument not provided

    Error: Missing required argument: input for command 'process'

§Performance Considerations

  • Type parsing: O(1) for most types, O(n) for string length
  • CLI parsing: O(n) where n = number of arguments
  • REPL parsing: O(m + n) where m = line length (tokenization), n = arguments
  • Command resolution: O(1) via HashMap lookup in registry

§Thread Safety

All parsers are:

  • Stateless: Can be used concurrently from multiple threads
  • Borrowing: Use references to definitions/registry (no ownership)
  • Reusable: Can parse multiple commands with the same parser instance

§Future Extensions

Potential enhancements for future versions:

  • Support for subcommands (e.g., git commit)
  • Environment variable expansion
  • Glob pattern matching for paths
  • Command history and auto-completion hints
  • Streaming parser for very large inputs

Re-exports§

pub use cli_parser::CliParser;
pub use repl_parser::ParsedCommand;
pub use repl_parser::ReplParser;

Modules§

cli_parser
CLI argument parser
repl_parser
REPL line parser
type_parser
Type parsing functions