From 9b2a5880bb687973290281870822b21250ea36de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Tue, 23 Jan 2018 21:38:48 +0900 Subject: [PATCH] Use FileMap as an input. --- ecmascript/Cargo.toml | 1 - ecmascript/parser/src/lexer/input.rs | 63 ++++++++++++++------------- ecmascript/parser/src/lexer/number.rs | 11 +++-- ecmascript/parser/src/lexer/tests.rs | 8 ++-- ecmascript/parser/src/lib.rs | 29 ++++++++---- ecmascript/parser/src/parser/mod.rs | 8 ++-- ecmascript/parser/tests/test262.rs | 19 +++++--- swc/src/lib.rs | 9 ++-- 8 files changed, 82 insertions(+), 66 deletions(-) diff --git a/ecmascript/Cargo.toml b/ecmascript/Cargo.toml index a3022e29d41..296b80e0a2e 100644 --- a/ecmascript/Cargo.toml +++ b/ecmascript/Cargo.toml @@ -7,5 +7,4 @@ authors = ["강동윤 "] swc_ecma_ast = { path = "./ast" } swc_ecma_parser = { path = "./parser" } - [dev-dependencies] diff --git a/ecmascript/parser/src/lexer/input.rs b/ecmascript/parser/src/lexer/input.rs index a82b37641e0..38f912d6e67 100644 --- a/ecmascript/parser/src/lexer/input.rs +++ b/ecmascript/parser/src/lexer/input.rs @@ -1,5 +1,5 @@ use std::str; -use swc_common::BytePos; +use swc_common::{BytePos, FileMap}; /// Used inside lexer. pub(super) struct LexerInput { @@ -8,7 +8,7 @@ pub(super) struct LexerInput { input: I, } -impl<'a, I: Input> LexerInput { +impl LexerInput { pub const fn new(input: I) -> Self { LexerInput { input, @@ -57,9 +57,37 @@ impl<'a, I: Input> LexerInput { } #[derive(Debug, Clone)] -pub struct CharIndices<'a>(pub str::CharIndices<'a>); +pub struct FileMapInput<'a> { + fm: &'a FileMap, + start_pos: BytePos, + iter: str::CharIndices<'a>, +} -impl<'a> Input for CharIndices<'a> { +impl<'a> From<&'a FileMap> for FileMapInput<'a> { + fn from(fm: &'a FileMap) -> Self { + let src = match fm.src { + Some(ref s) => s, + None => unreachable!("Cannot lex filemap without source: {}", fm.name), + }; + + FileMapInput { + start_pos: fm.start_pos, + iter: src.char_indices(), + fm, + } + } +} + +impl<'a> Iterator for FileMapInput<'a> { + type Item = (BytePos, char); + + fn next(&mut self) -> Option { + self.iter + .next() + .map(|(i, c)| (BytePos(i as u32 + self.start_pos.0), c)) + } +} +impl<'a> Input for FileMapInput<'a> { fn peek(&mut self) -> Option<(BytePos, char)> { self.clone().nth(0) } @@ -75,13 +103,6 @@ impl<'a> Input for CharIndices<'a> { None } } -impl<'a> Iterator for CharIndices<'a> { - type Item = (BytePos, char); - - fn next(&mut self) -> Option { - self.0.next().map(|(i, c)| (BytePos(i as _), c)) - } -} pub trait Input: Iterator { fn peek(&mut self) -> Option<(BytePos, char)>; @@ -94,23 +115,3 @@ pub trait Input: Iterator { where F: FnMut(char) -> bool; } - -impl<'a, I> Input for &'a mut I -where - I: Input, -{ - fn peek(&mut self) -> Option<(BytePos, char)> { - ::peek(*self) - } - - fn peek_ahead(&mut self) -> Option<(BytePos, char)> { - ::peek_ahead(*self) - } - - fn uncons_while(&mut self, f: F) -> Option<&str> - where - F: FnMut(char) -> bool, - { - ::uncons_while(self, f) - } -} diff --git a/ecmascript/parser/src/lexer/number.rs b/ecmascript/parser/src/lexer/number.rs index a85aba78e47..cce037567fa 100644 --- a/ecmascript/parser/src/lexer/number.rs +++ b/ecmascript/parser/src/lexer/number.rs @@ -267,16 +267,16 @@ impl<'a, I: Input> Lexer<'a, I> { #[cfg(test)] mod tests { use super::*; - use lexer::input::CharIndices; + use super::input::FileMapInput; use std::f64::INFINITY; use std::panic; fn lex(s: &'static str, f: F) -> Ret where - F: FnOnce(&mut Lexer) -> Ret, + F: FnOnce(&mut Lexer) -> Ret, { - ::with_test_sess(s, |sess| { - let mut l = Lexer::new(sess, CharIndices(s.char_indices())); + ::with_test_sess(s, |sess, fm| { + let mut l = Lexer::new(sess, fm.into()); f(&mut l) }) } @@ -369,9 +369,8 @@ mod tests { .or_else(|_| case.parse::()) .expect("failed to parse `expected` as float using str.parse()"); - let input = CharIndices(case.char_indices()); let vec = panic::catch_unwind(|| { - ::with_test_sess(case, |mut sess| { + ::with_test_sess(case, |mut sess, input| { sess.cfg.strict = strict; Lexer::new(sess, input) .map(|ts| ts.token) diff --git a/ecmascript/parser/src/lexer/tests.rs b/ecmascript/parser/src/lexer/tests.rs index 5896a88f2d0..8359e1977b5 100644 --- a/ecmascript/parser/src/lexer/tests.rs +++ b/ecmascript/parser/src/lexer/tests.rs @@ -1,14 +1,14 @@ use super::*; -use super::input::CharIndices; +use super::input::FileMapInput; use std::ops::Range; use std::str; fn with_lexer(s: &'static str, f: F) -> Ret where - F: FnOnce(&mut Lexer) -> Ret, + F: FnOnce(&mut Lexer) -> Ret, { - ::with_test_sess(s, |sess| { - let mut l = Lexer::new(sess, CharIndices(s.char_indices())); + ::with_test_sess(s, |sess, fm| { + let mut l = Lexer::new(sess, fm); f(&mut l) }) } diff --git a/ecmascript/parser/src/lib.rs b/ecmascript/parser/src/lib.rs index 6712dad0a99..eee894ccf89 100644 --- a/ecmascript/parser/src/lib.rs +++ b/ecmascript/parser/src/lib.rs @@ -25,7 +25,7 @@ pub extern crate swc_macros; #[macro_use] extern crate testing; extern crate unicode_xid; -pub use self::lexer::input::{CharIndices, Input}; +pub use self::lexer::input::{FileMapInput, Input}; pub use self::parser::*; use slog::Logger; use swc_common::errors::Handler; @@ -61,19 +61,30 @@ pub struct Session<'a> { #[cfg(test)] fn with_test_sess(src: &'static str, f: F) -> Ret where - F: FnOnce(Session) -> Ret, + F: FnOnce(Session, FileMapInput) -> Ret, { + use std::rc::Rc; + use swc_common::FileName; + use swc_common::errors::{CodeMap, FilePathMapping}; + + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); + let fm = cm.new_filemap(FileName::Real("testing".into()), src.into()); + let handler = ::swc_common::errors::Handler::with_tty_emitter( - ::swc_common::errors::ColorConfig::Never, + ::swc_common::errors::ColorConfig::Auto, true, false, - None, + Some(cm), ); + let logger = ::testing::logger().new(o!("src" => src)); - f(Session { - handler: &handler, - logger: &logger, - cfg: Default::default(), - }) + f( + Session { + handler: &handler, + logger: &logger, + cfg: Default::default(), + }, + (&*fm).into(), + ) } diff --git a/ecmascript/parser/src/parser/mod.rs b/ecmascript/parser/src/parser/mod.rs index df1a03f1173..b8e466f054f 100644 --- a/ecmascript/parser/src/parser/mod.rs +++ b/ecmascript/parser/src/parser/mod.rs @@ -81,11 +81,9 @@ impl<'a, I: Input> Parser<'a, I> { } #[cfg(test)] -fn test_parser(s: &'static str, f: F) -> Ret +pub fn test_parser(s: &'static str, f: F) -> Ret where - F: FnOnce(&mut Parser<::CharIndices>) -> Ret, + F: FnOnce(&mut Parser<::FileMapInput>) -> Ret, { - ::with_test_sess(s, |session| { - f(&mut Parser::new(session, ::CharIndices(s.char_indices()))) - }) + ::with_test_sess(s, |sess, input| f(&mut Parser::new(sess, input))) } diff --git a/ecmascript/parser/tests/test262.rs b/ecmascript/parser/tests/test262.rs index b6c023ed9a2..e08c6e6407c 100644 --- a/ecmascript/parser/tests/test262.rs +++ b/ecmascript/parser/tests/test262.rs @@ -16,11 +16,13 @@ use std::fs::read_dir; use std::io::{self, Read}; use std::panic::{catch_unwind, resume_unwind}; use std::path::Path; +use std::rc::Rc; use swc_common::{FoldWith, Folder}; +use swc_common::FileName; use swc_common::Span; +use swc_common::errors::{CodeMap, FilePathMapping}; use swc_common::errors::Handler; - -use swc_ecma_parser::{CharIndices, PResult, Parser, Session}; +use swc_ecma_parser::{FileMapInput, PResult, Parser, Session}; use swc_ecma_parser::ast::*; use test::{test_main, Options, TestDesc, TestDescAndFn, TestFn, TestName}; use test::ShouldPanic::No; @@ -179,19 +181,23 @@ fn logger(file_name: &str, src: &str) -> Logger { } struct TestSess { + cm: Rc, handler: Handler, logger: Logger, } impl TestSess { fn new() -> Self { + let cm = Rc::new(CodeMap::new(FilePathMapping::empty())); + let handler = ::swc_common::errors::Handler::with_tty_emitter( ::swc_common::errors::ColorConfig::Never, true, false, - None, + Some(cm.clone()), ); TestSess { + cm, handler, logger: ::testing::logger(), } @@ -205,16 +211,19 @@ impl TestSess { fn with_parser<'a, F, Ret>(&'a mut self, file_name: &str, src: &str, f: F) -> PResult<'a, Ret> where - F: FnOnce(&mut Parser<'a, CharIndices>) -> PResult<'a, Ret>, + F: FnOnce(&mut Parser<'a, FileMapInput>) -> PResult<'a, Ret>, { self.logger = logger(file_name, src); + let fm = self.cm + .new_filemap(FileName::Real(file_name.into()), src.into()); + f(&mut Parser::new( Session { logger: &self.logger, handler: &self.handler, cfg: Default::default(), }, - ::CharIndices(src.char_indices()), + (&*fm).into(), )) } } diff --git a/swc/src/lib.rs b/swc/src/lib.rs index c9cbbf544c5..91934aef2a3 100644 --- a/swc/src/lib.rs +++ b/swc/src/lib.rs @@ -7,9 +7,9 @@ pub extern crate swc_macros; use slog::Logger; use std::path::Path; use std::rc::Rc; -use swc_common::errors::{CodeMap, FilePathMapping, Handler}; +use swc_common::errors::{CodeMap, Handler}; use swc_ecmascript::ast::Module; -use swc_ecmascript::parser::{CharIndices, PResult, Parser, Session as ParseSess}; +use swc_ecmascript::parser::{FileMapInput, PResult, Parser, Session as ParseSess}; pub struct Compiler { codemap: Rc, @@ -35,10 +35,9 @@ impl Compiler { /// TODO pub fn parse_js(&self, path: &Path) -> PResult { - let file = self.codemap + let fm = self.codemap .load_file_and_lines(path) .expect("failed to load file"); - let src = file.src.clone().expect("we loaded this right before"); Parser::new( ParseSess { @@ -46,7 +45,7 @@ impl Compiler { logger: &self.logger, cfg: Default::default(), }, - CharIndices(src.char_indices()), + FileMapInput::from(&*fm), ).parse_module() } }