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