2018-11-18 08:00:07 +03:00
//! es2019 parser
//!
//! # Features
//!
//! ## Heavily tested
//!
//! Passes almost all tests from [tc39/test262][].
//!
//! ## Error reporting
//!
//! ```sh
//! error: 'implements', 'interface', 'let', 'package', 'private', 'protected', 'public', 'static', or 'yield' cannot be used as an identifier in strict mode
//! --> invalid.js:3:10
//! |
//! 3 | function yield() {
//! | ^^^^^
//! ```
//!
//! # Example
//!
//! ```
//! #[macro_use]
//! extern crate swc_common;
//! extern crate swc_ecma_parser;
//! use swc_common::{
//! errors::{ColorConfig, Handler},
//! sync::Lrc,
//! FileName, FilePathMapping, SourceMap,
//! };
2018-12-30 05:57:27 +03:00
//! use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax};
2018-11-18 08:00:07 +03:00
//!
//! fn main() {
//! swc_common::GLOBALS.set(&swc_common::Globals::new(), || {
//! let cm = Lrc::new(SourceMap::new(FilePathMapping::empty()));
//! let handler =
//! Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone()));
//!
//! let session = Session {
//! handler: &handler,
//! cfg: Default::default(),
//! };
//!
//! // Real usage
//! // let fm = cm
//! // .load_file(Path::new("test.js"))
//! // .expect("failed to load test.js");
//!
//! let fm = cm.new_source_file(
//! FileName::Custom("test.js".into()),
//! "function foo() {}".into(),
//! );
//!
2018-12-30 05:57:27 +03:00
//! let mut parser = Parser::new(session, Syntax::Es2019, SourceFileInput::from(&*fm));
2018-11-18 08:00:07 +03:00
//!
//! let _module = parser.parse_module().expect("failed to parser module");
//! });
//! }
//! ```
//!
//!
//! [tc39/test262]:https://github.com/tc39/test262
2018-01-12 10:53:06 +03:00
#![ feature(box_syntax) ]
#![ feature(box_patterns) ]
#![ feature(const_fn) ]
#![ feature(specialization) ]
#![ feature(never_type) ]
#![ feature(try_from) ]
#![ feature(try_trait) ]
2018-12-21 10:54:36 +03:00
#![ cfg_attr(test, feature(test)) ]
2018-01-12 10:53:06 +03:00
#![ deny(unreachable_patterns) ]
#![ deny(unsafe_code) ]
extern crate either ;
2018-12-21 10:54:36 +03:00
#[ macro_use ]
extern crate smallvec ;
2018-11-17 10:38:23 +03:00
extern crate swc_ecma_parser_macros as parser_macros ;
2018-01-12 10:53:06 +03:00
#[ macro_use ]
2018-12-21 10:54:36 +03:00
extern crate log ;
2018-01-12 10:53:06 +03:00
#[ macro_use(js_word) ]
2018-11-17 04:02:40 +03:00
extern crate swc_atoms ;
2018-11-17 10:38:23 +03:00
extern crate enum_kind ;
2018-12-30 05:57:27 +03:00
extern crate regex ;
2018-11-17 04:02:40 +03:00
extern crate swc_common ;
2018-12-30 05:57:27 +03:00
#[ macro_use ]
extern crate lazy_static ;
2018-11-17 04:02:40 +03:00
extern crate swc_ecma_ast as ast ;
2018-01-12 10:53:06 +03:00
#[ macro_use ]
2018-12-30 05:57:27 +03:00
#[ cfg(test) ]
2018-01-12 10:53:06 +03:00
extern crate testing ;
2018-12-21 10:54:36 +03:00
#[ cfg(test) ]
2018-12-30 05:57:27 +03:00
extern crate env_logger ;
#[ cfg(test) ]
2018-12-21 10:54:36 +03:00
extern crate test ;
2018-01-12 10:53:06 +03:00
extern crate unicode_xid ;
2018-09-16 14:25:41 +03:00
pub use self ::{
lexer ::input ::{ Input , SourceFileInput } ,
parser ::* ,
} ;
2018-01-22 04:45:08 +03:00
use swc_common ::errors ::Handler ;
2018-01-12 10:53:06 +03:00
#[ macro_use ]
mod macros ;
2018-01-22 04:45:08 +03:00
mod error ;
2018-01-21 11:47:37 +03:00
mod lexer ;
mod parser ;
2018-06-02 12:01:00 +03:00
mod token ;
2018-01-21 11:47:37 +03:00
2018-12-30 05:57:27 +03:00
#[ derive(Debug, Clone, Copy, PartialEq, Eq) ]
pub enum Syntax {
Es2019 ,
Jsx ,
Typescript ,
Tsx ,
}
impl Syntax {
/// Should we pare jsx?
pub fn jsx ( self ) -> bool {
match self {
Syntax ::Jsx | Syntax ::Tsx = > true ,
_ = > false ,
}
}
}
2018-01-21 11:47:37 +03:00
#[ derive(Debug, Clone, Copy, PartialEq, Eq, Default) ]
pub struct Config {
/// Support numeric separator.
pub num_sep : bool ,
/// Support function bind expression.
pub fn_bind : bool ,
2018-01-26 15:53:30 +03:00
}
2018-01-21 11:47:37 +03:00
2018-01-26 15:53:30 +03:00
/// Syntatic context.
#[ derive(Debug, Clone, Copy, Default) ]
struct Context {
2018-01-21 11:47:37 +03:00
/// Is in module code?
2018-01-26 15:53:30 +03:00
module : bool ,
strict : bool ,
include_in_expr : bool ,
/// If true, await expression is parsed, and "await" is treated as a
/// keyword.
in_async : bool ,
/// If true, yield expression is parsed, and "yield" is treated as a
/// keyword.
in_generator : bool ,
in_function : bool ,
in_parameters : bool ,
2018-12-30 05:57:27 +03:00
in_forced_jsx_context : bool ,
2018-01-21 11:47:37 +03:00
}
2018-01-22 04:45:08 +03:00
#[ derive(Clone, Copy) ]
2018-01-21 11:47:37 +03:00
pub struct Session < ' a > {
pub cfg : Config ,
2018-01-22 04:45:08 +03:00
pub handler : & ' a Handler ,
}
#[ cfg(test) ]
2018-11-17 06:30:49 +03:00
fn with_test_sess < F , Ret > ( src : & 'static str , f : F ) -> Result < Ret , ::testing ::StdErr >
2018-01-22 04:45:08 +03:00
where
2018-11-17 06:30:49 +03:00
F : FnOnce ( Session , SourceFileInput ) -> Result < Ret , ( ) > ,
2018-01-22 04:45:08 +03:00
{
2018-11-17 06:30:49 +03:00
use swc_common ::FileName ;
2018-01-23 15:38:48 +03:00
2018-12-21 10:54:36 +03:00
::testing ::run_test ( | cm , handler | {
2018-11-17 06:30:49 +03:00
let fm = cm . new_source_file ( FileName ::Real ( " testing " . into ( ) ) , src . into ( ) ) ;
2018-01-23 15:38:48 +03:00
2018-11-17 06:30:49 +03:00
f (
Session {
handler : & handler ,
cfg : Default ::default ( ) ,
} ,
( & * fm ) . into ( ) ,
)
} )
2018-01-21 11:47:37 +03:00
}