Skip to content

Instantly share code, notes, and snippets.

@RadicalZephyr
Last active April 21, 2021 23:43
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save RadicalZephyr/c77111fe212cc0c9265d85110998fadc to your computer and use it in GitHub Desktop.
Save RadicalZephyr/c77111fe212cc0c9265d85110998fadc to your computer and use it in GitHub Desktop.
GCode parser built using LALRPOP
use std::str::FromStr;
use lalrpop_util::ParseError;
use crate::gcode::{GCode, Mnemonic};
use crate::parse::Error as GCodeError;
grammar;
extern {
type Error = GCodeError;
}
pub GCodeExpr: GCode = {
<Word> " " <Args> => GCode::code_and_args(<>),
};
Word: (Mnemonic, u32, Option<u32>) = {
<letter:r"[GMPT]"><major_number:Number><minor_number:("."<Number>)?> =>? {
Ok((
Mnemonic::from_str(letter).map_err(|_| ParseError::User {
error: GCodeError::UnknownMnemonic(letter.chars().next().unwrap())
})?,
major_number,
minor_number,
))
}
}
Number: u32 = {
r"[0-9]+" =>? u32::from_str(<>).map_err(|_| ParseError::User {
error: GCodeError::NumberTooBig
})
}
Args: Vec<Arg> = {
<mut v:(" " <ArgExpr>)*><e:ArgExpr?> => match e {
Some(e) => { v.push(e); v },
None => v,
}
}
ArgExpr: Arg = {
<letter:r"[A-MO-Za-mo-z]"><value:Float> => Arg::standard(letter.chars().next().unwrap(), value)
}
Float: f32 = {
r"[0-9]+(\.[0-9]+)?" =>? f32::from_str(<>).map_err(|_| ParseError::User {
error: GCodeError::NumberTooBig,
})
}
use std::str::FromStr;
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum Mnemonic {
General,
Miscellaneous,
ProgramNumber,
ToolChange,
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct UnknownMnemonic;
impl FromStr for Mnemonic {
type Err = UnknownMnemonic;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"g" | "G" => Ok(Mnemonic::General),
"m" | "M" => Ok(Mnemonic::Miscellaneous),
"p" | "P" => Ok(Mnemonic::ProgramNumber),
"t" | "T" => Ok(Mnemonic::ToolChange),
_ => Err(UnknownMnemonic),
}
}
}
#[derive(Clone, Debug, PartialEq)]
pub struct GCode {
mnemonic: Mnemonic,
major_number: u32,
minor_number: Option<u32>,
arguments: Vec<Arg>,
}
impl GCode {
pub fn new(
mnemonic: Mnemonic,
major_number: u32,
minor_number: Option<u32>,
arguments: Vec<Arg>,
) -> Self {
Self {
mnemonic,
major_number,
minor_number,
arguments,
}
}
pub fn code_and_args(
(mnemonic, major_number, minor_number): (Mnemonic, u32, Option<u32>),
) -> Self {
Self {
mnemonic,
major_number,
minor_number,
arguments: Vec::new(),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Arg {
letter: char,
value: ArgValue,
}
impl Arg {
pub fn standard(letter: char, value: f32) -> Self {
Self {
letter,
value: ArgValue::Float(value),
}
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ArgValue {
Float(f32),
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment