use crate::ast::BinOp;
use super::{lexer::Token, Parser, ParserError};
macro_rules! try_consume {
($self:expr, $p:pat => $e:expr) => {
match $self.peek()? {
$p => {
let _ = $self.lexer.next().unwrap();
Ok($e)
}
token => Err(ParserError::Unexpected(token)),
}
};
}
impl<'a> Parser<'a> {
pub(super) fn peek(&mut self) -> Result<Token, ParserError> {
Ok(self
.lexer
.peek()
.ok_or(ParserError::UnexpectedEOF)?
.clone()
.map_err(ParserError::LexerError)?
.item)
}
pub(super) fn try_consume_null(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Null => ())
}
pub(super) fn try_consume_not(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Not => ())
}
pub(super) fn try_consume_arrow(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Arrow => ())
}
pub(super) fn try_consume_dot(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Dot => ())
}
pub(super) fn try_consume_semi(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Semi => ())
}
pub(super) fn try_consume_open_paren(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::OpenParen => ())
}
pub(super) fn try_consume_close_paren(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::CloseParen => ())
}
pub(super) fn try_consume_eq(&mut self) -> Result<(), ParserError> {
try_consume!(self, Token::Eq => ())
}
pub(super) fn peek_symbol(&mut self) -> Result<String, ParserError> {
match self.peek()? {
Token::Symbol(s) => Ok(s),
token => Err(ParserError::Unexpected(token)),
}
}
pub(super) fn try_consume_symbol(&mut self) -> Result<String, ParserError> {
match self.peek()? {
Token::Symbol(s) => {
let _ = self.lexer.next().unwrap();
Ok(s)
}
token => Err(ParserError::Unexpected(token)),
}
}
pub(super) fn try_consume_keyword(&mut self, keyword: &str) -> Result<(), ParserError> {
match self.peek()? {
Token::Symbol(s) => {
if s == keyword {
let _ = self.lexer.next().unwrap();
Ok(())
} else {
Err(ParserError::UnexpectedKeyword(s))
}
}
token => Err(ParserError::Unexpected(token)),
}
}
pub(super) fn try_consume_binary_operator(&mut self) -> Result<BinOp, ParserError> {
match self.peek()? {
Token::Eq => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Eq)
}
Token::NEq => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::NEq)
}
Token::Gt => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Gt)
}
Token::GtEq => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::GtEq)
}
Token::Lt => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Lt)
}
Token::LtEq => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::LtEq)
}
Token::And => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::And)
}
Token::Or => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Or)
}
Token::Plus => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Add)
}
Token::Minus => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Sub)
}
Token::Star => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Mul)
}
Token::Slash => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Div)
}
Token::Mod => {
let _ = self.lexer.next().unwrap();
Ok(BinOp::Mod)
}
token => Err(ParserError::Unexpected(token)),
}
}
}