CryptoPatrick / agents
Portrait of gf-core, The Polyglot #23 of 26

Agents/Language & dialogue

Grammar runtime Available v0.3.0

gf-core

The Polyglot

Runs Grammatical Framework grammars in Rust, no Haskell server needed.

7Downloads, all time
7Last 90 days
1Releases since Oct 2026

Downloads per day

Last 90 days · 7 total · peak 7

Dossier

What gf-core does.

Parses and linearizes text with pre-compiled GF (PGF) grammars in pure Rust.

From the crate: “Rust runtime for Grammatical Framework.”

Codename
The Polyglot
Role
Grammar runtime
Character
Speaks many languages through one grammar and is fussy about it. Parses first, translates second.
Domain
Language & dialogue
Enlisted
8 October 2026
Last release
v0.3.0, 8 October 2026
Keywords
gf, grammar, parser, runtime

Use cases

Put it to work.

Getting started

Call it in.

Add it to a Rust project, then follow the example. The full API is on docs.rs.

Install

cargo add gf-core

Example

-- a "Hello World" grammar
    abstract Hello = {
  
      flags startcat = Greeting ;
  
      cat Greeting ; Recipient ;
  
      fun
        Hello : Recipient -> Greeting ;
        World, Mum, Friends : Recipient ;
    }

More

concrete HelloEng of Hello = {
      lincat Greeting, Recipient = {s : Str} ;
  
      lin
        Hello recip = {s = "hello" ++ recip.s} ;
        World = {s = "world"} ;
        Mum = {s = "mum"} ;
        Friends = {s = "friends"} ;
    }

More

concrete HelloIta of Hello = {
      lincat Greeting, Recipient = {s : Str} ;
      lin
        Hello recip = {s = "ciao" ++ recip.s} ;
        World = {s = "mondo"} ;
        Mum = {s = "mamma"} ;
        Friends = {s = "amici"} ;
    }

More

use gf_core::*;
use std::fs;
use bytes::Bytes;


fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Uncomment the line below to see debug output from GF-Core operations
    set_debug(true);
    
    // Read the binary file containing the PGF grammar.
    let pgf_content = fs::read("grammars/Food/Food.pgf")?;
    
    // Parse the binary content of the PGF file.
    let pgf = pgf2json::parse_pgf(&Bytes::from(pgf_content))?;
    
    // Convert the PGF data into JSON formatl
    let json_string = pgf2json::pgf_to_json(&pgf)?;

    // Parse JSON into JSON values.
    let json_value: serde_json::Value = serde_json::from_str(&json_string)?;
    
    // Create a JSON valued PGF struct.
    let pgf_struct: PGF = serde_json::from_value(json_value)?;
    println!("TODO: Understand content of (pgf_struct): {:?}", pgf_struct);
    
    // Create a GF grammar from the PGF struct.
    let grammar: GFGrammar = GFGrammar::from_json(pgf_struct);
    
    // Test our fixed abstract syntax parsing
    let test_cases = [
        "Fish",
        "This(Fish)", 
        "Is(This(Fish), Delicious)",
        "MakeS (NP) (VP)",
    ];
    
    for test_case in test_cases {
        println!("\nTesting abstract syntax: '{}'", test_case);
        match grammar.abstract_grammar.parse_tree(test_case, None) {
            Some(tree) => {
                println!("✓ Parsed successfully: {}", tree.print());
                
                // Try to linearize this tree
                if let Some(eng_concrete) = grammar.concretes.get("FoodEng") {
                    println!("LOG: Attempting linearization with FoodEng concrete grammar");
                    let english_output = eng_concrete.linearize(&tree);
                    println!("  English: '{}'", english_output);
                }
            }
            None => {
                println!("✗ Failed to parse");
            }
        }
    }
    
    // Also test the natural language parsing for comparison
    println!("\n=== Natural Language Parsing (for comparison) ===");
    if let Some(eng_concrete) = grammar.concretes.get("FoodEng") {
        let trees = eng_concrete.parse_string("this fish is delicious", &grammar.abstract_grammar.startcat);
        
        if trees.is_empty() {
            println!("No valid parse found for 'this fish is delicious'");
        } else {
            println!("Found {} parse tree(s):", trees.len());
            for (i, tree) in trees.iter().enumerate() {
                println!("  Tree {}: {}", i + 1, tree.print());
                
                // Linearize back to English
                let english_output = eng_concrete.linearize(tree);
                println!("  English: {}", english_output);
            }
        }
    }

    // Note: FoodIta concrete grammar not available in this PGF file
    println!("Available concrete grammars: {:?}", grammar.concretes.keys().collect::<Vec<_>>());

    Ok(())
}

Build with a prompt

Add the Rust crate `gf-core` (version 0.3.0) to this project with `cargo add gf-core`. I want to use it for this: Parses and linearizes text with pre-compiled GF (PGF) grammars in pure Rust. Before writing code, read its README at https://crates.io/crates/gf-core and the API docs at https://docs.rs/gf-core. Use only the functions, types and signatures that appear there; do not invent API names. Write a minimal working example and one test that runs it.

Paste this into Claude Code or another coding agent.

Specs

Version
0.3.0
License
MIT
Edition
Rust 2021
MSRV
1.88
Size
3,267 lines of code, 81 of comments
Package
60.8 KB compressed
Dependencies
bytes, clap, pgf2json, regex, serde, serde_json
Used by
0 crates on crates.io
Docs
docs.rs, built
Repository
cryptopatrick/gf-core · 0★ · 0 forks · 0 open issues · pushed 15 Oct 2025

Release history

VersionDateDownloads
0.3.08 Oct 20267

Documentation

The manual.

The crate's README as published on crates.io. The full API reference is on docs.rs.

Read the README


GF-CORE
GF-CORE

Rust implementation of the Grammatical Framework runtime.

What is GF-CORE • Features • How To Use • Documentation • License

🛎 Important Notices

  • This is not a full Grammatical Framework compiler, only a runtime
  • Requires pre-compiled PGF files generated by the official GF compiler

📌 Table of Contents

Table of Contents
  1. What is GF-CORE
  2. Features
  3. How to Use
  4. Documentation
  5. Author
  6. Support
  7. Contributing
  8. License

🤔 What is GF-CORE

gf-core is a pure Rust implementation of the Grammatical Framework runtime that enables developers to integrate GF-powered multilingual natural language processing directly into Rust applications without requiring a separate Haskell-based GF server.

Use Cases

  • Multilingual Applications: Build applications that support multiple languages with consistent grammar rules
  • Natural Language Interfaces: Create command-line tools and APIs with natural language parsing capabilities
  • Translation Systems: Implement controlled translation between supported languages
  • Grammar-Based Text Generation: Generate natural language text from abstract syntax trees
  • Embedded Systems: Deploy GF capabilities in resource-constrained environments where Haskell dependencies are impractical

Architecture

The library provides a complete GF runtime environment:

  1. PGF Loading: Parse and load Portable Grammar Format files
  2. Abstract Syntax: Work with grammar-defined abstract syntax trees
  3. Concrete Syntax: Handle multiple concrete language implementations
  4. Bidirectional Processing: Parse natural language to AST and linearize AST to natural language

📷 Features

Core Runtime Capabilities

  • PGF Parser: Load and parse Portable Grammar Format files generated by GF compiler
  • Abstract Syntax Trees: Full support for GF abstract syntax with tree manipulation
  • Multi-language Support: Handle multiple concrete grammars simultaneously
  • Type Safety: Rust's type system ensures memory safety and correctness

Parsing & Linearization

  • Natural Language Parsing: Convert text strings to abstract syntax trees
  • Tree Linearization: Generate natural language text from abstract syntax
  • Bidirectional Processing: Seamlessly switch between parsing and generation
  • Grammar Validation: Ensure input conforms to loaded grammar rules

PGF Support

  • Binary Format: Direct loading of compiled PGF files
  • JSON Conversion: Convert PGF data to/from JSON for interoperability
  • Grammar Introspection: Access grammar metadata and structure
  • Multiple Concrete Grammars: Support for multilingual grammar files

JSON Integration

  • Serialization: Convert grammar structures to JSON format
  • Deserialization: Load grammars from JSON representations
  • API Compatibility: Easy integration with web services and APIs
  • Debug Output: Human-readable grammar inspection

🚙 How to Use

Requirements

gf-core requires:

  • Rust 1.70 or higher
  • Pre-compiled PGF files (generated using the official GF compiler)

Installation

Install with cargo:

cargo add gf-core

Step 1: Write a grammar

To use this crate we need a grammar. Typically we want to write three grammars; an abstract grammar, and two concrete grammars.

Abstact Grammar File: Hello.gf

 -- a "Hello World" grammar
    abstract Hello = {
  
      flags startcat = Greeting ;
  
      cat Greeting ; Recipient ;
  
      fun
        Hello : Recipient -> Greeting ;
        World, Mum, Friends : Recipient ;
    }

Concrete English Grammar File: HelloEng.gf

concrete HelloEng of Hello = {
      lincat Greeting, Recipient = {s : Str} ;
  
      lin
        Hello recip = {s = "hello" ++ recip.s} ;
        World = {s = "world"} ;
        Mum = {s = "mum"} ;
        Friends = {s = "friends"} ;
    }

Concrete Italian Grammar File: HelloIta.gf

concrete HelloIta of Hello = {
      lincat Greeting, Recipient = {s : Str} ;
      lin
        Hello recip = {s = "ciao" ++ recip.s} ;
        World = {s = "mondo"} ;
        Mum = {s = "mamma"} ;
        Friends = {s = "amici"} ;
    }

Step 2: Compile the grammars into PGF

Once we have our grammars written, we need to compile them into PGF (Portable Grammar Format). To do this, we need the GF CLI, which is part of the GF binary.

The GF binary and cli can be downloaded from this page

# Compile the grammar into Hello.pgf
gf -make HelloEng.gf HelloIta.gf

Running this command, GF will look at Hello.gf (since it's what the concrete syntaxes depend on) and then produce the PGF file: Hello.pgf.

Step 3: Use the runtime

Example

Here's a complete example demonstrating the gf-core runtime:

use gf_core::*;
use std::fs;
use bytes::Bytes;


fn main() -> Result<(), Box<dyn std::error::Error>> {
    // Uncomment the line below to see debug output from GF-Core operations
    set_debug(true);
    
    // Read the binary file containing the PGF grammar.
    let pgf_content = fs::read("grammars/Food/Food.pgf")?;
    
    // Parse the binary content of the PGF file.
    let pgf = pgf2json::parse_pgf(&Bytes::from(pgf_content))?;
    
    // Convert the PGF data into JSON formatl
    let json_string = pgf2json::pgf_to_json(&pgf)?;

    // Parse JSON into JSON values.
    let json_value: serde_json::Value = serde_json::from_str(&json_string)?;
    
    // Create a JSON valued PGF struct.
    let pgf_struct: PGF = serde_json::from_value(json_value)?;
    println!("TODO: Understand content of (pgf_struct): {:?}", pgf_struct);
    
    // Create a GF grammar from the PGF struct.
    let grammar: GFGrammar = GFGrammar::from_json(pgf_struct);
    
    // Test our fixed abstract syntax parsing
    let test_cases = [
        "Fish",
        "This(Fish)", 
        "Is(This(Fish), Delicious)",
        "MakeS (NP) (VP)",
    ];
    
    for test_case in test_cases {
        println!("\nTesting abstract syntax: '{}'", test_case);
        match grammar.abstract_grammar.parse_tree(test_case, None) {
            Some(tree) => {
                println!("✓ Parsed successfully: {}", tree.print());
                
                // Try to linearize this tree
                if let Some(eng_concrete) = grammar.concretes.get("FoodEng") {
                    println!("LOG: Attempting linearization with FoodEng concrete grammar");
                    let english_output = eng_concrete.linearize(&tree);
                    println!("  English: '{}'", english_output);
                }
            }
            None => {
                println!("✗ Failed to parse");
            }
        }
    }
    
    // Also test the natural language parsing for comparison
    println!("\n=== Natural Language Parsing (for comparison) ===");
    if let Some(eng_concrete) = grammar.concretes.get("FoodEng") {
        let trees = eng_concrete.parse_string("this fish is delicious", &grammar.abstract_grammar.startcat);
        
        if trees.is_empty() {
            println!("No valid parse found for 'this fish is delicious'");
        } else {
            println!("Found {} parse tree(s):", trees.len());
            for (i, tree) in trees.iter().enumerate() {
                println!("  Tree {}: {}", i + 1, tree.print());
                
                // Linearize back to English
                let english_output = eng_concrete.linearize(tree);
                println!("  English: {}", english_output);
            }
        }
    }

    // Note: FoodIta concrete grammar not available in this PGF file
    println!("Available concrete grammars: {:?}", grammar.concretes.keys().collect::<Vec<_>>());

    Ok(())
}

This program will:

  1. Load the Food.pgf grammar file
  2. Parse it and convert it to JSON
  3. Create a GFGrammar from the JSON
  4. Parse abstract syntax expressions into ASTs
  5. Linearize ASTs back to natural language text
  6. Demonstrate natural language parsing capabilities

📚 Documentation

Comprehensive documentation is available at docs.rs/gf-core, including:

  • API reference for all public types and functions
  • Tutorial on working with GF grammars in Rust
  • Examples of different parsing and linearization strategies
  • Performance considerations and best practices

🖊 Author

CryptoPatrick

Keybase Verification:
https://keybase.io/cryptopatrick/sigs/8epNh5h2FtIX1UNNmf8YQ-k33M8J-Md4LnAN

🐣 Support

Leave a ⭐ if you think this project is cool.

🤝 Contributing

Found a bug? Missing a specific feature? Contributions are welcome! Please see our contributing guidelines for details on:

  • Code style and testing requirements
  • Submitting bug reports and feature requests
  • Development setup and workflow

🗄 License

This project is licensed under MIT. See LICENSE for details.

Resources

Same unit

Other agents.