use lexer::{Input, Lexer};
use swc_common::{BytePos, Span, DUMMY_SP};
use token::*;
use Context;
pub(super) struct ParserInput<'a, I: Input> {
iter: Lexer<'a, I>,
prev_span: Span,
cur: Option<TokenAndSpan>,
next: Option<TokenAndSpan>,
}
impl<'a, I: Input> ParserInput<'a, I> {
pub fn new(lexer: Lexer<'a, I>) -> Self {
ParserInput {
iter: lexer,
cur: None,
prev_span: DUMMY_SP,
next: None,
}
}
fn bump_inner(&mut self) -> Option<Token> {
let prev = self.cur.take();
self.prev_span = match prev {
Some(TokenAndSpan { span, .. }) => span,
_ => self.prev_span,
};
self.cur = self.next.take().or_else(|| self.iter.next());
prev.map(|it| it.token)
}
pub fn cur_debug(&self) -> Option<&Token> {
self.cur.as_ref().map(|it| &it.token)
}
pub fn bump(&mut self) -> Token {
let prev = match self.cur.take() {
Some(t) => t,
None => unreachable!(
"Current token is `None`. Parser should not call bump()without knowing current \
token"
),
};
self.prev_span = prev.span;
prev.token
}
pub fn knows_cur(&self) -> bool {
self.cur.is_some()
}
pub fn peek(&mut self) -> Option<&Token> {
assert!(
self.cur.is_some(),
"parser should not call peek() without knowing current token"
);
if self.next.is_none() {
self.next = self.iter.next();
}
self.next.as_ref().map(|ts| &ts.token)
}
pub fn had_line_break_before_cur(&mut self) -> bool {
self.cur();
self.cur
.as_ref()
.map(|it| it.had_line_break)
.unwrap_or_else(|| true)
}
pub fn has_linebreak_between_cur_and_peeked(&mut self) -> bool {
let _ = self.peek();
self.next
.as_ref()
.map(|item| item.had_line_break)
.unwrap_or({
true
})
}
pub fn cur(&mut self) -> Option<&Token> {
if self.cur.is_none() {
self.bump_inner();
}
self.cur.as_ref().map(|item| &item.token)
}
pub fn is(&mut self, expected: &Token) -> bool {
match self.cur() {
Some(t) => *expected == *t,
_ => false,
}
}
pub fn peeked_is(&mut self, expected: &Token) -> bool {
match self.peek() {
Some(t) => *expected == *t,
_ => false,
}
}
pub fn eat(&mut self, expected: &Token) -> bool {
let v = self.is(expected);
if v {
self.bump();
}
v
}
pub fn eat_keyword(&mut self, kwd: Keyword) -> bool {
self.eat(&Word(Keyword(kwd)))
}
pub fn cur_pos(&mut self) -> BytePos {
let _ = self.cur();
self.cur
.as_ref()
.map(|item| item.span.lo())
.unwrap_or_else(|| {
self.last_pos()
})
}
pub fn cur_span(&self) -> Span {
self.cur
.as_ref()
.map(|item| item.span)
.unwrap_or(self.prev_span)
}
pub fn last_pos(&self) -> BytePos {
self.prev_span.hi()
}
pub const fn prev_span(&self) -> Span {
self.prev_span
}
pub const fn get_ctx(&self) -> Context {
self.iter.ctx
}
pub fn set_ctx(&mut self, ctx: Context) {
self.iter.ctx = ctx;
}
}