Use FileMap as an input.

This commit is contained in:
강동윤 2018-01-23 21:38:48 +09:00
parent e2f75ec0a2
commit 9b2a5880bb
8 changed files with 82 additions and 66 deletions

View File

@ -7,5 +7,4 @@ authors = ["강동윤 <kdy1@outlook.kr>"]
swc_ecma_ast = { path = "./ast" }
swc_ecma_parser = { path = "./parser" }
[dev-dependencies]

View File

@ -1,5 +1,5 @@
use std::str;
use swc_common::BytePos;
use swc_common::{BytePos, FileMap};
/// Used inside lexer.
pub(super) struct LexerInput<I: Input> {
@ -8,7 +8,7 @@ pub(super) struct LexerInput<I: Input> {
input: I,
}
impl<'a, I: Input> LexerInput<I> {
impl<I: Input> LexerInput<I> {
pub const fn new(input: I) -> Self {
LexerInput {
input,
@ -57,9 +57,37 @@ impl<'a, I: Input> LexerInput<I> {
}
#[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::Item> {
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::Item> {
self.0.next().map(|(i, c)| (BytePos(i as _), c))
}
}
pub trait Input: Iterator<Item = (BytePos, char)> {
fn peek(&mut self) -> Option<(BytePos, char)>;
@ -94,23 +115,3 @@ pub trait Input: Iterator<Item = (BytePos, char)> {
where
F: FnMut(char) -> bool;
}
impl<'a, I> Input for &'a mut I
where
I: Input,
{
fn peek(&mut self) -> Option<(BytePos, char)> {
<I as Input>::peek(*self)
}
fn peek_ahead(&mut self) -> Option<(BytePos, char)> {
<I as Input>::peek_ahead(*self)
}
fn uncons_while<F>(&mut self, f: F) -> Option<&str>
where
F: FnMut(char) -> bool,
{
<I as Input>::uncons_while(self, f)
}
}

View File

@ -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<F, Ret>(s: &'static str, f: F) -> Ret
where
F: FnOnce(&mut Lexer<CharIndices>) -> Ret,
F: FnOnce(&mut Lexer<FileMapInput>) -> 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::<f64>())
.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)

View File

@ -1,14 +1,14 @@
use super::*;
use super::input::CharIndices;
use super::input::FileMapInput;
use std::ops::Range;
use std::str;
fn with_lexer<F, Ret>(s: &'static str, f: F) -> Ret
where
F: FnOnce(&mut Lexer<CharIndices>) -> Ret,
F: FnOnce(&mut Lexer<FileMapInput>) -> 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)
})
}

View File

@ -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<F, Ret>(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(),
)
}

View File

@ -81,11 +81,9 @@ impl<'a, I: Input> Parser<'a, I> {
}
#[cfg(test)]
fn test_parser<F, Ret>(s: &'static str, f: F) -> Ret
pub fn test_parser<F, Ret>(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)))
}

View File

@ -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<CodeMap>,
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(),
))
}
}

View File

@ -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<CodeMap>,
@ -35,10 +35,9 @@ impl Compiler {
/// TODO
pub fn parse_js(&self, path: &Path) -> PResult<Module> {
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()
}
}