Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

ROUP

Rust-based OpenMP & OpenACC Parser

Safe, fast, and comprehensive directive parsing

Get Started · Tutorials · API Reference · GitHub


What is ROUP?

ROUP is an experimental parser for OpenMP and OpenACC directives, written in safe Rust with C, C++, and Fortran bindings. Parse pragmas like #pragma omp parallel for or !$acc parallel into structured data that your tools can analyze, transform, and process.

⚠️ Experimental Status: ROUP is under active development and not yet production-ready. APIs may change, and some OpenMP features are still being implemented. Use in research and experimental projects.

Perfect for:

  • 🔧 Compiler research - Experiment with OpenMP parsing in compilers
  • 🔍 Analysis prototypes - Build experimental linters and analyzers
  • 🎓 Researchers - Study parallelization patterns and test new ideas
  • 📚 Educators - Teaching tool for parallel programming concepts

Why ROUP?

🚀 Fast & Lightweight

  • Zero-copy lexer and hand-written parsers
  • Standalone library (no LLVM/ANTLR dependencies)
  • Compatibility shims for ompparser and accparser

🛡️ Safe & Reliable

  • Memory safety guaranteed except for the narrow FFI boundary
  • Extensive automated tests plus OpenMP_VV/OpenACCV-V validation and compat ctests
  • NULL-safe C API with defensive checks

📚 Comprehensive Directive Support

  • OpenMP 3.0–6.0 directives, clauses, combined forms, and metadirectives
  • OpenACC 3.4 directives, clauses, aliases, and end-paired constructs
  • Canonical keyword handling and clause alias preservation
  • Interactive parser debugger (roup_debug) for OpenMP/OpenACC (C and Fortran sentinels)

🔌 Multi-Language APIs

LanguageAPI StyleMemory ManagementStatus
RustNativeAutomatic (ownership)
CPointer-basedManual (malloc/free pattern)
C++RAII wrappersAutomatic (destructors)
FortranC interopManual (via iso_c_binding)✅ (via C API)

Quick Example

Parse in 3 Lines (Rust)

use roup::parser::openmp;

let parser = openmp::parser();
let (_, directive) = parser.parse("#pragma omp parallel for num_threads(4)").unwrap();
// Access directive information
println!("Directive: {}", directive.name);  // Output: Directive: parallel for
println!("Found {} clauses", directive.clauses.len());  // Output: Found 1 clauses
// Iterate through clauses
for clause in &directive.clauses {
    println!("  Clause: {}", clause.name);  // Output:   Clause: num_threads
}

Parse in C

OmpDirective* dir = roup_parse("#pragma omp parallel for num_threads(4)");
printf("Clauses: %d\n", roup_directive_clause_count(dir));
roup_directive_free(dir);

Parse in C++ (with RAII)

roup::Directive dir("#pragma omp parallel for num_threads(4)");
std::cout << "Clauses: " << dir.clause_count() << "\n";
// Automatic cleanup!

Parse Fortran

! Free-form Fortran
directive_ptr = roup_parse_with_language("!$OMP PARALLEL PRIVATE(A)", &
                                          ROUP_LANG_FORTRAN_FREE)

See full examples →


Feature Highlights

🎯 Comprehensive Coverage

Parallel Constructs - 20+ directives
  • parallel - Basic parallel regions
  • parallel for - Combined parallel + worksharing
  • parallel sections - Parallel sections
  • parallel master - Parallel master thread
  • parallel loop - OpenMP 5.0+ parallel loop
  • And more…
Work-Sharing - 10+ directives
  • for / do - Loop worksharing
  • sections / section - Code sections
  • single - Execute once
  • workshare - Fortran worksharing
  • loop - Generic loop construct
Tasking - 15+ directives
  • task - Explicit tasks
  • taskloop - Loop-based tasks
  • taskgroup - Task synchronization
  • taskwait - Wait for tasks
  • taskyield - Yield to other tasks
  • Dependency clauses: depend, priority, detach
Device Offloading - 25+ directives
  • target - Offload to device
  • target data - Device data management
  • target enter/exit data - Data transfer
  • target update - Synchronize data
  • teams - Multiple thread teams
  • distribute - Distribute iterations
SIMD - 10+ directives
  • simd - SIMD loops
  • declare simd - Vectorizable functions
  • distribute simd - Combined distribute + SIMD
  • Various alignment and vectorization clauses
Advanced (OpenMP 5.0+)
  • metadirective - Context-sensitive directives
  • declare variant - Function variants
  • loop - Generic loop construct
  • scan - Prefix scan operations
  • assume - Compiler assumptions

Full OpenMP Support Matrix →

🔍 Rich Clause Support

92+ clause types including:

CategoryClauses
Data Sharingprivate, shared, firstprivate, lastprivate
Reductionsreduction(+:x), reduction(min:y), custom operators
Schedulingschedule(static), schedule(dynamic,100), collapse(3)
Controlif(condition), num_threads(8), proc_bind(close)
Devicemap(to:x), device(2), defaultmap(tofrom:scalar)
Dependenciesdepend(in:x), depend(out:y), depend(inout:z)

Complete clause reference → | Edge cases | Handled (fuzzing tested) | Likely has bugs | | Spec compliance | Verified | Uncertain |

Verdict: Unless you have very specific needs, use ROUP.


Safety Guarantees

ROUP prioritizes safety without compromising usability:

Memory Safety

  • No buffer overflows - Rust prevents at compile time
  • No use-after-free - Ownership system enforces
  • No double-free - Checked at FFI boundary
  • No memory leaks - RAII and destructors
  • No data races - Thread-safe parsing

API Safety

Rust API:

  • 100% memory-safe by construction
  • Impossible to trigger undefined behavior

C API:

  • NULL checks before all pointer operations
  • Returns safe defaults on error (-1, NULL)
  • Validates UTF-8 encoding
  • Documents all safety contracts

Getting Started

Choose your language:

🦀 Rust

Install:

[dependencies]
roup = "0.7"

Learn:

🔧 C

Build:

cargo build --release

Learn:

⚙️ C++

Build:

cargo build --release

Learn:

Quick Start Guide →


Community


License

ROUP is open source under the MIT License.

Copyright © 2024-2025 Anjia Wang


Next Steps


Why ROUP?

For Compiler Developers

  • Drop-in OpenMP/OpenACC parser component
  • Well-tested, battle-hardened parsing logic
  • Easy FFI integration from any language

For Tool Builders

  • Analyze OpenMP code without a full compiler
  • Build linters, formatters, and code analyzers
  • Extract parallelization patterns from codebases

For Researchers

  • Study directive usage patterns
  • Prototype new directive extensions
  • Educational tool for learning parallel programming

Quick Example

Rust

use roup::parser::openmp;

let parser = openmp::parser();
let input = "#pragma omp parallel for num_threads(4) private(i)";
match parser.parse(input) {
    Ok((_, directive)) => {
        println!("Directive: {:?}", directive.kind);
        println!("Clauses: {}", directive.clauses.len());
    }
    Err(e) => eprintln!("Parse error: {:?}", e),
}

C

#include <stdio.h>

// Forward declarations
typedef struct OmpDirective OmpDirective;
extern OmpDirective* roup_parse(const char* input);
extern int32_t roup_directive_clause_count(const OmpDirective* dir);
extern void roup_directive_free(OmpDirective* dir);

int main() {
    OmpDirective* dir = roup_parse("#pragma omp parallel for num_threads(4)");
    if (dir) {
        printf("Clauses: %d\n", roup_directive_clause_count(dir));
        roup_directive_free(dir);
    }
    return 0;
}

C++

#include <iostream>
#include <memory>

struct OmpDirective;
extern "C" {
    OmpDirective* roup_parse(const char* input);
    int32_t roup_directive_clause_count(const OmpDirective* dir);
    void roup_directive_free(OmpDirective* dir);
}

// RAII wrapper
class Directive {
    OmpDirective* ptr_;
public:
    explicit Directive(const char* input) : ptr_(roup_parse(input)) {}
    ~Directive() { if (ptr_) roup_directive_free(ptr_); }
    bool valid() const { return ptr_ != nullptr; }
    int clause_count() const { 
        return ptr_ ? roup_directive_clause_count(ptr_) : 0; 
    }
};

int main() {
    Directive dir("#pragma omp parallel for num_threads(4)");
    if (dir.valid()) {
        std::cout << "Clauses: " << dir.clause_count() << "\n";
    }
    return 0;
}

Architecture

ROUP uses a clean, modular architecture:

┌─────────────────────────────────────────┐
│         Application Layer               │
│  (Your compiler/tool/analyzer)          │
└─────────────────┬───────────────────────┘
                  │
      ┌───────────┼───────────┐
      │           │           │
      ▼           ▼           ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│ Rust API│ │  C API  │ │ C++ API │
│         │ │         │ │ (RAII)  │
└─────────┘ └─────────┘ └─────────┘
      │           │           │
      └───────────┼───────────┘
                  │
                  ▼
         ┌────────────────┐
         │  Core Parser   │
         │  (nom-based)   │
         └────────────────┘
                  │
      ┌───────────┼───────────┐
      ▼           ▼           ▼
┌─────────┐ ┌─────────┐ ┌─────────┐
│  Lexer  │ │Directive│ │ Clause  │
│         │ │ Parser  │ │ Parser  │
└─────────┘ └─────────┘ └─────────┘

Key Design Principles:

  • Safe by default - Rust’s ownership system prevents memory errors
  • Zero-copy parsing - Uses string slices, not allocations
  • Minimal unsafe - FFI boundary only, well-documented
  • Extensible - Easy to add new directives and clauses

OpenMP Support

ROUP currently supports OpenMP 5.0+ with comprehensive coverage:

Supported Directives (15+)

  • parallel - Parallel regions
  • for - Worksharing loops
  • sections, single - Worksharing constructs
  • task, taskwait, taskgroup - Tasking
  • target, teams, distribute - Device offloading
  • barrier, critical, atomic - Synchronization
  • metadirective - Dynamic selection
  • And more…

Supported Clauses (50+)

  • Data sharing: private, shared, firstprivate, lastprivate
  • Parallelism control: num_threads, if, proc_bind
  • Worksharing: schedule, collapse, nowait
  • Reductions: reduction with 10+ operators (+, *, min, max, etc.)
  • Device: map, device, defaultmap
  • Dependencies: depend, in, out, inout
  • And more…

See the OpenMP Support Matrix for the complete list.


Safety Guarantees

All unsafe code is isolated to the FFI boundary (src/c_api.rs), documented with safety requirements, and NULL-checked before dereferencing.


Getting Started

Want to experiment with ROUP? Check out our tutorials:

Or jump straight to the code:


License

ROUP is open source under the MIT License.

Copyright © 2024-2025 Anjia Wang