-
-
Notifications
You must be signed in to change notification settings - Fork 401
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
3 changed files
with
252 additions
and
0 deletions.
There are no files selected for viewing
79 changes: 79 additions & 0 deletions
79
boa/src/syntax/parser/expression/assignment/conditional.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! Conditional operator parsing. | ||
//! | ||
//! More information: | ||
//! - [MDN documentation][mdn] | ||
//! - [ECMAScript specification][spec] | ||
//! | ||
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator | ||
//! [spec]: https://tc39.es/ecma262/#sec-conditional-operator | ||
|
||
use crate::syntax::{ | ||
ast::{node::Node, punc::Punctuator, token::TokenKind}, | ||
parser::{ | ||
expression::{AssignmentExpression, LogicalORExpression}, | ||
AllowAwait, AllowIn, AllowYield, Cursor, ParseResult, TokenParser, | ||
}, | ||
}; | ||
|
||
/// Conditional expression parsing. | ||
/// | ||
/// More information: | ||
/// - [MDN documentation][mdn] | ||
/// - [ECMAScript specification][spec] | ||
/// | ||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Conditional_Operator | ||
/// [spec]: https://tc39.es/ecma262/#prod-ConditionalExpression | ||
#[derive(Debug, Clone, Copy)] | ||
pub(in crate::syntax::parser::expression) struct ConditionalExpression { | ||
allow_in: AllowIn, | ||
allow_yield: AllowYield, | ||
allow_await: AllowAwait, | ||
} | ||
|
||
impl ConditionalExpression { | ||
/// Creates a new `ConditionalExpression` parser. | ||
pub(in crate::syntax::parser::expression) fn new<I, Y, A>( | ||
allow_in: I, | ||
allow_yield: Y, | ||
allow_await: A, | ||
) -> Self | ||
where | ||
I: Into<AllowIn>, | ||
Y: Into<AllowYield>, | ||
A: Into<AllowAwait>, | ||
{ | ||
Self { | ||
allow_in: allow_in.into(), | ||
allow_yield: allow_yield.into(), | ||
allow_await: allow_await.into(), | ||
} | ||
} | ||
} | ||
|
||
impl TokenParser for ConditionalExpression { | ||
type Output = Node; | ||
|
||
fn parse(self, cursor: &mut Cursor<'_>) -> ParseResult { | ||
// TODO: coalesce expression | ||
let lhs = LogicalORExpression::new(self.allow_in, self.allow_yield, self.allow_await) | ||
.parse(cursor)?; | ||
|
||
if let Some(tok) = cursor.next() { | ||
if tok.kind == TokenKind::Punctuator(Punctuator::Question) { | ||
let then_clause = | ||
AssignmentExpression::new(self.allow_in, self.allow_yield, self.allow_await) | ||
.parse(cursor)?; | ||
cursor.expect(Punctuator::Colon, "conditional expression")?; | ||
|
||
let else_clause = | ||
AssignmentExpression::new(self.allow_in, self.allow_yield, self.allow_await) | ||
.parse(cursor)?; | ||
return Ok(Node::conditional_op(lhs, then_clause, else_clause)); | ||
} else { | ||
cursor.back(); | ||
} | ||
} | ||
|
||
Ok(lhs) | ||
} | ||
} |
94 changes: 94 additions & 0 deletions
94
boa/src/syntax/parser/expression/assignment/exponentiation.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
//! Exponentiation operator parsing. | ||
//! | ||
//! More information: | ||
//! - [MDN documentation][mdn] | ||
//! - [ECMAScript specification][spec] | ||
//! | ||
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation | ||
//! [spec]: https://tc39.es/ecma262/#sec-exp-operator | ||
|
||
use crate::syntax::{ | ||
ast::{ | ||
keyword::Keyword, | ||
node::Node, | ||
op::{BinOp, NumOp}, | ||
punc::Punctuator, | ||
token::TokenKind, | ||
}, | ||
parser::{ | ||
expression::{unary::UnaryExpression, update::UpdateExpression}, | ||
AllowAwait, AllowYield, Cursor, ParseResult, TokenParser, | ||
}, | ||
}; | ||
|
||
/// Parses an exponentiation expression. | ||
/// | ||
/// More information: | ||
/// - [MDN documentation][mdn] | ||
/// - [ECMAScript specification][spec] | ||
/// | ||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Arithmetic_Operators#Exponentiation | ||
/// [spec]: https://tc39.es/ecma262/#prod-ExponentiationExpression | ||
#[derive(Debug, Clone, Copy)] | ||
pub(in crate::syntax::parser::expression) struct ExponentiationExpression { | ||
allow_yield: AllowYield, | ||
allow_await: AllowAwait, | ||
} | ||
|
||
impl ExponentiationExpression { | ||
/// Creates a new `ExponentiationExpression` parser. | ||
pub(in crate::syntax::parser::expression) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self | ||
where | ||
Y: Into<AllowYield>, | ||
A: Into<AllowAwait>, | ||
{ | ||
Self { | ||
allow_yield: allow_yield.into(), | ||
allow_await: allow_await.into(), | ||
} | ||
} | ||
} | ||
|
||
impl ExponentiationExpression { | ||
/// Checks by looking at the next token to see whether it's a unary operator or not. | ||
fn is_unary_expression(cursor: &mut Cursor<'_>) -> bool { | ||
if let Some(tok) = cursor.peek(0) { | ||
match tok.kind { | ||
TokenKind::Keyword(Keyword::Delete) | ||
| TokenKind::Keyword(Keyword::Void) | ||
| TokenKind::Keyword(Keyword::TypeOf) | ||
| TokenKind::Punctuator(Punctuator::Add) | ||
| TokenKind::Punctuator(Punctuator::Sub) | ||
| TokenKind::Punctuator(Punctuator::Not) | ||
| TokenKind::Punctuator(Punctuator::Neg) => true, | ||
_ => false, | ||
} | ||
} else { | ||
false | ||
} | ||
} | ||
} | ||
|
||
impl TokenParser for ExponentiationExpression { | ||
type Output = Node; | ||
|
||
fn parse(self, cursor: &mut Cursor<'_>) -> ParseResult { | ||
if Self::is_unary_expression(cursor) { | ||
return UnaryExpression::new(self.allow_yield, self.allow_await).parse(cursor); | ||
} | ||
|
||
let lhs = UpdateExpression::new(self.allow_yield, self.allow_await).parse(cursor)?; | ||
if let Some(tok) = cursor.next() { | ||
if let TokenKind::Punctuator(Punctuator::Exp) = tok.kind { | ||
return Ok(Node::bin_op( | ||
BinOp::Num(NumOp::Exp), | ||
lhs, | ||
self.parse(cursor)?, | ||
)); | ||
} else { | ||
cursor.back(); | ||
} | ||
} | ||
Ok(lhs) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,79 @@ | ||
//! Unary operator parsing. | ||
//! | ||
//! More information: | ||
//! - [MDN documentation][mdn] | ||
//! - [ECMAScript specification][spec] | ||
//! | ||
//! [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Unary | ||
//! [spec]: https://tc39.es/ecma262/#sec-unary-operators | ||
|
||
use crate::syntax::{ | ||
ast::{keyword::Keyword, node::Node, op::UnaryOp, punc::Punctuator, token::TokenKind}, | ||
parser::{ | ||
expression::update::UpdateExpression, AllowAwait, AllowYield, Cursor, ParseError, | ||
ParseResult, TokenParser, | ||
}, | ||
}; | ||
|
||
/// Parses a unary expression. | ||
/// | ||
/// More information: | ||
/// - [MDN documentation][mdn] | ||
/// - [ECMAScript specification][spec] | ||
/// | ||
/// [mdn]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Expressions_and_Operators#Unary | ||
/// [spec]: https://tc39.es/ecma262/#prod-UnaryExpression | ||
#[derive(Debug, Clone, Copy)] | ||
pub(super) struct UnaryExpression { | ||
allow_yield: AllowYield, | ||
allow_await: AllowAwait, | ||
} | ||
|
||
impl UnaryExpression { | ||
/// Creates a new `UnaryExpression` parser. | ||
pub(super) fn new<Y, A>(allow_yield: Y, allow_await: A) -> Self | ||
where | ||
Y: Into<AllowYield>, | ||
A: Into<AllowAwait>, | ||
{ | ||
Self { | ||
allow_yield: allow_yield.into(), | ||
allow_await: allow_await.into(), | ||
} | ||
} | ||
} | ||
|
||
impl TokenParser for UnaryExpression { | ||
type Output = Node; | ||
|
||
fn parse(self, cursor: &mut Cursor<'_>) -> ParseResult { | ||
let tok = cursor.next().ok_or(ParseError::AbruptEnd)?; | ||
match tok.kind { | ||
TokenKind::Keyword(Keyword::Delete) => { | ||
Ok(Node::unary_op(UnaryOp::Delete, self.parse(cursor)?)) | ||
} | ||
TokenKind::Keyword(Keyword::Void) => { | ||
Ok(Node::unary_op(UnaryOp::Void, self.parse(cursor)?)) | ||
} | ||
TokenKind::Keyword(Keyword::TypeOf) => { | ||
Ok(Node::unary_op(UnaryOp::TypeOf, self.parse(cursor)?)) | ||
} | ||
TokenKind::Punctuator(Punctuator::Add) => { | ||
Ok(Node::unary_op(UnaryOp::Plus, self.parse(cursor)?)) | ||
} | ||
TokenKind::Punctuator(Punctuator::Sub) => { | ||
Ok(Node::unary_op(UnaryOp::Minus, self.parse(cursor)?)) | ||
} | ||
TokenKind::Punctuator(Punctuator::Neg) => { | ||
Ok(Node::unary_op(UnaryOp::Tilde, self.parse(cursor)?)) | ||
} | ||
TokenKind::Punctuator(Punctuator::Not) => { | ||
Ok(Node::unary_op(UnaryOp::Not, self.parse(cursor)?)) | ||
} | ||
_ => { | ||
cursor.back(); | ||
UpdateExpression::new(self.allow_yield, self.allow_await).parse(cursor) | ||
} | ||
} | ||
} | ||
} |