Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
64 changes: 61 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ maintenance = { status = "actively-developed" }
[features]
default = ["alloc", "serde"]
## Enables the `alloc` crate, enabling [`parse`] and the heap-allocated AST ([`Program`], [`Diagnostics`], etc.).
alloc = []
alloc = ["defmt?/alloc"]
## Enables serialisation and deserialisation of core and AST types via `serde`.
serde = ["dep:serde"]
## Enables defmt format implementations.
defmt = ["dep:defmt"]

#! ### Internal Features
#! The following features are not intended for public use.
Expand All @@ -33,6 +35,7 @@ unstable-doc-cfg = []

[dependencies]
cfg-if = "1.0.4"
defmt = { version = "1.1", optional = true }
doc-cfg = "0.1.0"
document-features = "0.2"
libm = "0.2"
Expand Down
31 changes: 31 additions & 0 deletions src/core/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,13 @@ impl Display for TokenType {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for TokenType {
fn format(&self, fmt: defmt::Formatter<'_>) {
defmt::write!(fmt, "{}", self.as_str())
}
}

/// Return type for visitor methods that may either continue with a child visitor
/// or pause parsing. See the [module-level docs](crate::core) for the control-flow model.
pub type ControlFlow<T> = core::ops::ControlFlow<(), T>;
Expand All @@ -74,6 +81,7 @@ pub type ControlFlow<T> = core::ops::ControlFlow<(), T>;
/// refer into the same `&str` passed to [`parse`](crate::core::parse) or
/// [`resume`](crate::core::resume).
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
#[repr(C)]
pub struct Span {
Expand Down Expand Up @@ -178,6 +186,18 @@ impl Debug for Number {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for Number {
fn format(&self, fmt: defmt::Formatter<'_>) {
let major = self.major();
defmt::write!(fmt, "{}", major);

if let Some(minor) = self.minor() {
defmt::write!(fmt, ".{}", minor);
}
}
}

/// An error returned when parsing a number.
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum ParseNumberError {
Expand Down Expand Up @@ -374,6 +394,16 @@ impl Display for Value<'_> {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for Value<'_> {
fn format(&self, fmt: defmt::Formatter<'_>) {
match self {
Value::Literal(n) => defmt::write!(fmt, "{}", n),
Value::Variable(s) => defmt::write!(fmt, "#{}", s),
}
}
}

/// A no-op visitor that ignores all callbacks.
///
/// Use when you only need to drive the parser (e.g. to validate syntax or
Expand All @@ -388,6 +418,7 @@ impl Display for Value<'_> {
/// parse(src, &mut Noop);
/// ```
#[derive(Debug, Default, Copy, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Noop;

impl ProgramVisitor for Noop {
Expand Down
38 changes: 38 additions & 0 deletions src/diags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,19 @@ impl Display for Diagnostic {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for Diagnostic {
fn format(&self, fmt: defmt::Formatter<'_>) {
let Diagnostic {
kind,
span: Span { line, .. },
} = self;
let line = line + 1;

defmt::write!(fmt, "{} on line {}", kind, line)
}
}

/// Category of parse diagnostic emitted during recovery.
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
Expand Down Expand Up @@ -61,10 +74,35 @@ impl Display for DiagnosticKind {
}
}

#[cfg(feature = "defmt")]
impl defmt::Format for DiagnosticKind {
fn format(&self, fmt: defmt::Formatter<'_>) {
match self {
DiagnosticKind::UnknownContent { text } => {
defmt::write!(fmt, "Unknown content: {}", text)
},
DiagnosticKind::Unexpected { actual, expected } => {
let expected = expected
.iter()
.map(|s| s.as_str())
.collect::<Vec<_>>()
.join(", ");
defmt::write!(
fmt,
"Unexpected: {} (expected: {})",
actual,
expected
)
},
}
}
}

/// Collection of [`Diagnostic`]s produced by a parse.
///
/// Returned by [`parse`](crate::parse) in `Err` when any diagnostic was emitted.
#[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Diagnostics(Vec<Diagnostic>);

impl Diagnostics {
Expand Down
Loading
Loading