Skip to content

Commit

Permalink
Parser (#2353)
Browse files Browse the repository at this point in the history
Created a parser to process the path we've described such as: ".-0-1-b"
  • Loading branch information
eliascxstro authored Nov 29, 2024
1 parent cc24c34 commit 154da35
Show file tree
Hide file tree
Showing 4 changed files with 161 additions and 0 deletions.
31 changes: 31 additions & 0 deletions interp/src/debugger/commands/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,37 @@ impl From<(Vec<Path>, Option<PrintCode>, PrintMode)> for PrintTuple {
}
}

/// ParseNodes enum is used to represent what child to traverse with respect to
/// the current ControlIdx.
/// Body defines that we should go into the body of a while or repeat.
/// Offset defines which child to go to.
/// If defines whether we should go to the true or false branch next
#[derive(Debug, PartialEq, Clone)]
pub enum ParseNodes {
Body,
Offset(u32),
If(bool),
}
pub struct ParsePath {
nodes: Vec<ParseNodes>,
}

impl ParsePath {
pub fn new(nodes: Vec<ParseNodes>) -> ParsePath {
ParsePath { nodes }
}

pub fn get_path(&self) -> Vec<ParseNodes> {
self.nodes.clone()
}
}

impl FromIterator<ParseNodes> for ParsePath {
fn from_iter<I: IntoIterator<Item = ParseNodes>>(iter: I) -> Self {
ParsePath::new(iter.into_iter().collect())
}
}

// Different types of printing commands
pub enum PrintCommand {
Normal,
Expand Down
1 change: 1 addition & 0 deletions interp/src/debugger/commands/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! This module contains the structures for the debugger commands
pub(crate) mod command_parser;
pub mod core;
mod path_parser;
pub use command_parser::parse_command;
pub use core::Command;

Expand Down
13 changes: 13 additions & 0 deletions interp/src/debugger/commands/path_parser.pest
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
root = { "." }

separator = { "-" }

body = { "b" }

num = { ASCII_DIGIT+ }

branch = {"t" | "f"}

clause = { separator ~ (body | num | branch) }

path = { SOI ~ root ~ clause* ~ EOI }
116 changes: 116 additions & 0 deletions interp/src/debugger/commands/path_parser.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
use super::{core::ParseNodes, ParsePath};

use pest_consume::{match_nodes, Error, Parser};

type ParseResult<T> = std::result::Result<T, Error<Rule>>;
type Node<'i> = pest_consume::Node<'i, Rule, ()>;

// include the grammar file so that Cargo knows to rebuild this file on grammar changes
const _GRAMMAR: &str = include_str!("path_parser.pest");

#[derive(Parser)]
#[grammar = "debugger/commands/path_parser.pest"]

pub struct PathParser;

#[pest_consume::parser]
impl PathParser {
fn EOI(_input: Node) -> ParseResult<()> {
Ok(())
}

fn root(_input: Node) -> ParseResult<()> {
Ok(())
}

fn body(_input: Node) -> ParseResult<()> {
Ok(())
}

fn separator(_input: Node) -> ParseResult<()> {
Ok(())
}

fn num(input: Node) -> ParseResult<u32> {
input
.as_str()
.parse::<u32>()
.map_err(|_| input.error("Expected non-negative number"))
}

fn branch(input: Node) -> ParseResult<bool> {
let b = input.as_str();
let result = b != "f";
Ok(result)
}

fn clause(input: Node) -> ParseResult<ParseNodes> {
Ok(match_nodes!(input.into_children();
[separator(_), num(n)] => ParseNodes::Offset(n),
[separator(_), body(_)] => ParseNodes::Body,
[separator(_), branch(b)] => ParseNodes::If(b)
))
}

fn path(input: Node) -> ParseResult<ParsePath> {
Ok(match_nodes!(input.into_children();
[root(_), clause(c).., EOI(_)] => ParsePath::from_iter(c),
))
}
}

// Parse the path
#[allow(dead_code)]
pub fn parse_path(input_str: &str) -> Result<ParsePath, Box<Error<Rule>>> {
let entries = PathParser::parse(Rule::path, input_str)?;
let entry = entries.single()?;

PathParser::path(entry).map_err(Box::new)
}

#[cfg(test)]
#[test]
fn root() {
let path = parse_path(".").unwrap();
dbg!(path.get_path());
assert_eq!(path.get_path(), Vec::new())
}

#[test]
fn body() {
let path = parse_path(".-b").unwrap();
dbg!(path.get_path());
assert_eq!(path.get_path(), vec![ParseNodes::Body])
}

#[test]
fn branch() {
let path = parse_path(".-f").unwrap();
dbg!(path.get_path());
assert_eq!(path.get_path(), vec![ParseNodes::If(false)])
}

#[test]
fn offset() {
let path = parse_path(".-0-1").unwrap();
dbg!(path.get_path());
assert_eq!(
path.get_path(),
vec![ParseNodes::Offset(0), ParseNodes::Offset(1)]
)
}

#[test]
fn multiple() {
let path = parse_path(".-0-1-b-t").unwrap();
dbg!(path.get_path());
assert_eq!(
path.get_path(),
vec![
ParseNodes::Offset(0),
ParseNodes::Offset(1),
ParseNodes::Body,
ParseNodes::If(true)
]
)
}

0 comments on commit 154da35

Please sign in to comment.