ratel/
grammar.rs

1use owned_slice::OwnedSlice;
2use operator::OperatorKind;
3
4#[derive(Debug, PartialEq, Clone, Copy)]
5pub enum Value {
6    Undefined,
7    Null,
8    True,
9    False,
10    Number(OwnedSlice),
11    Binary(u64),
12    String(OwnedSlice),
13    RawQuasi(OwnedSlice),
14}
15
16#[derive(Debug, PartialEq, Clone)]
17pub struct Parameter {
18    pub name: OwnedSlice,
19    pub default: Option<Box<Expression>>
20}
21
22#[derive(Debug, PartialEq, Clone)]
23pub enum Expression {
24    Void,
25    This,
26    Identifier(OwnedSlice),
27    Literal(Value),
28    Template {
29        tag: Option<Box<Expression>>,
30        expressions: Vec<Expression>,
31        quasis: Vec<OwnedSlice>,
32    },
33    RegEx {
34        pattern: OwnedSlice,
35        flags: OwnedSlice
36    },
37    Array(Vec<Expression>),
38    Sequence(Vec<Expression>),
39    Object(Vec<ObjectMember>),
40    Member {
41        object: Box<Expression>,
42        property: OwnedSlice,
43    },
44    ComputedMember {
45        object: Box<Expression>,
46        property: Box<Expression>,
47    },
48    Call {
49        callee: Box<Expression>,
50        arguments: Vec<Expression>,
51    },
52    Binary {
53        parenthesized: bool,
54        operator: OperatorKind,
55        left: Box<Expression>,
56        right: Box<Expression>,
57    },
58    Prefix {
59        operator: OperatorKind,
60        operand: Box<Expression>,
61    },
62    Postfix {
63        operator: OperatorKind,
64        operand: Box<Expression>,
65    },
66    Conditional {
67        test: Box<Expression>,
68        consequent: Box<Expression>,
69        alternate: Box<Expression>,
70    },
71    ArrowFunction {
72        params: Vec<Parameter>,
73        body: Box<Statement>,
74    },
75    Function {
76        name: Option<OwnedSlice>,
77        params: Vec<Parameter>,
78        body: Vec<Statement>,
79    }
80}
81
82impl Expression {
83    pub fn binding_power(&self) -> u8 {
84        match *self {
85            Expression::Member {
86                ..
87            }
88            |
89            Expression::ArrowFunction {
90                ..
91            } => 18,
92
93            Expression::Call {
94                ..
95            } => 17,
96
97            Expression::Prefix {
98                ..
99            } => 15,
100
101            Expression::Binary {
102                ref operator,
103                ..
104            }
105            |
106            Expression::Postfix {
107                ref operator,
108                ..
109            } => operator.binding_power(),
110
111            Expression::Conditional {
112                ..
113            } => 4,
114
115            _  => 100,
116        }
117    }
118
119    #[inline]
120    pub fn binary<E: Into<Expression>>(left: E, operator: OperatorKind, right: E) -> Self {
121        Expression::Binary {
122            parenthesized: false,
123            operator: operator,
124            left: Box::new(left.into()),
125            right: Box::new(right.into()),
126        }
127    }
128
129    #[inline]
130    pub fn member<E: Into<Expression>, S: Into<OwnedSlice>>(object: E, property: S) -> Self {
131        Expression::Member {
132            object: Box::new(object.into()),
133            property: property.into(),
134        }
135    }
136
137    #[inline]
138    pub fn call<E: Into<Expression>>(callee: E, arguments: Vec<Expression>) -> Self {
139        Expression::Call {
140            callee: Box::new(callee.into()),
141            arguments: arguments,
142        }
143    }
144
145    #[inline]
146    pub fn parenthesize(mut self) -> Expression {
147        if let Expression::Binary {
148            ref mut parenthesized,
149            ..
150        } = self {
151            *parenthesized = true;
152        }
153
154        self
155    }
156
157    #[inline]
158    pub fn needs_parens(&self, bp: u8) -> bool {
159        match *self {
160            Expression::Binary {
161                ref parenthesized,
162                ref operator,
163                ..
164            } => *parenthesized && bp >= operator.binding_power(),
165            _ => false
166        }
167    }
168
169    #[inline]
170    pub fn is_allowed_as_bare_statement(&self) -> bool {
171        match *self {
172            Expression::Object(_)       => false,
173            Expression::Function { .. } => false,
174
175            _                           => true,
176        }
177    }
178}
179
180impl From<&'static str> for Expression {
181    #[inline]
182    fn from(ident: &'static str) -> Self {
183        Expression::Identifier(OwnedSlice::from_static(ident))
184    }
185}
186
187impl From<OwnedSlice> for Expression {
188    #[inline]
189    fn from(ident: OwnedSlice) -> Self {
190        Expression::Identifier(ident)
191    }
192}
193
194impl<'a> From<&'a OwnedSlice> for Expression {
195    #[inline]
196    fn from(ident: &'a OwnedSlice) -> Self {
197        Expression::Identifier(*ident)
198    }
199}
200
201#[derive(Debug, PartialEq, Clone)]
202pub enum ObjectMember {
203    Shorthand {
204        key: OwnedSlice,
205    },
206    Value {
207        key: ObjectKey,
208        value: Expression,
209    },
210    Method {
211        key: ObjectKey,
212        params: Vec<Parameter>,
213        body: Vec<Statement>,
214    },
215}
216
217#[derive(Debug, PartialEq, Clone)]
218pub enum ObjectKey {
219    Computed(Expression),
220    Literal(OwnedSlice),
221    Binary(u64),
222}
223
224#[derive(Debug, PartialEq, Clone)]
225pub enum ClassMember {
226    Constructor {
227        params: Vec<Parameter>,
228        body: Vec<Statement>,
229    },
230    Method {
231        is_static: bool,
232        key: ClassKey,
233        params: Vec<Parameter>,
234        body: Vec<Statement>,
235    },
236    Property {
237        is_static: bool,
238        key: ClassKey,
239        value: Expression,
240    }
241}
242
243#[derive(Debug, PartialEq, Clone)]
244pub enum ClassKey {
245    Computed(Expression),
246    Literal(OwnedSlice),
247    Number(OwnedSlice),
248    Binary(u64),
249}
250
251impl ClassKey {
252    #[inline]
253    pub fn is_constructor(&self) -> bool {
254        match *self {
255            ClassKey::Literal(ref name) => name.as_str() == "constructor",
256
257            _ => false
258        }
259    }
260}
261
262#[derive(Debug, PartialEq, Clone, Copy)]
263pub enum VariableDeclarationKind {
264    Var,
265    Let,
266    Const,
267}
268
269#[derive(Debug, PartialEq, Clone)]
270pub struct VariableDeclarator {
271    pub name: OwnedSlice,
272    pub value: Option<Expression>,
273}
274
275#[derive(Debug, PartialEq, Clone)]
276pub enum Statement {
277    Empty,
278    Block {
279        body: Vec<Statement>,
280    },
281    // `Transparent` is not part of the language grammar, just a helper that
282    // allows the transformer to replace a single statement with mutliple
283    // statements without messing with parent array.
284    Transparent {
285        body: Vec<Statement>,
286    },
287    Labeled {
288        label: OwnedSlice,
289        body: Box<Statement>,
290    },
291    VariableDeclaration {
292        kind: VariableDeclarationKind,
293        declarators: Vec<VariableDeclarator>,
294    },
295    Expression {
296        value: Expression
297    },
298    Return {
299        value: Option<Expression>,
300    },
301    Break {
302        label: Option<OwnedSlice>,
303    },
304    Function {
305        name: OwnedSlice,
306        params: Vec<Parameter>,
307        body: Vec<Statement>,
308    },
309    Class {
310        name: OwnedSlice,
311        extends: Option<OwnedSlice>,
312        body: Vec<ClassMember>,
313    },
314    If {
315        test: Expression,
316        consequent: Box<Statement>,
317        alternate: Option<Box<Statement>>,
318    },
319    While {
320        test: Expression,
321        body: Box<Statement>,
322    },
323    For {
324        init: Option<Box<Statement>>,
325        test: Option<Expression>,
326        update: Option<Expression>,
327        body: Box<Statement>,
328    },
329    ForIn {
330        left: Box<Statement>,
331        right: Expression,
332        body: Box<Statement>,
333    },
334    ForOf {
335        left: Box<Statement>,
336        right: Expression,
337        body: Box<Statement>,
338    },
339    Throw {
340        value: Expression
341    },
342    Try {
343        body: Box<Statement>,
344        error: OwnedSlice,
345        handler: Box<Statement>,
346    }
347}
348
349impl From<Expression> for Statement {
350    #[inline]
351    fn from(expression: Expression) -> Self {
352        Statement::Expression {
353            value: expression
354        }
355    }
356}
357
358#[derive(Debug, PartialEq)]
359pub struct Program {
360    pub source: String,
361    pub body: Vec<Statement>,
362}