Skip to content

Commit

Permalink
Use nom-span for input types
Browse files Browse the repository at this point in the history
(Thank you, @JulesGuesnon!)
  • Loading branch information
scouten committed Dec 16, 2023
1 parent fe610c1 commit 9ef292b
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 0 deletions.
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,5 @@ rust-version = "1.72.0"

[dependencies]
nom = "7.1"
nom-span = "0.1.1"
thiserror = "1.0.50"
14 changes: 14 additions & 0 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use nom::{
error::{ErrorKind, FromExternalError, ParseError},
IResult,
};
use nom_span::Spanned;

// use crate::input::Input;

/// The error type for AsciiDoc parsing operations.
#[non_exhaustive]
Expand All @@ -17,6 +20,7 @@ pub enum Error {
}

impl<'a> ParseError<&'a str> for Error {
// TEMPORARY
fn from_error_kind(_input: &'a str, kind: ErrorKind) -> Self {
Error::NomError(kind)
}
Expand All @@ -26,6 +30,16 @@ impl<'a> ParseError<&'a str> for Error {
}
}

impl<'a> ParseError<Spanned<&'a str>> for Error {
fn from_error_kind(_input: Spanned<&'a str>, kind: ErrorKind) -> Self {
Error::NomError(kind)
}

fn append(_input: Spanned<&'a str>, kind: ErrorKind, _other: Self) -> Self {
Error::NomError(kind)
}
}

impl From<nom::Err<Error>> for Error {
fn from(e: nom::Err<Error>) -> Self {
match e {
Expand Down
73 changes: 73 additions & 0 deletions src/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
//! Data types that describe the location of a syntactic element.

use std::fmt::Display;

use nom_span::Spanned;

pub(crate) type Input<'a> = Spanned<&'a str>;

/// Location within an input stream.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Location {
line: usize,
col: usize,
}

impl Location {
/// Return the line number (1-based).
pub fn line(&self) -> usize {
self.line
}

/// Return the column number (1-based).
pub fn col(&self) -> usize {
self.col
}
}

impl<'a> From<&Input<'a>> for Location {
fn from(i: &Input<'a>) -> Self {
Self {
line: i.line(),
col: i.col(),
}
}
}

impl Display for Location {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{line}:{col}", line = self.line, col = self.col)
}
}

/// Span (start and end location) within an input stream.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub struct Span {
start: Location,
after_end: Location,
}

impl Span {
#[allow(dead_code)] // TEMPORARY
pub(crate) fn from_start_and_after_end(start: &'_ Input<'_>, after_end: &'_ Input<'_>) -> Self {
Self {
start: start.into(),
after_end: after_end.into(),
}
}

/// Returns the starting location of this span.
pub fn start(&self) -> Location {
self.start
}

/// Returns the location immediately after the end of this span.
pub fn after_end(&self) -> Location {
self.after_end
}

/// Returns true if the `start` and `after_end` locations are the same.
pub fn is_empty(&self) -> bool {
self.start == self.after_end
}
}
2 changes: 2 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ pub mod blocks;
mod error;
pub use error::{Error, ParseResult};

pub mod input;

pub(crate) mod primitives;
pub mod strings;

Expand Down
53 changes: 53 additions & 0 deletions src/tests/input.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
mod location {
use nom::character::complete::alpha1;

use crate::input::{Input, Location};

#[test]
fn empty_str() {
let i = Input::new("", true);
let l: Location = (&i).into();
assert_eq!(l.line(), 1);
assert_eq!(l.col(), 1);
}

#[test]
fn take3() {
let i1 = Input::new("abc456", true);
let (i2, _) = alpha1::<Input, crate::Error>(i1).unwrap();
let l2: Location = (&i2).into();
assert_eq!(l2.line(), 1);
assert_eq!(l2.col(), 4);
}
}

mod span {
use nom::character::complete::alpha1;

use crate::input::{Input, Span};

#[test]
fn empty_str() {
let i = Input::new("", true);
let s = Span::from_start_and_after_end(&i, &i);

assert_eq!(s.start().line(), 1);
assert_eq!(s.start().col(), 1);
assert_eq!(s.after_end().line(), 1);
assert_eq!(s.after_end().col(), 1);
assert!(s.is_empty());
}

#[test]
fn take3() {
let i1 = Input::new("abc456", true);
let (i2, _) = alpha1::<Input, crate::Error>(i1).unwrap();
let s = Span::from_start_and_after_end(&i1, &i2);

assert_eq!(s.start().line(), 1);
assert_eq!(s.start().col(), 1);
assert_eq!(s.after_end().line(), 1);
assert_eq!(s.after_end().col(), 4);
assert!(!s.is_empty());
}
}
1 change: 1 addition & 0 deletions src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@

mod blocks;
mod fixtures;
mod input;
mod primitives;
mod strings;

0 comments on commit 9ef292b

Please sign in to comment.