A crate for parsing g-code programs, designed with embedded environments in mind.
Some explicit design goals of this crate are:
- embedded-friendly: users should be able to use this crate without
requiring access to an operating system (e.g.
#[no_std]
environments or WebAssembly) - deterministic memory usage: the library can be tweaked to use no
dynamic allocation (see [
buffers::Buffers
]) - error-resistant: erroneous input won't abort parsing, instead
notifying the caller and continuing on (see [
Callbacks
]) - performance: parsing should be reasonably fast, guaranteeing
O(n)
time complexity with no backtracking
Getting Started
The typical entry point to this crate is via the [parse()
] function. This
gives you an iterator over the [GCode
]s in a string of text, ignoring any
errors or comments that may appear along the way.
use Mnemonic;
let src = r#"
G90 (absolute coordinates)
G00 X50.0 Y-10 (move somewhere)
"#;
let got: = parse.collect;
assert_eq!;
let g90 = &got;
assert_eq!;
assert_eq!;
assert_eq!;
let rapid_move = &got;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
The [full_parse_with_callbacks()
] function can be used if you want access
to [Line
] information and to be notified on any parse errors.
use ;
/// A custom set of [`Callbacks`] we'll use to keep track of errors.
let src = r"
G90 N1 ; Line numbers (N) should be at the start of a line
G ; there was a G, but no number
G01 X50 $$%# Y20 ; invalid characters are ignored
";
let mut errors = default;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Customising Memory Usage
You'll need to manually create a [Parser
] if you want control over buffer
sizes instead of relying on [buffers::DefaultBuffers
].
You shouldn't normally need to do this unless you are on an embedded device
and know your expected input will be bigger than
[buffers::SmallFixedBuffers
] will allow.
use ;
use ArrayVec;
/// A type-level variable which contains definitions for each of our buffer
/// types.
let src = "G90 G01 X5.1";
let parser: = new;
let lines = parser.count;
assert_eq!;
Spans
Something that distinguishes this crate from a lot of other g-code parsers
is that each element's original location, its [Span
], is retained and
passed to the caller.
This is important for applications such as:
- Indicating where in the source text a parsing error or semantic error has occurred
- Visually highlighting the command currently being executed when stepping through a program in a simulator
- Reporting what point a CNC machine is up to when executing a job
It's pretty easy to check whether something contains its [Span
], just look
for a span()
method (e.g. [GCode::span()
]) or a span
field (e.g.
[Comment::span
]).
Cargo Features
Additional functionality can be enabled by adding feature flags to your
Cargo.toml
file:
- std: adds
std::error::Error
impls to any errors and switches toVec
for the default backing buffers - serde-1: allows serializing and deserializing most types with
serde