Agents/Language & dialogue
gf-core
The Polyglot
Runs Grammatical Framework grammars in Rust, no Haskell server needed.
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.
- Parse controlled natural language into a structured tree.
- Translate between languages with one shared grammar.
- Build a command-line tool that understands natural-language commands.
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
| Version | Date | Downloads |
|---|---|---|
| 0.3.0 | 8 Oct 2026 | 7 |
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
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
🤔 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:
- PGF Loading: Parse and load Portable Grammar Format files
- Abstract Syntax: Work with grammar-defined abstract syntax trees
- Concrete Syntax: Handle multiple concrete language implementations
- 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:
- Load the
Food.pgfgrammar file - Parse it and convert it to JSON
- Create a GFGrammar from the JSON
- Parse abstract syntax expressions into ASTs
- Linearize ASTs back to natural language text
- 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
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.
-
isuRust implementation of Information State Update theory, applicable in Issue-Based Dialogue Management and Conversational Agent Architecture.
-
pgf2jsonThis crate is an Application Programming Interface to load and interpret grammars compiled in Portable Grammar Format (PGF). The PGF format is produced as a final output from the GF compiler. The library provides methods for generating JSON output of a correctly formed PGF file. The API is meant to be used for embedding GF grammars in Rust programs.
-
squadleader-scenario
Scenario builder tools for the SquadLeader system.
-
hugin
A visual cpu profiler.