Simone Siega

case study - 5 min read

CFG Parser

Grammar-based CLI parser that converts arithmetic expressions into a structured parsing pipeline with validation and clear error reporting.

  • Language: Rust
  • Type: CLI tool
  • Parser: Recursive descent
  • Architecture: Tokenizer -> Parser -> Evaluator
  • Focus: Deterministic grammar parsing

Overview

CFG Parser is a command-line project that parses and evaluates arithmetic expressions using a context-free grammar. The project was developed as my first hands-on exploration of both Rust and context-free grammars. Rust was chosen for its strong guarantees around memory safety, performance, and low-level control, making it well suited for building reliable systems-oriented tooling.

Goal

The objective was to transform raw user input into well-structured arithmetic expressions while preserving operator precedence and providing clear feedback for invalid syntax. The project focuses on building a predictable parsing flow where each stage of the pipeline has a clear responsibility.

Technical Approach

The system separates tokenization from parsing so each stage remains testable, predictable, and easy to reason about. Input expressions are first converted into a stream of tokens, which are then consumed by grammar-driven parsing rules that evaluate the expression in a controlled and deterministic manner.

Architecture

The application follows a simple linear pipeline: input handling, tokenization, parsing, evaluation, and formatted output. Each component operates independently, which keeps dependencies minimal and allows individual stages to be debugged or extended without affecting the rest of the system.

CFG Parser architecture diagram

Key Decisions

The implementation prioritizes explicit parsing stages and readability over compact abstractions. This approach makes the system easier to debug, reason about, and extend when introducing new grammar rules or expression features.

  • Keep tokenizer and parser isolated with clear input/output boundaries.
  • Represent grammar behavior explicitly to simplify edge-case analysis.
  • Design CLI output to provide concise and actionable parser diagnostics.

Challenges

One of the main challenges was handling malformed expressions without triggering cascading parser failures. The solution involved introducing guard checks and controlled fallback branches within the parsing flow to keep evaluation stable even when encountering unexpected input.

  • Recover gracefully from missing tokens and unexpected symbols.
  • Prevent invalid intermediate states from propagating into evaluation.
  • Keep diagnostics readable without exposing internal parser complexity.

What I Learned

Building this project provided a practical introduction to Rust and reinforced core concepts of grammar-driven software design. It also highlighted how explicit parsing stages and clear module boundaries significantly improve maintainability, testing, and debugging in systems-oriented applications.

Future Improvements

Future iterations could extend the grammar to support more advanced mathematical expressions and improve developer ergonomics through richer diagnostics and additional testing strategies.

  • Introduce support for trigonometric functions such as sin, cos, and tan within the grammar.
  • Allow expressions containing symbolic variables and unknowns rather than only numeric inputs.
  • Add equation validation and evaluation capabilities to support expressions like linear equations.

Links

Additional resources for exploring the project, including the source repository and detailed technical documentation.