Browse Source

Initial commit

master
Colin Reeder 3 years ago
commit
f98ac6b5f3
4 changed files with 93 additions and 0 deletions
  1. +3
    -0
      .gitignore
  2. +7
    -0
      Cargo.toml
  3. +11
    -0
      src/lib.rs
  4. +72
    -0
      src/parse.rs

+ 3
- 0
.gitignore View File

@@ -0,0 +1,3 @@
/target
**/*.rs.bk
Cargo.lock

+ 7
- 0
Cargo.toml View File

@@ -0,0 +1,7 @@
[package]
name = "four"
version = "0.1.0"
authors = ["Colin Reeder <vpzomtrrfrt@gmail.com>"]

[dependencies]
vec1 = "1.1.0"

+ 11
- 0
src/lib.rs View File

@@ -0,0 +1,11 @@
#[macro_use]
extern crate vec1;

pub mod parse;

pub enum Expr {
Four,
Call(vec1::Vec1<Expr>)
}

pub use parse::{parse, ParseError};

+ 72
- 0
src/parse.rs View File

@@ -0,0 +1,72 @@
use std;

use {Expr};

pub enum ParseError {
TrailingCharacters,
UnexpectedEof,
EmptyBlock,
IOError(std::io::Error)
}

impl From<std::io::Error> for ParseError {
fn from(err: std::io::Error) -> ParseError {
ParseError::IOError(err)
}
}

pub fn parse(mut src: impl std::io::Read) -> Result<Expr, ParseError> {
let mut buf = [0];
let next = parse_next(&mut src, &mut buf)?;
let ret = src.read(&mut buf)?;
if ret > 0 {
Err(ParseError::TrailingCharacters)
}
else {
match next {
Next::EndFile => Err(ParseError::UnexpectedEof),
Next::EndParen => Err(ParseError::TrailingCharacters),
Next::Expr(expr) => Ok(expr)
}
}
}

enum Next {
Expr(Expr),
EndParen,
EndFile
}

fn parse_next(mut src: impl std::io::Read, buf: &mut [u8; 1]) -> Result<Next, ParseError> {
loop {
let ret = src.read(buf)?;
if ret < 1 {
return Ok(Next::EndFile);
}
if buf[0] == b'4' {
return Ok(Next::Expr(Expr::Four));
}
if buf[0] == b')' {
return Ok(Next::EndParen);
}
if buf[0] == b'(' {
return Ok(Next::Expr(parse_call(src, buf)?));
}
}
}

fn parse_call(mut src: impl std::io::Read, buf: &mut [u8; 1]) -> Result<Expr, ParseError> {
let mut args = match parse_next(&mut src, buf)? {
Next::EndFile => return Err(ParseError::UnexpectedEof),
Next::EndParen => return Err(ParseError::EmptyBlock),
Next::Expr(expr) => vec1![expr]
};

loop {
match parse_next(&mut src, buf)? {
Next::EndFile => return Err(ParseError::UnexpectedEof),
Next::EndParen => return Ok(Expr::Call(args)),
Next::Expr(expr) => args.push(expr)
}
}
}

Loading…
Cancel
Save