use super::*;
impl<'source, 'ast, 'name, 'names> Parser<'source, 'ast, 'name, 'names>
where
'name: 'ast,
{
pub(in crate::parser) fn new(
source: &'source [u8],
arena: &'ast AstArena,
names: &'names mut AstNameTable<'name>,
options: ParseOptions,
fragment_resume: Option<&FragmentParseResumeSettings<'ast>>,
) -> Self {
let store_cst_data = options.store_cst_data();
let base_position =
fragment_resume.map_or(Position::zero(), |settings| settings.resume_position);
let local_stack =
fragment_resume.map_or_else(Vec::new, |settings| settings.local_stack.clone());
let local_map = fragment_resume.map_or_else(
|| DenseHashMap::new(AstName::empty_key()),
|settings| settings.local_map.clone(),
);
let name_self = names.get_or_add("self");
let name_number = names.get_or_add("number");
let name_error = names.get_or_add("%error-id%");
let name_nil = names.get_or_add("nil");
let mut parser = Self {
options,
lexer: Lexer::with_position(source, names, base_position),
base_position,
arena,
current: Token::Eof,
diagnostics: DiagnosticState::default(),
comments: CommentState::new(),
cst: CstState::new(store_cst_data),
contexts: ContextState::default(),
locals: LocalState::new(local_map, local_stack),
recovery: RecoveryState::default(),
name_self,
name_number,
name_error,
name_nil,
declared_export_bindings: DenseHashMap::new(AstName::empty_key()),
has_module_return: false,
scratch_stat: ScratchVec::default(),
scratch_expr: ScratchVec::default(),
scratch_expr_aux: ScratchVec::default(),
scratch_string: ScratchVec::default(),
scratch_string2: ScratchVec::default(),
scratch_attr: ScratchVec::default(),
scratch_binding: ScratchVec::default(),
scratch_table_items: ScratchVec::default(),
scratch_cst_table_items: ScratchVec::default(),
scratch_class_members: ScratchVec::default(),
scratch_declared_extern_type_props: ScratchVec::default(),
scratch_type: ScratchVec::default(),
scratch_type_or_pack: ScratchVec::default(),
scratch_arg_name: ScratchVec::default(),
scratch_opt_arg_name: ScratchVec::default(),
scratch_generic_types: ScratchVec::default(),
scratch_generic_type_packs: ScratchVec::default(),
scratch_local: ScratchVec::default(),
scratch_table_type_props: ScratchVec::default(),
scratch_cst_table_type_items: ScratchVec::default(),
scratch_position: ScratchVec::default(),
scratch_position2: ScratchVec::default(),
};
parser.locals.stack.reserve(16);
parser.scratch_stat.reserve(16);
parser.scratch_expr.reserve(16);
parser.scratch_local.reserve(16);
parser.scratch_binding.reserve(16);
parser.advance();
parser
}
pub(in crate::parser) fn parse(
mut self,
) -> std::result::Result<ParseResult<'ast>, ParseErrors> {
static PARSE_SCOPE: OnceLock<u16> = OnceLock::new();
let _time_trace = time_trace::Scope::new(&PARSE_SCOPE, "Parser::parse", "Parser");
match self.parse_statements() {
Ok(statements) => {
if self.current.kind() != TokenKind::Eof {
let error = self.expected_eof_error();
self.report_parse_error(error);
}
if self.diagnostics.error_limit_reached
&& !self.options.no_error_limit()
&& let Some(errors) = self.take_parse_errors()
{
return Err(errors);
}
let root = self.root_block(statements);
let lines = self.source_line_count();
let (hotcomments, comment_locations) = self.comments.into_parts();
Ok(ParseResult::new(
root,
ParseMetadata::new(
lines,
hotcomments,
self.diagnostics.errors,
comment_locations,
self.cst.into_nodes(),
),
))
}
Err(error) => Err(self.finish_with_error(error)),
}
}
pub(in crate::parser) fn parse_node<T>(
mut self,
parse: impl FnOnce(&mut Self) -> Result<T>,
) -> std::result::Result<ParseNodeResult<'ast, T>, ParseErrors> {
static PARSE_SCOPE: OnceLock<u16> = OnceLock::new();
let _time_trace = time_trace::Scope::new(&PARSE_SCOPE, "Parser::parse", "Parser");
let node = match parse(&mut self) {
Ok(node) => node,
Err(error) => {
return Err(self.finish_with_error(error));
}
};
if self.current.kind() != TokenKind::Eof {
let error = ParseError::new(self.current_location(), "Expected end of file");
return Err(self.finish_with_error(error));
}
if self.diagnostics.error_limit_reached
&& !self.options.no_error_limit()
&& let Some(errors) = self.take_parse_errors()
{
return Err(errors);
}
let lines = self.source_line_count();
let (hotcomments, comment_locations) = self.comments.into_parts();
Ok(ParseNodeResult::new(
node,
ParseMetadata::new(
lines,
hotcomments,
self.diagnostics.errors,
comment_locations,
self.cst.into_nodes(),
),
))
}
fn finish_with_error(&mut self, error: ParseError) -> ParseErrors {
let fallback = error.clone();
self.report_parse_error(error);
self.take_parse_errors()
.unwrap_or_else(|| ParseErrors::single(fallback))
}
fn take_parse_errors(&mut self) -> Option<ParseErrors> {
ParseErrors::new(std::mem::take(&mut self.diagnostics.errors))
}
fn parse_statements(&mut self) -> Result<Vec<Statement<'ast>>> {
let locals_begin = self.locals.stack.len();
let mut statements = self.temp_statements();
self.parse_block_until_inner_into(BLOCK_FOLLOW, &mut statements)?;
self.restore_locals(locals_begin);
Ok(statements.as_slice().to_vec())
}
fn root_block(&mut self, statements: Vec<Statement<'ast>>) -> Block<'ast> {
let statements = self.arena.alloc_slice_copy(&statements);
let location = Location::new(self.base_position, self.current_token_location().begin);
self.arena
.alloc_block(BlockNode::new(statements, true, location))
}
}