typescript_ast/parser/
mod.rs1use std::{error::Error, path::Path, sync::Arc, collections::HashMap};
2
3use crate::ast::{
4 class::Class,
5 function::{Function, Param},
6 interface::Interface,
7 module::{Import, ImportAlias, Module},
8 statement::{ElseIf, Statement},
9 tstype::TsType,
10 typedefinition::{TypeBlock, TypeDefinition},
11 value::Value,
12};
13use pest::{iterators::Pair, Parser};
14use pest_derive::Parser;
15
16#[derive(Parser)]
17#[grammar = "parser/typescript.pest"] pub struct TypeScriptParser;
19
20fn parse_term(term: Pair<Rule>) -> Value {
21 let inner = term.into_inner().next().unwrap();
22
23 match inner.as_rule() {
24 Rule::Number => {
25 if let Ok(flt) = inner.as_str().parse::<f64>() {
26 Value::Number(flt)
27 } else {
28 Value::Undefined
29 }
30 }
31 Rule::False => Value::Boolean(false),
32 Rule::True => Value::Boolean(true),
33 Rule::Identifier => {
34 let names: Vec<String> = inner.as_str().split(".").map(|n| n.to_string()).collect();
35
36 Value::Identifier(names)
37 }
38 Rule::String => {
39 let data = inner.as_str();
40 Value::String(data[1..data.len() - 1].into())
41 }
42 Rule::Call => {
43 parse_call(inner)
44 }
45 _ => {
46 Value::Undefined
47 }
48 }
49}
50
51fn parse_value(expr: Pair<Rule>) -> Arc<Value> {
52 let mut inner = expr.into_inner();
53
54 let term = inner.next().unwrap();
55
56 if let Some(op) = inner.next() {
57 let term1 = inner.next().unwrap();
58 Arc::new(Value::Expression {
59 left: Arc::new(parse_term(term)),
60 op: op.as_str().into(),
61 right: Arc::new(parse_term(term1)),
62 })
63 } else {
64 Arc::new(parse_term(term))
65 }
66}
67
68fn parse_param_kind(kind: Pair<Rule>) -> Vec<TsType> {
69 let mut kinds = Vec::new();
70
71 for k in kind.into_inner() {
72 kinds.push(k.as_str().into());
73 }
74
75 kinds
76}
77
78fn parse_param(param: Pair<Rule>) -> Param {
79 let mut inner = param.into_inner();
80 let name = inner.next().unwrap();
81 let mut kinds = Vec::new();
82 let mut default = None;
83
84 while let Some(t) = inner.next() {
85 match t.as_rule() {
86 Rule::TypeIdentifiers => {
87 kinds = parse_param_kind(t);
88 }
89 Rule::Term => {
90 default = Some(parse_term(t));
91 }
92 _ => {}
93 }
94 }
95
96 Param {
97 name: name.as_str().to_string(),
98 kinds,
99 default,
100 }
101}
102
103fn parse_template_definition(tmp: Pair<Rule>) -> (String, Vec<TsType>) {
104 let mut inner = tmp.into_inner();
105
106 let name = inner.next().unwrap().as_str();
107
108 let kinds = if let Some(typedef) = inner.next() {
109 parse_param_kind(typedef)
110 }
111 else {
112 Vec::new()
113 };
114
115 (name.into(), kinds)
116}
117
118fn parse_function(func: Pair<Rule>) -> Function {
119 let mut name = None;
120 let mut params = Vec::new();
121 let mut returns = Vec::new();
122 let mut block_statements = Vec::new();
123 let mut template_args = HashMap::new();
124
125 for inner in func.into_inner() {
126 match inner.as_rule() {
127 Rule::Name => {
128 name = Some(inner.as_str().into());
129 }
130 Rule::TemplateDefinition => {
131 for p in inner.into_inner() {
132 let (name, kinds) = parse_template_definition(p);
133 template_args.insert(name, kinds);
134 }
135 }
136 Rule::FunctionDefinition => {
137 for p in inner.into_inner() {
138 match p.as_rule() {
139 Rule::ParamList => {
140 for p in p.into_inner() {
141 params.push(parse_param(p));
142 }
143 }
144 Rule::ReturnType => {
145 for r in p.into_inner() {
146 returns.push(r.as_str().into());
147 }
148 }
149 _ => {}
150 }
151 }
152 }
153 Rule::Block => {
154 for stmnt in inner.into_inner() {
155 if let Some(s) = parse_statement(stmnt) {
156 block_statements.push(s);
157 }
158 }
159 }
160 _ => {}
161 }
162 }
163
164 let f = Function {
165 name,
166 is_async: false,
167 template_args,
168 params,
169 returns,
170 block: block_statements,
171 };
172 f
173}
174
175fn parse_call(stmnt: Pair<Rule>) -> Value {
176 let mut inner = stmnt.into_inner();
177 let identifier: Vec<String> = inner
178 .next()
179 .unwrap()
180 .as_str()
181 .split(".")
182 .map(|n| n.to_string())
183 .collect();
184
185 let args = inner
186 .next()
187 .unwrap()
188 .into_inner()
189 .map(|n| parse_value(n))
190 .collect();
191
192 Value::Call { identifier, args }
193}
194
195fn parse_statement(stmnt: Pair<Rule>) -> Option<Statement> {
196 let stmnt = stmnt.into_inner().next().unwrap();
197
198 match stmnt.as_rule() {
199 Rule::Const => {
200 let mut inner = stmnt.into_inner();
201 let name = inner.next().unwrap();
202 let expr = inner.next().unwrap();
203
204 Some(Statement::Const {
205 name: name.as_str().to_string(),
206 value: parse_value(expr),
207 })
208 }
209 Rule::Let => {
210 let mut inner = stmnt.into_inner();
211 let name = inner.next().unwrap();
212 let expr = inner.next().unwrap();
213
214 Some(Statement::Let {
215 name: name.as_str().to_string(),
216 value: parse_value(expr),
217 })
218 }
219 Rule::Assign => {
220 let mut inner = stmnt.into_inner();
221 let name = inner.next().unwrap();
222 let expr = inner.next().unwrap();
223
224 Some(Statement::Assign {
225 identifier: name.as_str().to_string(),
226 value: parse_value(expr),
227 })
228 }
229 Rule::If => {
230 let mut inner = stmnt.into_inner();
231 let expr = inner.next().unwrap();
232 let block = inner.next().unwrap();
233
234 let mut block_stmnts = Vec::new();
235 for stmnt in block.into_inner() {
236 if let Some(s) = parse_statement(stmnt) {
237 block_stmnts.push(s);
238 }
239 }
240
241 let mut else_block = Vec::new();
242 let mut elseifs = Vec::new();
243 for next in inner {
244 match next.as_rule() {
245 Rule::ElseIf => {
246 let mut inner = next.into_inner();
247 let expr = inner.next().unwrap();
248 let block = inner.next().unwrap();
249
250 let mut block_statements = Vec::new();
251 for stmnt in block.into_inner() {
252 if let Some(s) = parse_statement(stmnt) {
253 block_statements.push(s);
254 }
255 }
256
257 elseifs.push(ElseIf {
258 expr: parse_value(expr),
259 block: block_statements,
260 });
261 }
262 Rule::Else => {
263 let block = next.into_inner().next().unwrap();
264 for stmnt in block.into_inner() {
265 if let Some(s) = parse_statement(stmnt) {
266 else_block.push(s);
267 }
268 }
269 }
270 _ => {}
271 }
272 }
273
274 Some(Statement::If {
275 expr: parse_value(expr),
276 block: block_stmnts,
277 elseifs,
278 els: else_block,
279 })
280 }
281 Rule::Function => {
282 let func = parse_function(stmnt);
283 Some(Statement::Function(func))
284 }
285 Rule::Call => Some(Statement::Call(Arc::new(parse_call(stmnt)))),
286 Rule::Return => {
287 Some(Statement::Return(parse_value(stmnt.into_inner().next().unwrap())))
288 }
289 _ => None,
290 }
291}
292
293fn parse_interface(stmnt: Pair<Rule>) -> Statement {
294 let mut inner = stmnt.into_inner();
295
296 let name = inner.next().unwrap().as_str();
297 let mut extends = None;
298 let mut attributes = Vec::new();
299 let mut methods = Vec::new();
300
301 while let Some(block) = inner.next() {
302 match block.as_rule() {
303 Rule::InterfaceExtends => {
304 let inner = block.into_inner().next().unwrap();
305 extends = Some(inner.as_str().into());
306 }
307 Rule::InterfaceBody => {
308 for part in block.into_inner() {
309 match part.as_rule() {
310 Rule::InterfaceMethod => {
311 methods.push(parse_function(part));
312 }
313 Rule::InterfaceAttribute => {
314 attributes.push(parse_param(part.into_inner().next().unwrap()));
315 }
316 _ => {}
317 }
318 }
319 }
320 _ => {}
321 }
322 }
323
324 let interface = Interface {
325 name: name.to_string(),
326 extends,
327 attributes,
328 methods,
329 };
330 Statement::Interface(interface)
331}
332
333fn parse_class(stmnt: Pair<Rule>) -> Statement {
334 let mut inner = stmnt.into_inner();
335
336 let name = inner.next().unwrap().as_str();
337 let mut extends = None;
338 let mut implements = Vec::new();
339 let mut attributes = Vec::new();
340 let mut methods = Vec::new();
341 let mut template_args = HashMap::new();
342
343 while let Some(block) = inner.next() {
344 match block.as_rule() {
345 Rule::TemplateDefinition => {
346 for inner in block.into_inner() {
347 let (name, args) = parse_template_definition(inner);
348 template_args.insert(name, args);
349 }
350 }
351 Rule::Extends => {
352 let inner = block.into_inner().next().unwrap();
353 extends = Some(inner.as_str().into());
354 }
355 Rule::Implements => {
356 for name in block.into_inner() {
357 implements.push(name.as_str().into());
358 }
359 }
360 Rule::ClassBody => {
361 for part in block.into_inner() {
362 match part.as_rule() {
363 Rule::Method => {
364 methods.push(parse_function(part));
365 }
366 Rule::ClassAttribute => {
367 attributes.push(parse_param(part.into_inner().next().unwrap()));
368 }
369 _ => {}
370 }
371 }
372 }
373 _ => {}
374 }
375 }
376
377 let class = Class {
378 name: name.to_string(),
379 extends,
380 implements,
381 attributes,
382 methods,
383 template_args,
384 };
385 Statement::Class(class)
386}
387
388fn parse_type(stmnt: Pair<Rule>) -> Statement {
389 let mut inner = stmnt.into_inner();
390
391 let name = inner.next().unwrap().as_str();
392 let mut blocks = Vec::new();
393 let mut aggregates = Vec::new();
394
395 let definitions = inner.next().unwrap().into_inner();
396 for def in definitions {
397 match def.as_rule() {
398 Rule::TypeBlock => {
399 let mut attributes = Vec::new();
400 for tuple in def.into_inner() {
401 let mut inner = tuple.into_inner();
402
403 let name = inner.next().unwrap().as_str();
404 let kind = inner.next().unwrap();
405 attributes.push(Param {
406 name: name.to_string(),
407 kinds: parse_param_kind(kind),
408 default: None,
409 });
410 }
411
412 blocks.push(TypeBlock { attributes })
413 }
414 Rule::Name => {
415 aggregates.push(def.as_str().to_string());
416 }
417 _ => {}
418 }
419 }
420
421 Statement::Type(TypeDefinition {
422 name: name.to_string(),
423 blocks,
424 aggregates,
425 })
426}
427
428pub fn file<T: AsRef<Path>>(filename: T) -> Result<Module, Box<dyn Error>> {
429 let src = std::fs::read_to_string(filename)?;
430 source(&src)
431}
432
433pub fn source(source: &str) -> Result<Module, Box<dyn Error>> {
434 let mut module = Module::new();
435 let rules = TypeScriptParser::parse(Rule::Statements, &source)?
436 .next()
437 .unwrap();
438
439 for stmnt in rules.into_inner() {
440 match stmnt.as_rule() {
441 Rule::Import => {
442 let path = stmnt.into_inner().next().unwrap();
443 let name = path.as_str();
444 let clean_name = &name[1..name.len() - 1];
445
446 module.imports.push(Import::Normal {
447 path: clean_name.to_string(),
448 });
449 }
450 Rule::ImportFrom => {
451 let mut inner = stmnt.into_inner();
452 let namelist = inner.next().unwrap();
453 let mut names = Vec::new();
454
455 for n in namelist.into_inner() {
456 let mut inner = n.into_inner();
457 let name = inner.next().unwrap();
458 let name_str = name.as_str();
459
460 if let Some(alias) = inner.next() {
461 let alias_str = alias.as_str();
462 names.push(ImportAlias::Alias {
463 name: name_str.to_string(),
464 alias: alias_str.to_string(),
465 });
466 } else {
467 names.push(ImportAlias::None {
468 name: name_str.to_string(),
469 });
470 }
471 }
472
473 let file = inner.next().unwrap();
474 let filename = file.as_str();
475
476 module.imports.push(Import::From {
477 names,
478 path: filename[1..filename.len() - 1].to_string(),
479 })
480 }
481 Rule::Interface => {
482 module.statements.push(parse_interface(stmnt));
483 }
484 Rule::Class => {
485 module.statements.push(parse_class(stmnt));
486 }
487 Rule::Type => {
488 module.statements.push(parse_type(stmnt));
489 }
490 Rule::Statement => {
491 if let Some(s) = parse_statement(stmnt) {
492 module.statements.push(s);
493 }
494 }
495 _ => {}
496 }
497 }
498
499 Ok(module)
500}