use ress::prelude::*;
pub use ress::Span;
mod comment_handler;
mod error;
mod formal_params;
mod lexical_names;
mod lhs;
mod regex;
pub mod spanned;
pub use crate::comment_handler::CommentHandler;
pub use crate::comment_handler::DefaultCommentHandler;
pub use crate::error::Error;
use resast::prelude::*;
use std::collections::HashMap;
struct Config {
tolerant: bool,
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
enum LabelKind {
Iteration,
Other,
Unknown,
}
struct Context<'a> {
is_module: bool,
allow_in: bool,
allow_strict_directive: bool,
allow_yield: bool,
allow_await: bool,
allow_super: bool,
allow_super_call: bool,
first_covert_initialized_name_error: Option<Item<&'a str>>,
is_assignment_target: bool,
is_binding_element: bool,
in_function_body: bool,
in_iteration: bool,
in_switch: bool,
label_set: HashMap<&'a str, LabelKind>,
strict: bool,
lexical_names: lexical_names::DuplicateNameDetector<'a>,
has_line_term: bool,
past_prolog: bool,
errored: bool,
found_directive_octal_escape: bool,
}
impl Default for Config {
fn default() -> Self {
log::trace!("default config");
Self { tolerant: false }
}
}
impl<'a> Default for Context<'a> {
fn default() -> Self {
log::trace!("default context",);
Self {
is_module: false,
allow_await: true,
allow_in: true,
allow_strict_directive: true,
allow_yield: true,
allow_super: false,
allow_super_call: false,
first_covert_initialized_name_error: None,
is_assignment_target: false,
is_binding_element: false,
in_function_body: false,
in_iteration: false,
in_switch: false,
label_set: HashMap::new(),
strict: false,
lexical_names: lexical_names::DuplicateNameDetector::default(),
has_line_term: false,
past_prolog: false,
errored: false,
found_directive_octal_escape: false,
}
}
}
impl<'a> Context<'a> {
#[tracing::instrument(level = "trace", skip(self))]
pub fn set_allow_super(&mut self, value: bool) {
self.allow_super = value;
}
#[tracing::instrument(level = "trace", skip(self))]
pub fn set_is_assignment_target(&mut self, value: bool) -> bool {
let old = self.is_assignment_target;
self.is_assignment_target = value;
old
}
#[tracing::instrument(level = "trace", skip(self))]
pub fn set_is_binding_element(&mut self, value: bool) -> bool {
let old = self.is_binding_element;
self.is_binding_element = value;
old
}
}
#[derive(Default)]
pub struct Builder<'b> {
inner: crate::spanned::Builder<'b>,
}
impl<'b> Builder<'b> {
pub fn new() -> Self {
Self::default()
}
pub fn set_tolerant(&mut self, value: bool) {
self.inner.set_tolerant(value);
}
pub fn tolerant(mut self, value: bool) -> Self {
self.set_tolerant(value);
self
}
pub fn set_module(&mut self, value: bool) {
self.inner.set_module(value);
}
pub fn module(mut self, value: bool) -> Self {
self.set_module(value);
self
}
pub fn set_js(&mut self, js: &'b str) {
self.inner.set_js(js);
}
pub fn js(mut self, js: &'b str) -> Self {
self.set_js(js);
self
}
pub fn build(self) -> Res<Parser<'b, DefaultCommentHandler>> {
let inner = self.inner.build()?;
Ok(Parser { inner })
}
}
impl<'b> Builder<'b> {
pub fn with_comment_handler<CH>(self, handler: CH) -> Res<Parser<'b, CH>>
where
CH: CommentHandler<'b>,
{
let inner = self.inner.with_comment_handler(handler)?;
Ok(Parser { inner })
}
}
pub struct Parser<'a, CH> {
inner: crate::spanned::Parser<'a, CH>,
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Debug, Clone, Copy)]
pub struct Line {
start: usize,
end: usize,
}
type Res<T> = Result<T, Error>;
impl<'a> Parser<'a, DefaultCommentHandler> {
pub fn new(text: &'a str) -> Res<Self> {
let inner = crate::spanned::Parser::new(text)?;
Ok(Self { inner })
}
}
impl<'a> Parser<'a, ()> {
pub fn builder() -> Builder<'a> {
Builder::new()
}
}
impl<'b, CH> Parser<'b, CH>
where
CH: CommentHandler<'b> + Sized,
{
pub fn parse(&mut self) -> Res<Program> {
let ret = self.inner.parse()?;
Ok(ret.into())
}
pub fn next_position(&self) -> SourceLocation {
self.inner.next_position()
}
pub fn comment_handler(&self) -> &CH {
&self.inner.comment_handler
}
pub fn comment_handler_mut(&mut self) -> &mut CH {
&mut self.inner.comment_handler
}
}
impl<'b, CH> Iterator for Parser<'b, CH>
where
CH: CommentHandler<'b> + Sized,
{
type Item = Res<ProgramPart<'b>>;
fn next(&mut self) -> Option<Self::Item> {
let ret = self.inner.next()?;
Some(ret.map(Into::into))
}
}