Skip to content

Commit 893bc26

Browse files
committed
impl loop parsing for StatementListItem
1 parent 44e644d commit 893bc26

File tree

3 files changed

+89
-11
lines changed

3 files changed

+89
-11
lines changed

core/parser/src/parser/parse_loop.rs

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,12 @@ use crate::parser::statement::{StatementList, StatementListLocal, StatementListN
1010

1111
#[macro_export]
1212
macro_rules! parse_cmd {
13+
// or move into `pop_local_state!`
14+
[[POP LOCAL]: $state:ident => Empty] => {{
15+
let Ok($crate::parser::SavedState::Empty) = $state.pop_local_state() else {
16+
return Err($state.general_error(concat!("expect `Empty` saved state")))
17+
};
18+
}};
1319
// or move into `pop_local_state!`
1420
[[POP LOCAL]: $state:ident => $variant:ident] => {{
1521
let Ok($crate::parser::SavedState::$variant(ret)) = $state.pop_local_state() else {
@@ -18,10 +24,10 @@ macro_rules! parse_cmd {
1824
ret
1925
}};
2026

21-
// or move into `pop_last_node!`
27+
// or move into `pop_node!`
2228
[[POP NODE]: $state:ident => $variant:ident] => {{
2329
let Ok($crate::parser::ParsedNode::$variant(ret)) = $state.pop_node() else {
24-
return Err($state.general_error(concat!("expect `", stringify!($variant) ,"Local` saved state")))
30+
return Err($state.general_error(concat!("expect `", stringify!($variant) ,"` node")))
2531
};
2632
ret
2733
}};
@@ -31,6 +37,11 @@ macro_rules! parse_cmd {
3137
$state.push_local($crate::parser::SavedState::$variant($local));
3238
return ParseResult::Ok($crate::parser::ControlFlow::SubParse { node: Box::new($item), point: $point });
3339
}};
40+
// or move into `sub_parse!`
41+
[[SUB PARSE]: $item:expr; $state:ident <= Empty ($point:literal)] => {{
42+
$state.push_local($crate::parser::SavedState::Empty);
43+
return ParseResult::Ok($crate::parser::ControlFlow::SubParse { node: Box::new($item), point: $point });
44+
}};
3445

3546
// or move into `parse_done!`
3647
[[DONE]: $state:ident <= $variant:ident($node:expr)] => {{
@@ -56,6 +67,9 @@ impl ParseLoop {
5667
debug_assert!(!parse_stack.is_empty());
5768
debug_assert_eq!(continue_points.len(), parse_stack.len());
5869

70+
// SAFETY:
71+
// we push (entry, 0) on first iteration & it will pop only on
72+
// last `ControlFlow::Done` after which this fuction returns
5973
let continue_point = continue_points.pop().unwrap();
6074
let parser = parse_stack.last_mut().unwrap();
6175

@@ -170,14 +184,23 @@ impl<'a, R: ReadChar> ParseState<'a, R> {
170184
pub(super) fn peek(&mut self, skip_n: usize) -> ParseResult<Option<&Token>> {
171185
self.cursor.peek(skip_n, &mut self.interner)
172186
}
187+
188+
/// Check if the peeked token is a line terminator.
189+
pub(super) fn peek_is_line_terminator(&mut self, skip_n: usize) -> ParseResult<Option<bool>> {
190+
self.cursor.peek_is_line_terminator(skip_n, &mut self.interner)
191+
}
192+
173193
}
174194

175195
pub(super) enum ParsedNode {
176196
Empty,
177197
StatementListItem(ast::StatementListItem),
178198
StatementList(StatementListNode),
199+
Declaration(ast::Declaration),
200+
Statement(ast::Statement),
179201
}
180202

181203
pub(super) enum SavedState {
204+
Empty,
182205
StatementList(StatementListLocal),
183206
}

core/parser/src/parser/statement/declaration/mod.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,10 +23,7 @@ pub(in crate::parser) use self::{
2323
lexical::{allowed_token_after_let, LexicalDeclaration},
2424
};
2525
use crate::{
26-
lexer::TokenKind,
27-
parser::{AllowAwait, AllowYield, Cursor, OrAbrupt, ParseResult, TokenParser},
28-
source::ReadChar,
29-
Error,
26+
lexer::TokenKind, parse_cmd, parser::{parse_loop::ParseState, AllowAwait, AllowYield, ControlFlow, Cursor, OrAbrupt, ParseResult, TokenLoopParser, TokenParser}, source::ReadChar, Error
3027
};
3128
use boa_ast::{self as ast, Keyword};
3229
use boa_interner::{Interner, Sym};
@@ -93,6 +90,14 @@ where
9390
}
9491
}
9592

93+
impl<R: ReadChar> TokenLoopParser<R> for Declaration {
94+
fn parse_loop(&mut self, state: &mut ParseState<'_, R>, _continue_point: usize) -> ParseResult<ControlFlow<R>> {
95+
let (cursor, interner) = state.mut_inner();
96+
let ok = self.parse(cursor, interner)?;
97+
parse_cmd!([DONE]: state <= Declaration(ok))
98+
}
99+
}
100+
96101
/// Parses a `from` clause.
97102
///
98103
/// More information:

core/parser/src/parser/statement/mod.rs

Lines changed: 55 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ use self::{
4040
};
4141
use crate::{
4242
lexer::{token::EscapeSequence, Error as LexError, InputElement, Token, TokenKind}, parse_cmd, parser::{
43-
expression::{BindingIdentifier, Initializer, PropertyName}, parse_loop::ParseState, AllowAwait, AllowReturn, AllowYield, ControlFlow, Cursor, OrAbrupt, ParseResult, TokenLoopParser, TokenParser
43+
expression::{BindingIdentifier, Initializer, PropertyName}, parse_loop::ParseState, AllowAwait, AllowReturn, AllowYield, ControlFlow, Cursor, OrAbrupt, ParseResult, ParsedNode, TokenLoopParser, TokenParser
4444
}, source::ReadChar, Error
4545
};
4646
use ast::{
@@ -222,6 +222,14 @@ where
222222
}
223223
}
224224

225+
impl<R: ReadChar> TokenLoopParser<R> for Statement {
226+
fn parse_loop(&mut self, state: &mut ParseState<'_, R>, _continue_point: usize) -> ParseResult<ControlFlow<R>> {
227+
let (cursor, interner) = state.mut_inner();
228+
let ok = self.parse(cursor, interner)?;
229+
parse_cmd!([DONE]: state <= Statement(ok))
230+
}
231+
}
232+
225233
/// Reads a list of statements.
226234
///
227235
/// More information:
@@ -603,10 +611,52 @@ impl<R> TokenLoopParser<R> for StatementListItem
603611
where
604612
R: ReadChar,
605613
{
606-
fn parse_loop(&mut self, state: &mut ParseState<'_, R>, _continue_point: usize) -> ParseResult<ControlFlow<R>> {
607-
let (cursor, interner) = state.mut_inner();
608-
let ok = self.parse(cursor, interner)?;
609-
parse_cmd!([DONE]: state <= StatementListItem(ok))
614+
fn parse_loop(&mut self, state: &mut ParseState<'_, R>, continue_point: usize) -> ParseResult<ControlFlow<R>> {
615+
if continue_point == 1 {
616+
parse_cmd![[POP LOCAL]: state => Empty];
617+
match state.pop_node()? {
618+
ParsedNode::Declaration(decl) => {
619+
parse_cmd![[DONE]: state <= StatementListItem(ast::StatementListItem::from(decl))]
620+
}
621+
ParsedNode::Statement(stmt) => {
622+
parse_cmd![[DONE]: state <= StatementListItem(ast::StatementListItem::from(stmt))]
623+
}
624+
_ => return Err(state.general_error(concat!("expect `Declaration` or `Statement` node")))
625+
}
626+
} else if continue_point > 1 {
627+
return state.continue_point_error(continue_point)
628+
}
629+
630+
let tok = state.peek(0).or_abrupt()?;
631+
632+
let decl = Declaration::new(self.allow_yield, self.allow_await);
633+
let stmt = Statement::new(self.allow_yield, self.allow_await, self.allow_return);
634+
635+
match tok.kind().clone() {
636+
TokenKind::Keyword((Keyword::Function | Keyword::Class | Keyword::Const, _)) => {
637+
parse_cmd![[SUB PARSE]: decl; state <= Empty (1)]
638+
}
639+
TokenKind::Keyword((Keyword::Let, false)) if allowed_token_after_let(state.peek(1)?) => {
640+
parse_cmd![[SUB PARSE]: decl; state <= Empty (1)]
641+
}
642+
TokenKind::Keyword((Keyword::Async, false)) => {
643+
let skip_n = if state.peek_is_line_terminator(0).or_abrupt()? {
644+
2
645+
} else {
646+
1
647+
};
648+
649+
let is_line_terminator = state.peek_is_line_terminator(skip_n)?.unwrap_or(true);
650+
651+
match state.peek(1)?.map(Token::kind) {
652+
Some(TokenKind::Keyword((Keyword::Function, _))) if !is_line_terminator => {
653+
parse_cmd![[SUB PARSE]: decl; state <= Empty (1)]
654+
}
655+
_ => parse_cmd![[SUB PARSE]: stmt; state <= Empty (1)]
656+
}
657+
}
658+
_ => parse_cmd![[SUB PARSE]: stmt; state <= Empty (1)]
659+
}
610660
}
611661
}
612662

0 commit comments

Comments
 (0)