use crate::syntax::{
ast::{node::ConditionalOp, Node, Punctuator},
lexer::TokenKind,
parser::{
expression::{AssignmentExpression, ShortCircuitExpression},
AllowAwait, AllowIn, AllowYield, Cursor, ParseResult, TokenParser,
},
};
use boa_interner::{Interner, Sym};
use boa_profiler::Profiler;
use std::io::Read;
#[derive(Debug, Clone, Copy)]
pub(in crate::syntax::parser::expression) struct ConditionalExpression {
name: Option<Sym>,
allow_in: AllowIn,
allow_yield: AllowYield,
allow_await: AllowAwait,
}
impl ConditionalExpression {
pub(in crate::syntax::parser::expression) fn new<N, I, Y, A>(
name: N,
allow_in: I,
allow_yield: Y,
allow_await: A,
) -> Self
where
N: Into<Option<Sym>>,
I: Into<AllowIn>,
Y: Into<AllowYield>,
A: Into<AllowAwait>,
{
Self {
name: name.into(),
allow_in: allow_in.into(),
allow_yield: allow_yield.into(),
allow_await: allow_await.into(),
}
}
}
impl<R> TokenParser<R> for ConditionalExpression
where
R: Read,
{
type Output = Node;
fn parse(self, cursor: &mut Cursor<R>, interner: &mut Interner) -> ParseResult {
let _timer = Profiler::global().start_event("ConditionalExpression", "Parsing");
let lhs = ShortCircuitExpression::new(
self.name,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
if let Some(tok) = cursor.peek(0, interner)? {
if tok.kind() == &TokenKind::Punctuator(Punctuator::Question) {
cursor.next(interner)?.expect("? character vanished"); let then_clause = AssignmentExpression::new(
None,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
cursor.expect(Punctuator::Colon, "conditional expression", interner)?;
let else_clause = AssignmentExpression::new(
None,
self.allow_in,
self.allow_yield,
self.allow_await,
)
.parse(cursor, interner)?;
return Ok(ConditionalOp::new(lhs, then_clause, else_clause).into());
}
}
Ok(lhs)
}
}