parser works

This commit is contained in:
nora 2022-04-12 19:32:48 +02:00
parent 2b1daa55fb
commit 2484fe1f44
7 changed files with 402 additions and 0 deletions

8
rust2/src/main.rs Normal file
View file

@ -0,0 +1,8 @@
#![feature(allocator_api)]
#![warn(rust_2018_idioms)]
mod parse;
fn main() {
println!("Hello, world!");
}

104
rust2/src/parse.rs Normal file
View file

@ -0,0 +1,104 @@
use bumpalo::Bump;
type Instrs<'ast> = Vec<Instr<'ast>, &'ast Bump>;
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum Instr<'ast> {
Add,
Sub,
Right,
Left,
Out,
In,
Loop(Instrs<'ast>),
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct ParseError;
pub fn parse<I>(alloc: &Bump, mut src: I) -> Result<Instrs<'_>, ParseError>
where
I: Iterator<Item = u8>,
{
let mut instrs = Vec::new_in(alloc);
loop {
match src.next() {
Some(b'+') => instrs.push(Instr::Add),
Some(b'-') => instrs.push(Instr::Sub),
Some(b'>') => instrs.push(Instr::Right),
Some(b'<') => instrs.push(Instr::Left),
Some(b'.') => instrs.push(Instr::Out),
Some(b',') => instrs.push(Instr::In),
Some(b'[') => {
let loop_instrs = parse_loop(alloc, &mut src, 0)?;
instrs.push(Instr::Loop(loop_instrs));
}
Some(b']') => return Err(ParseError),
Some(_) => {} // comment
None => break,
}
}
Ok(instrs)
}
pub fn parse_loop<'ast, I>(
alloc: &'ast Bump,
src: &mut I,
depth: u16,
) -> Result<Instrs<'ast>, ParseError>
where
I: Iterator<Item = u8>,
{
const MAX_DEPTH: u16 = 1000;
if depth > MAX_DEPTH {
return Err(ParseError);
}
let mut instrs = Vec::new_in(alloc);
loop {
match src.next() {
Some(b'+') => instrs.push(Instr::Add),
Some(b'-') => instrs.push(Instr::Sub),
Some(b'>') => instrs.push(Instr::Right),
Some(b'<') => instrs.push(Instr::Left),
Some(b'.') => instrs.push(Instr::Out),
Some(b',') => instrs.push(Instr::In),
Some(b'[') => {
let loop_instrs = parse_loop(alloc, src, depth + 1)?;
instrs.push(Instr::Loop(loop_instrs));
}
Some(b']') => break,
Some(_) => {} // comment
None => return Err(ParseError),
}
}
Ok(instrs)
}
#[cfg(test)]
mod tests {
use bumpalo::Bump;
#[test]
fn simple() {
let alloc = Bump::new();
let bf = ">+<++[-].";
let instrs = super::parse(&alloc, bf.bytes());
insta::assert_debug_snapshot!(instrs);
}
#[test]
fn nested_loop() {
let alloc = Bump::new();
let bf = "+[-[-[-]]+>>>]";
let instrs = super::parse(&alloc, bf.bytes());
insta::assert_debug_snapshot!(instrs);
}
}

View file

@ -0,0 +1,29 @@
---
source: src/parse.rs
assertion_line: 102
expression: instrs
---
Ok(
[
Add,
Loop(
[
Sub,
Loop(
[
Sub,
Loop(
[
Sub,
],
),
],
),
Add,
Right,
Right,
Right,
],
),
],
)

View file

@ -0,0 +1,20 @@
---
source: src/parse.rs
assertion_line: 93
expression: instrs
---
Ok(
[
Right,
Add,
Left,
Add,
Add,
Loop(
[
Sub,
],
),
Out,
],
)