parlex-calc

Crates.ioparlex-calc
lib.rsparlex-calc
version0.3.0
created_at2025-10-14 11:25:40.480776+00
updated_at2025-10-23 10:16:44.720785+00
descriptionParlex example: simple calculator
homepage
repositoryhttps://github.com/ikhomyakov/parlex.git
max_upload_size
id1882087
size106,222
Igor Y. Khomyakov (ikhomyakov)

documentation

README

parlex-calc

Crates.io Documentation License: LGPL-3.0-or-later Rust

A sample calculator built using the parlex and parlex-gen toolchain. This crate demonstrates the full workflow of defining, generating, and running a small but complete language processor using ALEX and ASLR.

Highlights

  • Implements a complete expression parser with arithmetic, identifiers, and assignments
  • Shows how to integrate generated lexer and parser code with user-defined driver logic
  • Demonstrates runtime ambiguity resolution using operator precedence
  • Uses a simple symbol table (SymTab) for variable storage and lookup

Components

  • CalcLexer — Tokenizes numeric literals, identifiers, operators, parentheses, and separators
  • CalcParser — Parses arithmetic expressions, statements, and assignments
  • CalcLexerDriver / CalcParserDriver — Implement runtime actions for tokenization and parsing
  • SymTab — Maintains variable bindings, allowing expressions like a = 2 + 3; b = a * 10;
  • CalcError — Unified error type covering lexical, parsing, and semantic errors

Example

use parlex_calc::{CalcParser, SymTab};
use try_next::{IterInput, TryNextWithContext};

fn main() -> Result<(), Box<dyn std::error::Error>> {
    let mut symtab = SymTab::new();
    let input = IterInput::from("x = 2 + 3; y = x * 4;".bytes());
    let mut parser = CalcParser::try_new(input)?;
    let results = parser.try_collect_with_context(&mut symtab)?;
    for r in results {
        println!("Parsed: {:?}", r);
    }
    Ok(())
}

This example shows how to:

  • Create an input stream (IterInput)
  • Instantiate a parser and shared context (SymTab)
  • Parse and evaluate multiple statements from the same stream

Learning Purposes

The calculator serves as:

  • A reference implementation of how to connect a lexer and parser generated by Parlex

  • A template project for building interpreters, DSLs, or scripting languages in Rust

  • A demonstration of end-to-end Parlex integration with try_next::TryNextWithContext streaming APIs

Running parlex-calc binary

cargo run -p parlex-calc -- parse <<EOS
/* examples */
/* statement 1 */
x = 2 + 3;
/* statement 2 */
y = x * 4
EOS

Prints both the symbol table (SymTab) and the parsed token stream.

[parlex-calc/src/main.rs:171:13] &parser.stats() = (
    LexerStats {
        unreads: 63,
        chars: 72,
        matches: 34,
    },
    ParserStats {
        tokens: 16,
        shifts: 13,
        reductions: 11,
        ambigs: 0,
    },
)
[parlex-calc/src/main.rs:172:13] &symtab = SymTab {
    tab: {
        "x": 5,
        "y": 20,
    },
}
[parlex-calc/src/main.rs:173:13] &toks = [
    CalcToken {
        token_id: Stat,
        value: Stat {
            comments: [
                "/* examples */",
                "/* statement 1 */",
            ],
            value: Some(
                5,
            ),
        },
        span: Some(
            Span {
                start: Position {
                    line: 0,
                    column: 0,
                },
                end: Position {
                    line: 2,
                    column: 9,
                },
            },
        ),
    },
    CalcToken {
        token_id: Stat,
        value: Stat {
            comments: [
                "/* statement 2 */",
            ],
            value: Some(
                20,
            ),
        },
        span: Some(
            Span {
                start: Position {
                    line: 3,
                    column: 0,
                },
                end: Position {
                    line: 4,
                    column: 9,
                },
            },
        ),
    },
]

Building & testing

At the repository root:

cargo build
cargo test

License

Copyright (c) 2005–2025 IKH Software, Inc.

Released under the terms of the GNU Lesser General Public License, version 3.0 or (at your option) any later version (LGPL-3.0-or-later).

Contributing

Contributions are welcome! Please feel free to submit issues or pull requests.

Commit count: 0

cargo fmt