Skip to content

Instantly share code, notes, and snippets.

@ChristopherBiscardi
Created February 7, 2023 14:19
Show Gist options
  • Save ChristopherBiscardi/668b89ad5b5be39f0c504e13ee11f4f2 to your computer and use it in GitHub Desktop.
Save ChristopherBiscardi/668b89ad5b5be39f0c504e13ee11f4f2 to your computer and use it in GitHub Desktop.
nom custom error examples
use color_eyre::eyre::{Result, Context};
use nom::{
bytes::complete::tag,
character::complete::alpha1,
combinator::rest,
error::{ErrorKind, ParseError},
sequence::preceded,
*,
};
use thiserror::Error; // 1.0.38
#[derive(Error, Debug)]
pub enum MyParserError<I> {
#[error("nom error")]
NomError(#[from] nom::error::Error<I>),
#[error("No #+ symbol")]
NoHash,
}
impl<I> ParseError<I> for MyParserError<I> {
// on one line, we show the error code and the input that caused it
fn from_error_kind(input: I, kind: ErrorKind) -> Self {
let nom_error =
nom::error::Error::from_error_kind(input, kind);
MyParserError::NomError(nom_error)
}
fn append(
input: I,
kind: ErrorKind,
other: Self,
) -> Self {
other
}
}
#[derive(Debug, PartialEq)]
struct AttributeInfo {
name: String,
identifier: String,
}
fn parse(
input: &str,
) -> IResult<&str, AttributeInfo, MyParserError<&str>> {
let result: nom::IResult<&str, &str> =
preceded(tag("#+"), alpha1)(input);
let Ok((input, name)) = result else {
return Err(nom::Err::Failure(MyParserError::NoHash));
};
let (input, identifier) =
preceded(tag(": "), rest)(input)?;
Ok((
input,
AttributeInfo {
name: name.to_string(),
identifier: identifier.to_string(),
},
))
}
fn main() -> Result<()> {
color_eyre::install()?;
let input = "malformatted Short informational text";
let result = parse(input).wrap_err("tried to parse");
dbg!(&result);
let output = result.unwrap();
dbg!(output);
Ok(())
}
#[test]
fn parse_works() {
let input = "#+TITLE: sdfkljsadflk";
let output = parse(input).unwrap();
assert_eq!(
(
"",
AttributeInfo {
name: "TITLE".to_string(),
identifier: "sdfkljsadflk".to_string()
},
),
output
);
}
use color_eyre::eyre::{Context, Result};
use nom::{
bytes::complete::tag, character::complete::alpha1,
combinator::rest, sequence::preceded, *,
};
use nom_supreme::{error::ErrorTree, ParserExt};
#[derive(Debug, PartialEq)]
struct AttributeInfo {
name: String,
identifier: String,
}
fn parse(
input: &str,
) -> IResult<&str, AttributeInfo, ErrorTree<&str>> {
let (input, name) = preceded(
tag("#+")
.context("Requires that line starts with `#+`"),
alpha1,
)(input)?;
let (input, identifier) =
preceded(tag(": "), rest)(input)?;
Ok((
input,
AttributeInfo {
name: name.to_string(),
identifier: identifier.to_string(),
},
))
}
fn main() -> Result<()> {
color_eyre::install()?;
let input = "malformatted Short informational text";
let result = parse(input).context("tried to parse");
dbg!(&result);
let output = result.unwrap();
dbg!(output);
Ok(())
}
#[test]
fn parse_works() {
let input = "#+TITLE: sdfkljsadflk";
let output = parse(input).unwrap();
assert_eq!(
(
"",
AttributeInfo {
name: "TITLE".to_string(),
identifier: "sdfkljsadflk".to_string()
},
),
output
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment