|
- 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)
- }
- }
- }
|