From f98ac6b5f34983ee3afb4722c974844333049853 Mon Sep 17 00:00:00 2001 From: Colin Reeder Date: Sun, 9 Sep 2018 08:15:46 -0600 Subject: [PATCH] Initial commit --- .gitignore | 3 +++ Cargo.toml | 7 +++++ src/lib.rs | 11 ++++++++ src/parse.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/lib.rs create mode 100644 src/parse.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..6936990 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/target +**/*.rs.bk +Cargo.lock diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..752bc17 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "four" +version = "0.1.0" +authors = ["Colin Reeder "] + +[dependencies] +vec1 = "1.1.0" diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..4ca7447 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,11 @@ +#[macro_use] +extern crate vec1; + +pub mod parse; + +pub enum Expr { + Four, + Call(vec1::Vec1) +} + +pub use parse::{parse, ParseError}; diff --git a/src/parse.rs b/src/parse.rs new file mode 100644 index 0000000..773e976 --- /dev/null +++ b/src/parse.rs @@ -0,0 +1,72 @@ +use std; + +use {Expr}; + +pub enum ParseError { + TrailingCharacters, + UnexpectedEof, + EmptyBlock, + IOError(std::io::Error) +} + +impl From for ParseError { + fn from(err: std::io::Error) -> ParseError { + ParseError::IOError(err) + } +} + +pub fn parse(mut src: impl std::io::Read) -> Result { + 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 { + 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 { + 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) + } + } +}