usecrate::queue_stack::QueueStack; usecrate::simulator::Simulator; use ast::arena; use ast::SourceLocation; use generated_parser::{
full_actions, AstBuilder, AstBuilderDelegate, ErrorCode, ParseError, ParserTrait, Result,
StackValue, TermValue, TerminalId, Token, TABLES,
}; use json_log::json_trace;
pubstruct Parser<'alloc> { /// Vector of states visited in the LR parse table.
state_stack: Vec<usize>, /// Stack and Queue of terms and their associated values. The Queue /// corresponds to terms which are added as lookahead as well as terms which /// are replayed, and the stack matches the state_stack.
node_stack: QueueStack<TermValue<StackValue<'alloc>>>, /// Build the AST stored in the TermValue vectors.
handler: AstBuilder<'alloc>,
}
pubfn write_token(&mutself, token: arena::Box<'alloc, Token>) -> Result<'alloc, ()> {
json_trace!({ "method": "write_token", "is_on_new_line": token.is_on_new_line, "start": token.loc.start, "end": token.loc.end,
}); // Shift the token with the associated StackValue. let term = token.terminal_id.into(); let accept = self.shift(TermValue {
term,
value: StackValue::Token(token),
})?; // JavaScript grammar accepts empty inputs, therefore we can never // accept any program before receiving a TerminalId::End.
assert!(!accept);
Ok(())
}
pubfn close(&mutself, position: usize) -> Result<'alloc, StackValue<'alloc>> { // Shift the End terminal with the associated StackValue.
json_trace!({ "method": "close", "position": position,
}); let loc = SourceLocation::new(position, position); let token = Token::basic_token(TerminalId::End, loc); let accept = self.shift(TermValue {
term: TerminalId::End.into(),
value: StackValue::Token(self.handler.alloc(token)),
})?; // Adding a TerminalId::End would either lead to a parse error, or to // accepting the current input. In which case we return matching node // value.
assert!(accept);
// We can either reduce a Script/Module, or a Script/Module followed by // an <End> terminal.
assert!(self.node_stack.stack_len() >= 1);
assert!(self.node_stack.stack_len() <= 2); ifself.node_stack.stack_len() > 1 { self.node_stack.pop();
}
Ok(self.node_stack.pop().unwrap().value)
}
fn try_error_handling(&mutself, t: TermValue<StackValue<'alloc>>) -> Result<'alloc, bool> {
json_trace!({ "try_error_handling_term": format!("{}", { let s: &'static str = t.term.into();
s
}),
}); iflet StackValue::Token(ref token) = t.value { // Error tokens might them-self cause more errors to be reported. // This happens due to the fact that the ErrorToken can be replayed, // and while the ErrorToken might be in the lookahead rules, it // might not be in the shifted terms coming after the reduced // nonterminal. if t.term == TerminalId::ErrorToken.into() { return Err(Self::parse_error(token).into());
}
// Otherwise, check if the current rule accept an Automatic // Semi-Colon insertion (ASI). let state = self.state();
assert!(state < TABLES.shift_count); let error_code = TABLES.error_codes[state]; iflet Some(error_code) = error_code { let err_token = (*token).clone(); Self::recover(token, error_code)?; self.replay(t); let err_token = self.handler.alloc(err_token); self.replay(TermValue {
term: TerminalId::ErrorToken.into(),
value: StackValue::Token(err_token),
}); return Ok(false);
} // On error, don't attempt error handling again. return Err(Self::parse_error(token).into());
}
Err(ParseError::ParserCannotUnpackToken.into())
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.