From b03cccb8dd9c72d14998f8c3cd49f43131a6ef88 Mon Sep 17 00:00:00 2001 From: Chris Mounce Date: Wed, 30 Apr 2025 00:12:04 -0700 Subject: [PATCH] Partial work toward a PEG parser library --- src/labels/labels.rs | 14 +++++++ src/labels/mod.rs | 1 + src/main.rs | 1 + src/preprocess/mod.rs | 1 + src/preprocess/peg.rs | 93 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 110 insertions(+) create mode 100644 src/labels/labels.rs create mode 100644 src/labels/mod.rs create mode 100644 src/preprocess/peg.rs diff --git a/src/labels/labels.rs b/src/labels/labels.rs new file mode 100644 index 0000000..4bc8c1d --- /dev/null +++ b/src/labels/labels.rs @@ -0,0 +1,14 @@ +use super::super::preprocess::peg::Parser; +use anyhow::Result; + +fn parse_program(p: &mut Parser) -> Result<()> { + p.star(|p| parse_line(p))?; + p.eof()?; + Ok(()) +} + +fn parse_line(p: &mut Parser) -> Result<()> { + p.star(|p| p.char(|c| c != '\n'))?; + p.literal("\n")?; + Ok(()) +} diff --git a/src/labels/mod.rs b/src/labels/mod.rs new file mode 100644 index 0000000..988d57b --- /dev/null +++ b/src/labels/mod.rs @@ -0,0 +1 @@ +pub mod labels; diff --git a/src/main.rs b/src/main.rs index b998f14..1df52a0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,4 +1,5 @@ mod encoding; +mod labels; mod preprocess; mod world; diff --git a/src/preprocess/mod.rs b/src/preprocess/mod.rs index d45ed7b..78eb8f4 100644 --- a/src/preprocess/mod.rs +++ b/src/preprocess/mod.rs @@ -1,3 +1,4 @@ pub mod eval; pub mod parse; +pub mod peg; pub mod scan; diff --git a/src/preprocess/peg.rs b/src/preprocess/peg.rs new file mode 100644 index 0000000..bb77ade --- /dev/null +++ b/src/preprocess/peg.rs @@ -0,0 +1,93 @@ +use anyhow::{Result, anyhow, bail}; + +// TODO: Add offsets +pub enum Tag { + Open(&'static str), + Close, +} +pub struct Parser { + input: String, + offset: usize, + output: Vec, +} + +#[derive(Clone, Copy)] +pub struct Savepoint { + offset: usize, + num_tags: usize, +} + +impl Parser { + pub fn new(input: &str) -> Self { + Self { + input: input.into(), + offset: 0, + output: Vec::new(), + } + } + + pub fn save(&self) -> Savepoint { + Savepoint { + offset: self.offset, + num_tags: self.output.len(), + } + } + + pub fn restore(&mut self, sp: Savepoint) { + self.offset = sp.offset; + self.output.truncate(sp.num_tags); + } + + pub fn eof(&mut self) -> Result<()> { + if self.input.len() == self.offset { + Ok(()) + } else { + bail!("No match") + } + } + + pub fn literal(&mut self, str: &str) -> Result<()> { + if self.input[self.offset..].starts_with(str) { + self.offset += str.len(); + Ok(()) + } else { + bail!("No match") + } + } + + pub fn char(&mut self, f: F) -> Result<()> + where + F: Fn(char) -> bool, + { + if let Some(c) = self.input[self.offset..].chars().next() { + if f(c) { + self.offset += c.len_utf8(); + return Ok(()); + } + } + bail!("No match") + } + + pub fn star(&mut self, mut f: F) -> Result<()> + where + F: FnMut(&mut Self) -> Result<()>, + { + let mut sp = self.save(); + while let Ok(_) = f(self) { + sp = self.save(); + } + self.restore(sp); + Ok(()) + } +} + +mod test { + use super::*; + + #[test] + fn test_hello() { + let mut p = Parser::new("foo"); + p.literal("f").unwrap(); + p.star(|p| p.literal("o")).unwrap(); + } +}