Skip to content

Commit

Permalink
upgrade nom to v8 (#165)
Browse files Browse the repository at this point in the history
  • Loading branch information
CrockAgile authored Jan 30, 2025
1 parent 964f46a commit fa571dd
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 77 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ hashbrown = "0.15.0"
version = "0.9"

[dependencies.nom]
version = "^7.0.0"
version = "^8.0.0"

[dependencies.serde]
version = "1.0.118"
Expand Down
27 changes: 12 additions & 15 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ use std::error;
use std::fmt;
use std::str;

use nom::{
error::{VerboseError, VerboseErrorKind},
Err,
};
use nom::{error::ErrorKind, Err};

#[derive(PartialEq, Eq, Debug, Clone)]
#[non_exhaustive]
Expand All @@ -24,20 +21,20 @@ impl fmt::Display for Error {

impl error::Error for Error {}

impl From<VerboseError<(&'_ str, VerboseErrorKind)>> for Error {
fn from(err: VerboseError<(&str, VerboseErrorKind)>) -> Self {
impl From<nom::error::Error<&str>> for Error {
fn from(err: nom::error::Error<&str>) -> Self {
Error::ParseError(format!("Parsing error: {err:?}"))
}
}

impl From<Err<VerboseError<&str>>> for Error {
fn from(err: Err<VerboseError<&str>>) -> Self {
impl From<Err<nom::error::Error<&str>>> for Error {
fn from(err: Err<nom::error::Error<&str>>) -> Self {
Error::ParseError(format!("Parsing error: {err:?}"))
}
}

impl From<(&'_ str, VerboseErrorKind)> for Error {
fn from(err: (&str, VerboseErrorKind)) -> Self {
impl From<(&'_ str, ErrorKind)> for Error {
fn from(err: (&str, ErrorKind)) -> Self {
let string = format!("Parsing error: {:?}\n {:?}", err.1, err.0);
Error::ParseError(string)
}
Expand All @@ -46,9 +43,9 @@ impl From<(&'_ str, VerboseErrorKind)> for Error {
#[cfg(test)]
mod tests {
use crate::error::Error;
use nom::{bytes::complete::tag, error::VerboseError, Err, IResult};
use nom::{bytes::complete::tag, Err, IResult};

fn give_error_kind(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
fn give_error_kind(input: &str) -> IResult<&str, &str> {
let (input, _) = tag("1234")(input)?;
let (input, res) = tag("5678")(input)?;
Ok((input, res))
Expand Down Expand Up @@ -86,16 +83,16 @@ mod tests {

#[test]
fn from_nom_verbose_error() {
let error = nom::error::VerboseError { errors: vec![] };
let error = nom::error::Error::new("test", nom::error::ErrorKind::Tag);
assert!(matches!(Error::from(error), Error::ParseError(_)));
}

#[test]
fn from_str_and_nom_verbose_error_kind() {
let description = "anything";
let verbose_kind = nom::error::VerboseErrorKind::Char('z');
let error_kind = nom::error::ErrorKind::Char;
assert!(matches!(
Error::from((description, verbose_kind)),
Error::from((description, error_kind)),
Error::ParseError(_)
));
}
Expand Down
11 changes: 5 additions & 6 deletions src/parsers/augmented.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@ use nom::{
bytes::complete::{tag, take_till},
character::complete::{self, satisfy},
combinator::{complete, not},
error::VerboseError,
IResult,
IResult, Parser,
};

use super::whitespace_plus_comments;
Expand All @@ -15,7 +14,7 @@ use super::whitespace_plus_comments;
pub struct ABNF;

impl Format for ABNF {
fn prod_lhs(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
fn prod_lhs(input: &str) -> IResult<&str, Term> {
let (input, nt) = take_till(char::is_whitespace)(input)?;

let (input, _) = whitespace_plus_comments(input).unwrap();
Expand All @@ -25,13 +24,13 @@ impl Format for ABNF {
Ok((input, Term::Nonterminal(nt.to_string())))
}

fn nonterminal(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
satisfy(|c: char| c.is_alphabetic() || c == '_')(input)?;
fn nonterminal(input: &str) -> IResult<&str, Term> {
satisfy(|c: char| c.is_alphabetic() || c == '_').parse(input)?;
let (input, nt) = take_till(char::is_whitespace)(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();

//if this is the lefhandside of an expression then prod_lhs() should parse this
not(complete(tag("=")))(input)?;
not(complete(tag("="))).parse(input)?;

Ok((input, Term::Nonterminal(nt.to_string())))
}
Expand Down
18 changes: 7 additions & 11 deletions src/parsers/bnf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,29 @@ use nom::{
bytes::complete::{tag, take_until},
character::complete,
combinator::{complete, not},
error::VerboseError,
sequence::delimited,
IResult,
IResult, Parser,
};

#[non_exhaustive]
pub struct BNF;

impl Format for BNF {
fn prod_lhs(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
fn prod_lhs(input: &str) -> IResult<&str, Term> {
let (input, nt) =
delimited(complete::char('<'), take_until(">"), complete::char('>'))(input)?;
delimited(complete::char('<'), take_until(">"), complete::char('>')).parse(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();
let (input, _) = tag("::=")(input)?;
let (input, _) = tag("::=").parse(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();

Ok((input, Term::Nonterminal(nt.to_string())))
}

fn nonterminal(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
fn nonterminal(input: &str) -> IResult<&str, Term> {
let (input, nt) =
delimited(complete::char('<'), take_until(">"), complete::char('>'))(input)?;
delimited(complete::char('<'), take_until(">"), complete::char('>')).parse(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();

//if this is the lefhandside of an expression then prod_lhs() should parse this
not(complete(tag("::=")))(input)?;

not(complete(tag("::="))).parse(input)?;
Ok((input, Term::Nonterminal(nt.to_string())))
}
}
Expand Down
83 changes: 39 additions & 44 deletions src/parsers/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,37 +15,38 @@ use nom::{
bytes::complete::{take_till, take_until},
character::complete::{self, multispace0},
combinator::{all_consuming, complete, eof, opt, peek, recognize},
error::VerboseError,
multi::many1,
sequence::{delimited, preceded},
IResult,
IResult, Parser,
};

pub trait Format {
fn prod_lhs(input: &str) -> IResult<&str, Term, VerboseError<&str>>;
fn nonterminal(input: &str) -> IResult<&str, Term, VerboseError<&str>>;
fn prod_lhs(input: &str) -> IResult<&str, Term>;
fn nonterminal(input: &str) -> IResult<&str, Term>;
}

pub fn terminal(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
pub fn terminal(input: &str) -> IResult<&str, Term> {
let (input, t) = alt((
delimited(complete::char('"'), take_until("\""), complete::char('"')),
delimited(complete::char('\''), take_until("'"), complete::char('\'')),
))(input)?;
))
.parse(input)?;

let (input, _) = whitespace_plus_comments(input).unwrap();

Ok((input, Term::Terminal(t.to_string())))
}

///this should never fail, unwrap it when calling directly please!
pub fn whitespace_plus_comments(mut input: &str) -> IResult<&str, char, VerboseError<&str>> {
pub fn whitespace_plus_comments(mut input: &str) -> IResult<&str, char> {
let mut old_input = input;
loop {
(input, _) = multispace0(input)?;
(input, _) = multispace0::<&str, nom::error::Error<&str>>.parse(input)?;
(input, _) = opt(preceded(
complete::char(';'),
take_till(|c: char| c == '\r' || c == '\n'),
))(input)?;
))
.parse(input)?;

if input == old_input {
break;
Expand All @@ -57,73 +58,67 @@ pub fn whitespace_plus_comments(mut input: &str) -> IResult<&str, char, VerboseE

pub fn is_format_standard_bnf(input: &str) -> bool {
let (input, _) = whitespace_plus_comments(input).unwrap();
complete::char::<&str, VerboseError<&str>>('<')(input).is_ok()
complete::char::<&str, nom::error::Error<&str>>('<')
.parse(input)
.is_ok()
}

pub fn term<F: Format>(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
alt((terminal, F::nonterminal))(input)
pub fn term<F: Format>(input: &str) -> IResult<&str, Term> {
alt((terminal, F::nonterminal)).parse(input)
}

pub fn term_complete<F: Format>(input: &str) -> IResult<&str, Term, VerboseError<&str>> {
all_consuming(term::<F>)(input)
pub fn term_complete<F: Format>(input: &str) -> IResult<&str, Term> {
all_consuming(term::<F>).parse(input)
}

pub fn expression_next<F: Format>(input: &str) -> IResult<&str, &str, VerboseError<&str>> {
let (input, _) = complete::char('|')(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();

complete(expression::<F>)(input)?;

pub fn expression_next<F: Format>(input: &str) -> IResult<&str, &str> {
let (input, _) = complete::char('|').parse(input)?;
let (input, _) = whitespace_plus_comments(input)?;
complete(expression::<F>).parse(input)?;
Ok((input, ""))
}

pub fn expression<F: Format>(input: &str) -> IResult<&str, Expression, VerboseError<&str>> {
pub fn expression<F: Format>(input: &str) -> IResult<&str, Expression> {
term::<F>(input)?;

let (input, terms) = many1(complete(term::<F>))(input)?;
let (input, terms) = many1(complete(term::<F>)).parse(input)?;
let (input, _) = alt((
peek(complete(eof)),
expression_next::<F>,
recognize(peek(complete(F::prod_lhs))),
))(input)?;

))
.parse(input)?;
Ok((input, Expression::from_parts(terms)))
}

pub fn expression_complete<F: Format>(
input: &str,
) -> IResult<&str, Expression, VerboseError<&str>> {
all_consuming(expression::<F>)(input)
pub fn expression_complete<F: Format>(input: &str) -> IResult<&str, Expression> {
all_consuming(expression::<F>).parse(input)
}

pub fn production<F: Format>(input: &str) -> IResult<&str, Production, VerboseError<&str>> {
pub fn production<F: Format>(input: &str) -> IResult<&str, Production> {
let (input, lhs) = F::prod_lhs(input)?;
let (input, rhs) = many1(complete(expression::<F>))(input)?;
let (input, _) = whitespace_plus_comments(input).unwrap();
let (input, rhs) = many1(complete(expression::<F>)).parse(input)?;
let (input, _) = whitespace_plus_comments(input)?;
let (input, _) = alt((
recognize(peek(complete(eof))),
recognize(peek(complete(F::prod_lhs))),
))(input)?;

))
.parse(input)?;
Ok((input, Production::from_parts(lhs, rhs)))
}

pub fn production_complete<F: Format>(
input: &str,
) -> IResult<&str, Production, VerboseError<&str>> {
all_consuming(production::<F>)(input)
pub fn production_complete<F: Format>(input: &str) -> IResult<&str, Production> {
all_consuming(production::<F>).parse(input)
}

pub fn grammar<F: Format>(input: &str) -> IResult<&str, Grammar, VerboseError<&str>> {
let (input, _) = whitespace_plus_comments(input).unwrap();
pub fn grammar<F: Format>(input: &str) -> IResult<&str, Grammar> {
let (input, _) = whitespace_plus_comments(input)?;
production::<F>(input)?;
let (input, prods) = many1(complete(production::<F>))(input)?;

let (input, prods) = many1(complete(production::<F>)).parse(input)?;
Ok((input, Grammar::from_parts(prods)))
}

pub fn grammar_complete<F: Format>(input: &str) -> IResult<&str, Grammar, VerboseError<&str>> {
all_consuming(grammar::<F>)(input)
pub fn grammar_complete<F: Format>(input: &str) -> IResult<&str, Grammar> {
all_consuming(grammar::<F>).parse(input)
}

#[cfg(test)]
Expand Down

0 comments on commit fa571dd

Please sign in to comment.