1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
#![allow(dead_code, unused_variables)]
#![deny(non_snake_case)]
use self::{input::ParserInput, util::ParseObject};
use crate::{
error::SyntaxError,
lexer::{Input, Lexer},
parser_macros::parser,
token::{Token, Word},
Context, Session, Syntax,
};
use ast::*;
use std::ops::{Deref, DerefMut};
use swc_atoms::JsWord;
use swc_common::{comments::Comments, errors::DiagnosticBuilder, BytePos, Span};
#[macro_use]
mod macros;
mod class_and_fn;
mod expr;
mod ident;
pub mod input;
mod jsx;
mod object;
mod pat;
mod stmt;
mod typescript;
mod util;
pub type PResult<'a, T> = Result<T, DiagnosticBuilder<'a>>;
#[derive(Clone)]
pub struct Parser<'a, I: Input> {
session: Session<'a>,
state: State,
input: ParserInput<'a, I>,
}
#[derive(Clone, Default)]
struct State {
labels: Vec<JsWord>,
potential_arrow_start: Option<BytePos>,
}
#[parser]
impl<'a, I: Input> Parser<'a, I> {
pub fn new(
session: Session<'a>,
syntax: Syntax,
input: I,
comments: Option<&'a Comments>,
) -> Self {
Parser {
session,
input: ParserInput::new(Lexer::new(session, syntax, input, comments)),
state: Default::default(),
}
}
pub fn parse_script(&mut self) -> PResult<'a, Script> {
let ctx = Context {
module: false,
..self.ctx()
};
self.set_ctx(ctx);
let start = cur_pos!();
let shebang = self.parse_shebang()?;
self.parse_block_body(true, true, None).map(|body| Script {
span: span!(start),
body,
shebang,
})
}
pub fn parse_module(&mut self) -> PResult<'a, Module> {
let ctx = Context {
module: true,
strict: true,
..self.ctx()
};
self.set_ctx(ctx);
let start = cur_pos!();
let shebang = self.parse_shebang()?;
self.parse_block_body(true, true, None).map(|body| Module {
span: span!(start),
body,
shebang,
})
}
fn parse_shebang(&mut self) -> PResult<'a, Option<JsWord>> {
match cur!(false) {
Ok(&Token::Shebang(..)) => match bump!() {
Token::Shebang(v) => Ok(Some(v)),
_ => unreachable!(),
},
_ => Ok(None),
}
}
fn ctx(&self) -> Context {
self.input.get_ctx()
}
}
#[cfg(test)]
pub fn test_parser<F, Ret>(s: &'static str, syntax: Syntax, f: F) -> Ret
where
F: for<'a> FnOnce(&'a mut Parser<'a, ::SourceFileInput>) -> Result<Ret, ()>,
{
crate::with_test_sess(s, |sess, input| {
f(&mut Parser::new(sess, syntax, input, None))
})
.unwrap_or_else(|output| panic!("test_parser(): failed to parse \n{}\n{}", s, output))
}