Skip to content

Commit

Permalink
js: Parse equality expressions
Browse files Browse the repository at this point in the history
  • Loading branch information
simonwuelker committed Jan 19, 2024
1 parent 6f6f5fc commit 19bc630
Show file tree
Hide file tree
Showing 2 changed files with 59 additions and 5 deletions.
56 changes: 55 additions & 1 deletion crates/js/src/parser/expression.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub enum BinaryOp {
Arithmetic(ArithmeticOp),
Logical(LogicalOp),
Bitwise(BitwiseOp),
Equality(EqualityOp),
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
Expand All @@ -45,6 +46,14 @@ pub enum BitwiseOp {
Xor,
}

#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum EqualityOp {
Equal,
NotEqual,
StrictEqual,
StrictNotEqual,
}

macro_rules! binary_op {
($docs: expr, $name: ident, $next: path, $op: path, $symbol: pat) => {
#[doc = $docs]
Expand Down Expand Up @@ -113,11 +122,49 @@ binary_op!(
binary_op!(
"<https://262.ecma-international.org/14.0/#prod-BitwiseANDExpression>",
parse_bitwise_and_expression,
NewExpression::parse::<IN, YIELD, AWAIT>,
parse_equality_expression::<IN, YIELD, AWAIT>,
BitwiseOp::And,
Punctuator::Ampersand
);

/// <https://262.ecma-international.org/14.0/#prod-EqualityExpression>
fn parse_equality_expression<const IN: bool, const YIELD: bool, const AWAIT: bool>(
tokenizer: &mut Tokenizer<'_>,
) -> Result<Expression, SyntaxError> {
let mut expression = parse_relational_expression::<IN, YIELD, AWAIT>(tokenizer)?;

let parse_or_term = |tokenizer: &mut Tokenizer<'_>| {
let operator = match tokenizer.attempt(Tokenizer::consume_punctuator)? {
Punctuator::DoubleEqual => EqualityOp::Equal,
Punctuator::TripleEqual => EqualityOp::StrictEqual,
Punctuator::ExclamationMarkEqual => EqualityOp::NotEqual,
Punctuator::ExclamationMarkDoubleEqual => EqualityOp::StrictEqual,
_ => return Err(tokenizer.syntax_error()),
};

let rhs = tokenizer.attempt(parse_relational_expression::<IN, YIELD, AWAIT>)?;

Ok((operator, rhs))
};

while let Ok((operator, next_term)) = tokenizer.attempt(parse_or_term) {
expression = BinaryExpression {
op: operator.into(),
lhs: Box::new(expression),
rhs: Box::new(next_term.into()),
}
.into();
}

Ok(expression)
}

fn parse_relational_expression<const IN: bool, const YIELD: bool, const AWAIT: bool>(
tokenizer: &mut Tokenizer<'_>,
) -> Result<Expression, SyntaxError> {
parse_primary_expression::<IN, YIELD, AWAIT>(tokenizer)
}

/// <https://262.ecma-international.org/14.0/#prod-LeftHandSideExpression>
#[derive(Clone, Debug)]
pub enum LeftHandSideExpression {
Expand Down Expand Up @@ -206,6 +253,7 @@ impl CompileToBytecode for Expression {
BinaryOp::Bitwise(BitwiseOp::Xor) => builder.bitwise_xor(lhs, rhs),
BinaryOp::Logical(LogicalOp::And) => builder.logical_and(lhs, rhs),
BinaryOp::Logical(LogicalOp::Or) => builder.logical_or(lhs, rhs),
BinaryOp::Equality(_) => todo!(),
};

dst
Expand Down Expand Up @@ -252,3 +300,9 @@ impl From<BitwiseOp> for BinaryOp {
Self::Bitwise(value)
}
}

impl From<EqualityOp> for BinaryOp {
fn from(value: EqualityOp) -> Self {
Self::Equality(value)
}
}
8 changes: 4 additions & 4 deletions crates/js/src/parser/tokenizer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,9 @@ pub enum Punctuator {
LessThanEqual,
GreaterThanEqual,
DoubleEqual,
NotEqual,
ExclamationMarkEqual,
TripleEqual,
NotDoubleEqual,
ExclamationMarkDoubleEqual,
Plus,
Minus,
Asterisk,
Expand Down Expand Up @@ -360,9 +360,9 @@ impl<'a> Tokenizer<'a> {
self.source.next();
if self.source.current() == Some('=') {
self.source.next();
Punctuator::NotDoubleEqual
Punctuator::ExclamationMarkDoubleEqual
} else {
Punctuator::NotEqual
Punctuator::ExclamationMarkEqual
}
} else {
Punctuator::ExclamationMark
Expand Down

0 comments on commit 19bc630

Please sign in to comment.